CSRF
跨站域請求僞造, 通過僞裝來自受信任用戶的慶七一來利用受信任的網站
攻擊者盜用了你的身份,僞裝成你發送惡意請求。它做的事情是:以你的名義發郵件,發消息,盜取你的賬號,甚至購買商品,造成個人隱私泄密和財產安全
原理
1.登錄受信任網站A,會生成一個本地的cookie
2.在不登出A的情況下,訪問危險網站B
類型
get型的csrf
img中嵌入url的get請求,如果黑客將網址替換crsf的地址就完成攻擊了
<img src=http://wooyun.org/csrf?xx=11 />
post類型的csrf
自動提交表單
<form action=http://wooyun.org/csrf.php method=POST>
<input type="text" name="xx" value="11" />
</form>
<script> document.forms[0].submit(); </script>
防禦
1. 驗證HTTP Referer字段(referer表明來源網站)
優點: 簡單易行,普通開發人員不需要擔心csrf漏洞,只需要給所有的安全敏感請求增加一個攔截器來檢查referer的值是不是自己網站的請求
缺點: 這個方法是爲完全依賴瀏覽器的,並不安全,而且有些瀏覽器可以篡改referer值,並且referer會記錄用戶的訪問來源,有些隱私客戶並不想泄露出去,就去設置瀏覽器在發送請求的時候不提供referer值,這個時候驗證referer值並沒有用
2. 在請求地址中添加token並驗證
優點: 比referer更加安全,在http請求中以參數的形式加入一個隨機產生的token,並在服務器建立一個攔截器來驗證這個token,token在用戶登錄後產生並放入session中,然後每次請求拿出token
**缺點:**對於一些框架來說很麻煩,要手動添加,難以保證token本身的安全,黑客本身在論壇發表內容,可以發佈自己的網站,這個黑客就可以得到token,發動攻擊。這個時候可以驗證來源
3. 在HTTP頭中自定義屬性並驗證
放在http頭中自定義屬性中
防禦實例
1.驗證referer
// 從 HTTP 頭中取得 Referer 值
var referer=req.headers.Referer;
// 判斷 Referer 是否以 test.example 開頭
if((referer!=null) && (_.startsWith(referer, “test.example ”)){
// 驗證通過
}else{
// 驗證失敗,返回錯誤
}
2.驗證請求的token
var session = req.session;
// 從 session 中得到 csrftoken 屬性
var token = session.csrftoken;
if(token == null){
// 產生新的 token 放入 session 中
token = generateToken();
token.csrftoken = token ;
return ....
} else{
// 從 HTTP 頭中取得 csrftoken
var token = req.headers.csrftoken;
// 從請求參數中取得 csrftoken
var xhrToken = req.param('csrftoken');
if(token != null && xhrToken != null && token.equals(xhrToken)){
return ...
}else{
return ... // ERROR
}
}
- 自定義token
var plainXhr = dojo.xhr;
// 重寫 dojo.xhr 方法
dojo.xhr = function(method,args,hasBody) {
// 確保 header 對象存在
args.headers = args.header || {};
tokenValue = '<%=request.getSession(false).getAttribute("csrftoken")%>';
var token = dojo.getObject("tokenValue");
// 把 csrftoken 屬性放到頭中
args.headers["csrftoken"] = (token) ? token : " ";
return plainXhr(method,args,hasBody);
};