一、攻擊原理
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 程序變得更加安全了。
2007-08-05 20:37 寫作開始
2007-08-05 21:14 第一版完成