CSRF是什么丹喻?
CSRF(Cross Site Request Forgery)腾降,中文是跨站點請求偽造。CSRF攻擊者在用戶已經(jīng)登錄目標(biāo)網(wǎng)站之后俊性,誘使用戶訪問一個攻擊頁面,利用目標(biāo)網(wǎng)站對用戶的信任描扯,以用戶身份在攻擊頁面對目標(biāo)網(wǎng)站發(fā)起偽造用戶操作的請求定页,達(dá)到攻擊目的。
舉個例子
簡單版:
假如博客園有個加關(guān)注的GET接口绽诚,blogUserGuid參數(shù)很明顯是關(guān)注人Id典徊,如下:
http://www.cnblogs.com/mvc/Follow/FollowBlogger.aspx?blogUserGuid=4e8c33d0-77fe-df11-ac81-842b2b196315
那我只需要在我的一篇博文內(nèi)容里面寫一個img標(biāo)簽:
<img style="width:0;" src="http://www.cnblogs.com/mvc/Follow/FollowBlogger.aspx?blogUserGuid=4e8c33d0-77fe-df11-ac81-842b2b196315"/>
那么只要有人打開我這篇博文,那就會自動關(guān)注我恩够。
升級版:
假如博客園還是有個加關(guān)注的接口卒落,不過已經(jīng)限制了只獲取POST請求的數(shù)據(jù)。這個時候就做一個第三方的頁面蜂桶,但里面包含form提交代碼儡毕,然后通過QQ、郵箱等社交工具傳播扑媚,誘惑用戶去打開腰湾,那打開過博客園的用戶就中招了。
在說例子之前要糾正一個iframe問題疆股,有人會直接在第三方頁面這樣寫费坊。如下:
<!DOCTYPE HTML><html lang="en-US"><head><title>CSRF SHOW</title></head><body><!--不嵌iframe會跳轉(zhuǎn)--><iframe style="display:none;"><form? name="form1" action="http://www.cnblogs.com/mvc/Follow/FollowBlogger.aspx" method="post"><input type="hidden" name="blogUserGuid" value="4e8c33d0-77fe-df11-ac81-842b2b196315"/><input type="submit" value></form><script>? ? ? ? ? ? ? ? ? ? document.forms.form1.submit();
? ? ? ? ? ? ? </script></iframe></body></html>
這樣是用問題的,由于同源策略的原因旬痹,iframe內(nèi)容根本加載不出來附井,所以里面form提交當(dāng)然不會執(zhí)行。
PS:我嘗試了chrome唱凯、IE11羡忘、Firefox,情況都是這樣磕昼。
所以可以用嵌多一層頁面方式解決卷雕,如下:
第一個展示頁面(test):
<!DOCTYPE HTML><html lang="en-US"><head><title>CSRF SHOW</title></head><body><iframe style="display:none;" src="test2.html"></iframe></body></html>
第二個隱藏頁面(test2):
<!DOCTYPE HTML><html lang="en-US"><head><title>CSRF GET</title><body><form? name="form1" action="http://www.cnblogs.com/mvc/Follow/FollowBlogger.aspx" method="post"><input type="hidden" name="blogUserGuid" value="4e8c33d0-77fe-df11-ac81-842b2b196315"/><input type="submit" value></form><script>? ? ? ? ? document.forms.form1.submit();
? ? </script></body></html>
這樣就可以解決了,有人會問為什么要加多一層iframe票从,因為不嵌iframe頁面會重定向漫雕,這樣就降低了攻擊的隱蔽性。另外我們test頁面不使用XMLHTTPRequest發(fā)送POST請求峰鄙,是因為有跨域的問題浸间,而form可以跨域post數(shù)據(jù)。
進(jìn)階版:
假如博客園還是有個加關(guān)注的接口吟榴,已經(jīng)限制POST魁蒜,但博文內(nèi)容是直接貼進(jìn)HTML(未過濾),那就遭受XSS攻擊。那么就可以直接把上面代碼嵌入博文兜看,那么只要有人打開我這篇博文锥咸,還是會自動關(guān)注我,這組合攻擊方式稱為XSRF细移。
CSRF攻擊的本質(zhì)原因
CSRF攻擊是源于Web的隱式身份驗證機制搏予!Web的身份驗證機制雖然可以保證一個請求是來自于某個用戶的瀏覽器,但卻無法保證該請求是用戶批準(zhǔn)發(fā)送的弧轧。CSRF攻擊的一般是由服務(wù)端解決雪侥。
CSRF工具的防御手段
1. 盡量使用POST,限制GET
GET接口太容易被拿來做CSRF攻擊精绎,看第一個示例就知道速缨,只要構(gòu)造一個img標(biāo)簽,而img標(biāo)簽又是不能過濾的數(shù)據(jù)捺典。接口最好限制為POST使用鸟廓,GET則無效,降低攻擊風(fēng)險襟己。
當(dāng)然POST并不是萬無一失引谜,攻擊者只要構(gòu)造一個form就可以,但需要在第三方頁面做擎浴,這樣就增加暴露的可能性员咽。
2. 瀏覽器Cookie策略
IE6、7贮预、8贝室、Safari會默認(rèn)攔截第三方本地Cookie(Third-party Cookie)的發(fā)送。但是Firefox2仿吞、3滑频、Opera、Chrome唤冈、Android等不會攔截峡迷,所以通過瀏覽器Cookie策略來防御CSRF攻擊不靠譜,只能說是降低了風(fēng)險你虹。
PS:Cookie分為兩種绘搞,Session Cookie(在瀏覽器關(guān)閉后,就會失效傅物,保存到內(nèi)存里)夯辖,Third-party Cookie(即只有到了Exprie時間后才會失效的Cookie,這種Cookie會保存到本地)董饰。
PS:另外如果網(wǎng)站返回HTTP頭包含P3P Header蒿褂,那么將允許瀏覽器發(fā)送第三方Cookie圆米。
3. 加驗證碼
驗證碼,強制用戶必須與應(yīng)用進(jìn)行交互啄栓,才能完成最終請求榨咐。在通常情況下,驗證碼能很好遏制CSRF攻擊谴供。但是出于用戶體驗考慮,網(wǎng)站不能給所有的操作都加上驗證碼齿坷。因此驗證碼只能作為一種輔助手段桂肌,不能作為主要解決方案。
4. Referer Check
Referer Check在Web最常見的應(yīng)用就是“防止圖片盜鏈”永淌。同理崎场,Referer Check也可以被用于檢查請求是否來自合法的“源”(Referer值是否是指定頁面,或者網(wǎng)站的域)遂蛀,如果都不是谭跨,那么就極可能是CSRF攻擊。
但是因為服務(wù)器并不是什么時候都能取到Referer李滴,所以也無法作為CSRF防御的主要手段螃宙。但是用Referer Check來監(jiān)控CSRF攻擊的發(fā)生,倒是一種可行的方法所坯。
5. Anti CSRF Token
現(xiàn)在業(yè)界對CSRF的防御谆扎,一致的做法是使用一個Token(Anti CSRF Token)。
例子:
1. 用戶訪問某個表單頁面芹助。
2. 服務(wù)端生成一個Token堂湖,放在用戶的Session中,或者瀏覽器的Cookie中状土。
3. 在頁面表單附帶上Token參數(shù)无蜂。
4. 用戶提交請求后, 服務(wù)端驗證表單中的Token是否與用戶Session(或Cookies)中的Token一致蒙谓,一致為合法請求斥季,不是則非法請求。
這個Token的值必須是隨機的彼乌,不可預(yù)測的泻肯。由于Token的存在,攻擊者無法再構(gòu)造一個帶有合法Token的請求實施CSRF攻擊慰照。另外使用Token時應(yīng)注意Token的保密性灶挟,盡量把敏感操作由GET改為POST,以form或AJAX形式提交毒租,避免Token泄露稚铣。
注意:
CSRF的Token僅僅用于對抗CSRF攻擊箱叁。當(dāng)網(wǎng)站同時存在XSS漏洞時候,那這個方案也是空談惕医。所以XSS帶來的問題耕漱,應(yīng)該使用XSS的防御方案予以解決。
總結(jié)
CSRF攻擊是攻擊者利用用戶的身份操作用戶帳戶的一種攻擊方式抬伺,通常使用Anti CSRF Token來防御CSRF攻擊螟够,同時要注意Token的保密性和隨機性。