文章目錄
- Cross-Site Request Forgery
- CSRF攻擊場景
- CSRF請求僞造
-
- GET
- POST
- XMLHttpRequest
- CSRF防守政策
-
- 驗證碼
- Anti CSRF Token
- JSON Web Token
- 參考
Cross-Site Request Forgery
CSRF,Cross-Site Request Forgery,跨站請求僞造,也被稱為: XSRF, One-Click attack, Sea Surf, Session Riding, Cross-Site Reference Forgery, and Hostile Linking。
CSRF是指攻擊者通過某些技術手段欺騙使用者,盜用其已認證的身份去執行一些惡意操作(如修改使用者郵件或密碼,發消息,轉賬和購買商品)。
CSRF漏洞與浏覽器的隐式身份認證機制有關。使用者在目标網頁完成身份認證時,浏覽器會在本地(Cookie)儲存目前會話狀态資訊,當使用者再次發送請求時,浏覽器會自動攜帶該會話Cookie, 伺服器據此判斷請求來自同一使用者(會話),執行請求操作。
這時假如攻擊者成功誘使使用者打開攻擊站點,則可向目标站點發送僞造請求。由于使用者已經認證過,是以浏覽器将自動攜帶之前的會話Id,被通路網站則會認為這是使用者的真實請求而去執行。
跨站是指惡意請求是由攻擊站點發起,而不是使用者一開始通路的可信站點。由于浏覽器同源政策(Same Origin Policy)的限制,攻擊者一般無法在攻擊站點擷取使用者Cookie,而隻能通過僞造請求進行攻擊。
CSRF攻擊場景
典型場景如下:
- 使用者登入可信站點A
- 未logout的情況下通路攻擊站點B
- 攻擊站點B向站點A發送惡意請求
攻擊實作的難點是第二步,即如何讓使用者在通路A的同時剛好打開B。
常見的形式有釣魚郵件、詐騙資訊、浏覽器彈出視窗(浏覽器劫持)、漏洞站點代碼植入等。
比如你在操作網銀時,剛好看到一封銀行發送給你的(釣魚)郵件,或者剛好浏覽器彈出一個你感興趣的新聞,然後你眼疾手快地點選了裡面的連結。
攻擊站點B不一定是惡意站點,可能隻是有漏洞的普通網站,甚至是受歡迎的高流量網站。
B向A發送請求是通過技術手段自動實作。也就是說,當打開網頁時,你就中招了,并不需要任何其他操作。是以盡管使用者登入A的同時正好打開B的幾率不大,但是黑客并不需要做什麼,隻是坐等收錢,因而這肯定也是一種受歡迎的攻擊手段。
另外,大多數人都沒有完成操作就立即登出的良好習慣。
CSRF請求僞造
GET
典型例子如下,
img
的情況下不需要使用者點選連結,打開視窗便自動送出請求。
<a href="http://bank.com/transfer.do?acct=MARIA&amount=100000">View my Pictures!</a>
<img src="http://bank.com/transfer.do?acct=MARIA&amount=100000" width="0" height="0" border="0">
是以一般更新操作不要用Get,因為僞造成本太低。
POST
Post實作相對應的代碼如下。
表單當然是不顯示出來的,通常放在隐藏的iframe裡。
<form action="<nowiki>http://bank.com/transfer.do</nowiki>" method="POST">
<input type="hidden" name="acct" value="MARIA"/>
<input type="hidden" name="amount" value="100000"/>
<input type="submit" value="View my pictures"/>
</form>
<body onload="document.forms[0].submit()">
XMLHttpRequest
XMLHttpRequest方法受浏覽器同源政策限制,一般不會成功,除非目标站點定義了
Access-Control-Allow-Origin: *
。
但是,在JavaScript的世界裡,繞過同源政策的代碼卻很容易找到,更不用說各種各樣的浏覽器漏洞了。
<script>
function put() {
var x = new XMLHttpRequest();
x.open("PUT","http://bank.com/transfer.do",true);
x.setRequestHeader("Content-Type", "application/json");
x.send(JSON.stringify({"acct":"BOB", "amount":100}));
}
</script>
<body onload="put()">
CSRF防守政策
由以上分析可知,CSRF攻擊之是以能奏效,主要是因為攻擊者可以成功地僞造一個合法的請求,即目标操作的所有參數都可以被分析出來。
是以防範的政策主要是往請求中加入無法猜測的參數值,比如驗證碼和Token。
驗證碼
驗證碼是最簡單有效的方法,但是因為影響使用者體驗,不能作為主要的解決方案。
Anti CSRF Token
CSRF Token方法與驗證碼類似,隻是不需要使用者幹預。
增加一個随機生成的Token,發送給前端,前端送出表單時包含該Token,在背景驗證,驗證通過才是有效請求。
一個請求送出後,Token即被消耗掉,然後重新生成新Token。是以,也要考慮同時有多個請求時的并發處理問題。
注意:
- Token要足夠随機,不可預測。
- Token要注意保密,不能洩露。
比如頁面如果同時有XSS(跨站腳本攻擊)漏洞,則攻擊者完全可以讀出頁面的Token值,再僞造合法的請求,這一過程一般稱為XSRF,與CSRF相差別。
除了加Token,也可以考慮給參數加密,或者驗證通路來源(Referrer)。
JSON Web Token
假如我已經使用了JWT無狀态App設計,還需不需要再引入CSRF Token?
答案是:不需要。
除了不是by request生成,JWT具有CSRF Token相同的特征,因而是安全的。
總的來說,避免使用Cookie進行身份認證,應該已經可以防範大多數的CSRF漏洞。
參考
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)
《白帽子講Web安全》 —— 吳翰清
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZwpmL5MzN1MDOwETMzAzMwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)