CSRF 攻擊和防御原理
CSRF 是跨站點請求偽造 (Cross—Site Request Forgery),存在巨大的危害性,本節(jié)講解 CSRF 攻擊和防御的原理。
1. 什么是 CSRF 攻擊
CSRF 是英文 Cross Site Request Forgery 的縮寫,中文翻譯為 “跨站請求偽造”,它是一種挾制用戶在當(dāng)前已登錄的 Web 應(yīng)用程序上執(zhí)行非本意的操作的攻擊方法。
用戶使用瀏覽器登錄網(wǎng)站,通過身份驗證后,來自該瀏覽器的請求會得到授權(quán):在服務(wù)端可以執(zhí)行新增數(shù)據(jù)、修改數(shù)據(jù)、刪除數(shù)據(jù)等操作。但是,這樣的身份驗證機制存在一個漏洞:只能保證請求發(fā)自某個登錄用戶的瀏覽器,卻不能保證請求本身是用戶自愿發(fā)出的。
攻擊者利用身份驗證漏洞可以挾制用戶在當(dāng)前已登錄的 Web 應(yīng)用程序上執(zhí)行非本意的操作。
2. CSRF 攻擊的過程
2.1 案例簡介
本小節(jié)通過一個具體的例子,講解 CSRF 工具的步驟。案例的假設(shè)如下:
- 存在一個銀行網(wǎng)站,提供在線轉(zhuǎn)賬功能;
- 用戶登錄銀行后,才可以使用在線轉(zhuǎn)賬功能;
- 銀行中存在兩個賬戶:受害者賬戶、攻擊者賬戶;
- 存在一個惡意網(wǎng)站,當(dāng)訪問該惡意網(wǎng)站時,會自動向銀行網(wǎng)站提出轉(zhuǎn)賬請求。
如果受害者沒有退出銀行網(wǎng)站的情況下訪問惡意網(wǎng)站,因為受害者已經(jīng)通過了銀行網(wǎng)站的身份驗證,因此發(fā)出的轉(zhuǎn)賬請求會通過銀行網(wǎng)站的授權(quán),即攻擊者完成了攻擊。
2.2 攻擊的步驟
發(fā)動 CSRF 攻擊的步驟如下圖所示:
2.2.1 登錄
受害者使用用戶名、密碼登錄銀行網(wǎng)站。
2.2.2 驗證通過
銀行網(wǎng)站根據(jù)用戶名、密碼查詢數(shù)據(jù)庫,如果匹配,則在 Session 中記錄用戶已經(jīng)通過身份驗證。
銀行網(wǎng)站提供了轉(zhuǎn)賬的功能,在實現(xiàn)轉(zhuǎn)賬功能時,首先在 Session 中檢查是用戶是否是登錄用戶,如果是登錄用戶,則允許執(zhí)行轉(zhuǎn)賬操作;如果不是登錄用戶,則不允許執(zhí)行轉(zhuǎn)賬操作。
2.2.3 被誘導(dǎo)
攻擊者創(chuàng)辦了一個惡意網(wǎng)站,提供一些吸引人的內(nèi)容(例如:色情、賭博、盜版小說等信息),誘導(dǎo)受害者訪問惡意網(wǎng)站。
2.2.4 惡意 HTML
當(dāng)受害者訪問惡意網(wǎng)站時,惡意網(wǎng)站傳輸給受害者一段惡意的 HTML 代碼,惡意的 HTML 代碼向銀行發(fā)起轉(zhuǎn)賬請求,代碼可能如下:
<form action='http://www.bank.com/transfer' method='post'>
<input type="text" name="name" value="hacker" placeholder="收款賬戶"/>
<input type="text" name="amount" value="100" placeholder="轉(zhuǎn)賬數(shù)量"/>
<input type="submit" id="submit" value="轉(zhuǎn)賬">
</form>
<script>
var submit = document.getElementById('submit');
submit.click();
</script>
在第 1 行,定義了一個向銀行網(wǎng)站提出轉(zhuǎn)賬請求的表單,通過 POST 方法向頁面 http://www.bank.com/transfer’ 提出轉(zhuǎn)賬請求。
在第 2 行,定義了一個名稱為 ‘name’、值為 ‘hacker’ 的文本字段,表示轉(zhuǎn)賬的收款賬戶是 ‘hacker’。
在第 3 行,定義了一個名稱為 ‘a(chǎn)mount’、值為 ‘100’ 的文本字段,表示轉(zhuǎn)賬的數(shù)量是 100。
在第 8 行和第 9 行,找到提交按鈕,模擬提交按鈕的 click 操作,實現(xiàn)了自動提交表單。即:用戶瀏覽器訪問這段惡意的 HTML 代碼后,會自動向銀行網(wǎng)站發(fā)出轉(zhuǎn)賬 100 元的請求。顯然,這次轉(zhuǎn)賬不是受害者用戶的本意,是攻擊者偽造的用戶請求。
2.2.5 轉(zhuǎn)賬
受害者的瀏覽器收到惡意的 HTML 后,執(zhí)行惡意的 HTML 中的 Javascript 代碼,自動向銀行提出了一個轉(zhuǎn)賬請求。
銀行網(wǎng)站收到轉(zhuǎn)賬請求后進行處理,如果受害者沒有退出銀行網(wǎng)站的登錄,此次轉(zhuǎn)賬請求可以通過身份驗證,可以正常完成轉(zhuǎn)賬的功能。
通過以上的 5 個步驟,攻擊者成功的挾制了受害者,在當(dāng)前已登錄的銀行網(wǎng)站上執(zhí)行非本意的轉(zhuǎn)賬操作。
3. CSRF 防御的方法
在業(yè)界目前防御 CSRF 攻擊有如下策略:
3.1 驗證 HTTP Referer 字段
HTTP Referer 字段簡介
在 HTTP 請求頭里有個 Referer 字段,用于表明請求的來源地址。以向銀行發(fā)出轉(zhuǎn)賬請求為例,說明 Referer 字段。
1. 用戶正常發(fā)出轉(zhuǎn)賬請求
用戶登錄銀行網(wǎng)站成功后,在網(wǎng)站首頁 http://www.bank.com/,存在一個轉(zhuǎn)賬按鈕;用戶通過點擊頁面上的轉(zhuǎn)賬按鈕進行轉(zhuǎn)賬,向銀行發(fā)出轉(zhuǎn)賬請求
屬性 | 描述 |
---|---|
請求的地址 | http://www.bank.com/transfer |
請求的 Referer | http://www.bank.com/ |
可以看出:請求的地址和請求的 Referer 是屬于相同的域名。
2. 攻擊者通過 CSRF 攻擊發(fā)出轉(zhuǎn)賬請求
如果用戶被誘導(dǎo)進入惡意網(wǎng)站 http://www.malicious.com,在惡意網(wǎng)站的頁面中向銀行發(fā)起轉(zhuǎn)賬請求,請求的屬性如下:
屬性 | 描述 |
---|---|
請求的地址 | http://www.bank.com/transfer |
請求的 Referer | http://www.malicious.com/ |
可以看出:請求的地址和請求的 Referer 是屬于不同的域名。
3.1.2 驗證 HTTP Referer 字段
正常情況下,Referer 字段和請求的地址是位于同一域名下的。如果是 CSRF 攻擊發(fā)起的請求,那么 Referer 字段和請求的地址就不是同一域名了,因此,服務(wù)器通過驗證 HTTP Referer 字段就能識別出 CSRF 攻擊。
該方法的優(yōu)點在于:只需要給所有安全敏感的請求統(tǒng)一增加一個攔截器來檢查 Referer 的值就可以防御所有的 CSRF 攻擊;特別是對于當(dāng)前現(xiàn)有的系統(tǒng),不需要改變當(dāng)前系統(tǒng)的任何已有代碼和邏輯,沒有風(fēng)險,非常便捷。
該方法的缺點在于:攻擊者能夠篡改請求頭的 Referer 字段內(nèi)容,從而欺騙服務(wù)器;有可能無法獲取 Referer 的值,因為 Referer 值會記錄下用戶的訪問來源,有些用戶認(rèn)為這樣會侵犯到他們自己的隱私權(quán),因此,用戶自己可以設(shè)置瀏覽器使其在發(fā)送請求時不再提供 Referer。
3.2 在請求中添加 Token 并驗證
目前業(yè)界對 CSRF 的防御,流行的做法是使用一個 Token(Anti CSRF Token)。使用 Token 防御 CSRF 攻擊的步驟如下:
- 用戶訪問某個安全相關(guān)的頁面,例如銀行的轉(zhuǎn)賬頁面;
- 服務(wù)端生成一個隨機的 Token,放在用戶的 Session 中;
- 在安全相關(guān)的頁面附帶上 Token,返回給客戶端;
- 用戶提交請求后,服務(wù)端獲取兩個 Token:驗證表單中的 Token、用戶 Session 中的 Token,如果一致則為合法請求,不一致則識別為 CSRF 攻擊。
4. 小結(jié)
本節(jié)講解了 CSRF 的概念,如何實施 CSRF 攻擊以及如何防御 CSRF 攻擊,使用思維導(dǎo)圖概括如下: