考慮到ASP 開發可以採用vbs 和js 兩種語言,這裡同時提供兩種語言的程式碼(雙語版?YY中…)最後囉嗦一句,本人錄入這篇文章用的機器上沒有ASP 環境,所以提供的程式碼未能進行測試,對這一點本人深表歉意。如果大家發現了程式碼中的任何問題,歡迎拍磚~本人皮厚~
一、攻擊原理
Cookies 欺騙主要利用目前網路上一些使用者管理系統將使用者登入資訊儲存在Cookies 中這一不安全的做法進行攻擊,其攻擊方法相對於SQL 注入漏洞等漏洞來說相對要困難一些,但還是很傻瓜。
我們知道,一般的基於Cookies 的使用者係統至少會在Cookies 中儲存兩個變數:username 和userlevel,其中username 為使用者名,而userlevel 為使用者的等級。當我們的瀏覽器造訪ASP 頁面時,它會傳出類似
GET /.../file.asp HTTP 1.0
…
Cookies: username=user&userlevel=1
…
的資料包,那麼,我們只要知道了管理員的username 和userlevel 值(假設分別為admin 和5),便可以透過傳輸
GET /.../file.asp HTTP 1.0
…
Cookies: username=admin&userlevel=5
…
來取得管理員權限。很簡單是不是?然而,在這個漏洞被發現之前,幾乎所有的使用者管理系統都依賴Cookies。
二、安全地儲存使用者資訊
既然Cookies 是不安全的,而我們必須把使用者登入資訊儲存下來,那麼應該儲存在什麼地方呢?
我們注意到,在ASP 中,除了Cookies 外,還有Session 可以儲存資訊。 Session 是儲存在伺服器上的,不是客戶端隨便就能夠更改的,所以具有極高的安全性。這樣,大家就可以把所有Cookies 的程式碼均換作Session 了。
三、長時間儲存使用者資訊
採用Session 來保存使用者登入訊息,雖然擺脫了Cookies 欺騙的問題,但是Session 不能長期儲存(IIS 預設Session 在使用者停止回應20 分鐘後失效),於是產生了這一節所述的Cookies + Session 混合儲存法。
此方法有兩個變種,第一種是在Cookies 中儲存使用者名稱和密碼,當使用者造訪一個頁面時,先讀取Session,如果有內容則以Session 為準,否則讀取Cookies,按照Cookies 中提供的使用者名稱和密碼進行不透明的登入一次,用以判斷Cookies 中的內容是否合法,若合法再進而存入Session 中。實現這一方法的程式碼如下:
vbs:
複製代碼代碼如下:
<%
Dim username, password
username = Session(username)
if username = then
' Session 中沒有使用者登入訊息
username = Request.Cookies(username)
password = Request.Cookies(password)
' 注意上面的兩句得到的username 和password 要進行SQL 注入漏洞的防範(即過濾掉單引號'),這裡略去
if username = or password = then
' 使用者沒有登入
…
else
' 這裡假設已經創建了conn 和rs 對象
rs.Open SELECT TOP 1 * FROM [user] WHERE username=' & username & ' AND password=' & password & ', conn, 1, 3
if rs.eof then
' Cookies 中的資訊非法
…
else
' Cookies 中的資訊合法,自動登入
Session(username) = username
…
end if
end if
else
' 使用者資訊已經存在於Session 中,直接讀取
…
end if
%>
js:
複製代碼代碼如下:
<%
var username, password;
username = Session(username) + ;
if (username == || username == undefined) {
// Session 中沒有使用者訊息
username = Request.Cookies(username) + ;
password = Request.Cookies(password) + ;
// 注意上面的兩句得到的username 和password 要進行SQL 注入漏洞的防範(即過濾掉單引號'),這裡略去
if (username == || username == undefined || password == || password == undefined) {
// 使用者沒有登入
…
}
else {
// 這裡假設已經建立了conn 和rs 對象
rs.Open(SELECT TOP 1 * FROM [user] WHERE username=' + username + ' AND password=' + password + ', conn, 1, 3);
if (rs.eof) {
// Cookies 中的資訊非法
…
}
else {
// Cookies 中的資訊合法,自動登入
Session(username) = username + ;
…
}
}
}
else {
// 使用者資訊已經存在於Session 中,直接讀取
…
}
%>
但這種方法對使用者來說又不太安全,原因是瀏覽器每次造訪頁面時都會把Cookies 傳輸過去,而包含密碼的Cookies 一旦被他人取得將導致使用者帳號被盜。對於這種情況,又出現了第二種方法,即在用戶資訊資料庫中增加一個字段verifycode,在用戶登入時,隨機產生一個長整型校驗值存入verifycode 字段,並且將username 和這個verifycode 值而不是password 存入Cookies。而在驗證Cookies 中的使用者資訊時,也只驗證username 和verifycode。這種方法的好處在於,即使用戶的Cookies 被駭客獲取,他也只能利用這個臨時產生的verifycode 登錄,而無法獲得用戶的密碼。只要此用戶再一次使用使用者名稱和密碼登錄,這個verifycode 值就會改變,駭客便無法透過原來的verifycode 登錄。
這種方法的實作只需要在上述方法一的程式碼上稍加改動。首先,在您的登入程式中,在驗證透過儲存使用者資訊的地方需要加上一段:
vbs:
複製代碼代碼如下:
<%
Response.Cookies(verifycode) = int(rnd * 2100000000)
%>
js:
複製代碼代碼如下:
<%
Response.Cookies(verifycode) = Math.floor(Math.random() * 2100000000);
%>
然後,在上面提供的驗證程式碼中把Cookies(password) 的驗證改為對Cookies(verifycode) 的驗證即可。
四、結論
透過我們的分析以及處理,Cookies 欺騙漏洞已經被完全解決,從此,我們的ASP 程式變得更加安全了。