CSRF 跨站僞造請求

CSRF(Cross-site request forgery)跨站請求僞造,也被稱爲“One Click Attack”或者Session Riding,通常縮寫爲CSRF或者XSRF,是一種對網站的惡意利用。儘管聽起來像跨站腳本(XSS),但它與XSS非常不同,XSS利用站點內的信任用戶,而CSRF則通過僞裝來自受信任用戶的請求來利用受信任的網站。與XSS攻擊相比,CSRF攻擊往往不大流行(因此對其進行防範的資源也相當稀少)和難以防範,所以被認爲比XSS更具危險性。但往往同XSS一同作案!

CSRF可以做什麼?

你這可以這麼理解CSRF攻擊:攻擊者盜用了你的身份,以你的名義發送惡意請求。CSRF能夠做的事情包括:以你名義發送郵件,發消息,盜取你的賬號,甚至於購買商品,虛擬貨幣轉賬……造成的問題包括:個人隱私泄露以及財產安全。

CSRF漏洞現狀

CSRF這種攻擊方式在2000年已經被國外的安全人員提出,但在國內,直到06年纔開始被關注,08年,國內外的多個大型社區和交互網站分別爆出CSRF漏洞,如:NYTimes.com(紐約時報)、Metafilter(一個大型的BLOG網站),YouTube和百度HI……而現在,互聯網上的許多站點仍對此毫無防備,以至於安全業界稱CSRF爲“沉睡的巨人”。

CSRF的原理

下圖簡單闡述了CSRF攻擊的思想:
這裏寫圖片描述

從上圖可以看出,要完成一次CSRF攻擊,受害者必須依次完成兩個步驟:

  • 登錄受信任網站A,並在本地生成Cookie。
  • 在不登出A的情況下,訪問危險網站B。

看到這裏,你也許會說:“如果我不滿足以上兩個條件中的一個,我就不會受到CSRF的攻擊”。是的,確實如此,但你不能保證以下情況不會發生:

  • 你不能保證你登錄了一個網站後,不再打開一個tab頁面並訪問另外的網站。
  • 你不能保證你關閉瀏覽器了後,你本地的Cookie立刻過期,你上次的會話已經結束。(事實上,關閉瀏覽器不能結束一個會話,但大多數人都會錯誤的認爲關閉瀏覽器就等於退出登錄/結束會話了……)
  • 上圖中所謂的攻擊網站,可能是一個存在其他漏洞的可信任的經常被人訪問的網站。

舉例:

例子1:

銀行網站A,它以GET請求來完成銀行轉賬的操作

如:http://www.mybank.com/Transfe

危險網站B,它裏面有一段HTML的代碼如下:

<img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000> 

實際操作:

首先,你登錄了銀行網站A,然後訪問危險網站B,噢,這時你會發現你的銀行賬戶少了1000塊……

原因:

爲什麼會這樣呢?原因是銀行網站A違反了HTTP規範,使用GET請求更新資源。在訪問危險網站B的之前,你已經登錄了銀行網站A,而B網站以GET的方式請求第三方資源(這裏的第三方就是指銀行網站了,原本這是一個合法的請求,但這裏被不法分子利用了),所以你的瀏覽器會帶上你的銀行網站A的Cookie發出Get請求,去獲取資源

http://www.mybank.com/Transfer.php?toBankId=11&money=1000 

結果銀行網站服務器收到請求後,認爲這是一個更新資源操作(轉賬操作),所以就立刻進行轉賬操作……

例子2:

爲了杜絕上面的問題,銀行決定改用POST請求完成轉賬操作。

銀行網站A的WEB表單如下:

<form action="Transfer.php" method="POST"> 

<p>ToBankId: <input type="text" name="toBankId" /></p> 

<p>Money: <input type="text" name="money" /></p> 

<p><input type="submit" value="Transfer" /></p> 

</form> 

後臺處理頁面Transfer.php如下:

<?php 

session_start(); 

if (isset($_REQUEST['toBankId'] && isset($_REQUEST['money'])) 

{ 

   buy_stocks($_REQUEST['toBankId'], $_REQUEST['money']); 

} 

危險網站B,仍然只是包含那句HTML代碼:

<img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000> 

原因:

和示例1中的操作一樣,你首先登錄了銀行網站A,然後訪問危險網站B,結果…..和示例1一樣,你再次沒了1000塊~T_T,這次事故的原因是:銀行後臺使用了$_REQUEST去獲取請求的數據,而$_REQUEST既可以獲取GET請求的數據,也可以獲取POST請求的數據,這就造成了在後臺處理程序無法區分這到底是GET請求的數據還是POST請求的數據。在PHP中,可以使用$_GET和$_POST分別獲取GET請求和POST請求的數據。在JAVA中,用於獲取請求數據request一樣存在不能區分GET請求數據和POST數據的問題。

例3:

經過前面2個慘痛的教訓,銀行決定把獲取請求數據的方法也改了,改用$_POST,只獲取POST請求的數據,後臺處理頁面Transfer.php代碼如下:

<?php 

session_start(); 

if (isset($_POST['toBankId'] && isset($_POST['money'])) 

{ 

  buy_stocks($_POST['toBankId'], $_POST['money']); 

} 

?>  

然而,危險網站B與時俱進,它改了一下代碼:

<html> 
<head> 
<script type="text/javascript"> 
function steal() 
{ 
           iframe = document.frames["steal"]; 
           iframe.document.Submit("transfer"); 
} 
</script> 
</head> 

<body onload="steal()"> 
<iframe name="steal" display="none"> 
<form method="POST" name="transfer" action="http://www.myBank.com/Transfer.php"> 
<input type="hidden" name="toBankId" value="11"> 
<input type="hidden" name="money" value="1000"> 
</form> 
</iframe> 
</body> 
</html>  

總結:

1、上面3個例子,CSRF主要的攻擊模式基本上是以上的3種,其中以第1,2種最爲嚴重,因爲觸發條件很簡單,一個<img>就可以了,而第3種比較麻煩,需要使用JavaScript,所以使用的機會會比前面的少很多,但無論是哪種情況,只要觸發了CSRF攻擊,後果都有可能很嚴重。
2、 從上面的3種攻擊模式,可以看出,CSRF攻擊是源於WEB的隱式身份驗證機制!WEB的身份驗證機制雖然可以保證一個請求是來自於某個用戶的瀏覽器,但卻無法保證該請求是用戶批准發送的!

當前防禦 CSRF 的幾種策略

在業界目前防禦 CSRF 攻擊主要有三種策略:1、驗證 HTTP Referer 字段;2、在請求地址中添加 token 並驗證;3、在 HTTP頭中自定義屬性並驗證。

下面就分別對這三種策略進行詳細介紹:

1、驗證 HTTP Referer 字段

利用HTTP頭中的Referer判斷請求來源是否合法。
優點:

簡單易行,只需要在最後給所有安全敏感的請求統一增加一個攔截器來檢查 Referer的值就可以。特別是對於當前現有的系統,不需要改變當前系統的任何已有代碼和邏輯,沒有風險,非常便捷。

缺點:

  • 1、Referer 的值是由瀏覽器提供的,不可全信,低版本瀏覽器下Referer存在僞造風險。
  • 2、用戶自己可以設置瀏覽器使其在發送請求時不再提供 Referer時,網站將拒絕合法用戶的訪問。

2、在請求地址中添加 token 並驗證

在請求中放入黑客所不能僞造的信息,並且該信息不存在於 cookie 之中,以HTTP請求參數的形式加入一個隨機產生的 token交由服務端驗證
優點:

  • 比檢查 Referer 要安全一些,並且不涉及用戶隱私。

缺點:

  • 1、對所有請求都添加token比較困難,難以保證 token 本身的安全,依然會被利用獲取到token

解決方法:

在 HTTP 頭中自定義屬性並驗證+一次性的 Tokens:將token放到 HTTP 頭中自定義的屬性裏。通 XMLHttpRequest 的異步請求交由後端校驗,並且一次有效。

優點:

  • 統一管理token輸入輸出,可以保證token的安全性

缺點:

  • 有侷限性,無法在非異步的請求上實施
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章