CSRF/XSRF概述

概述

CSRF(Cross-site request forgery)跨站請求僞造,也被稱爲“One Click Attack”或者Session Riding,通常縮寫爲CSRF或者XSRF,一般是攻擊者冒充用戶進行站內操作,它與XSS非常不同,XSS利用站點內的信任用戶,而CSRF則是僞裝成受信任用戶的請求來訪問操作受信任的網站。

原理

CSRF攻擊經常利用目標站點的身份驗證機制,CSRF攻擊這一弱點的根源在於Web的身份驗證機制雖然可以向目標站點保證一個請求來自於經過站點認證的某個用戶的賬號,但是卻無法保證該請求的確是那個用戶發出的或者是經過那個用戶批准的。
目前web網站泛用的身份驗證機制就是cookie-session認證機制,來跟蹤記錄用戶的行爲。
CSRF攻擊依賴下面的假定:
攻擊者瞭解受害者所在的站點;
攻擊者的目標站點具有持久化授權cookie或者受害者具有當前會話cookie;
目標站點沒有對用戶在網站行爲的第二授權;
欺騙用戶的瀏覽器發送HTTP請求給目標站點(也就是忽悠用戶點擊攻擊鏈接)或者攻擊者控制部分or全部站點(比如攻擊者通過XSS拿到未失效且經過網站授權的cookie)。
參考深入解析跨站請求僞造漏洞:原理剖析
比如攻擊者編寫了一個在用戶的銀行站點上進行取款的form提交的鏈接,並將此鏈接作爲圖片src。如果用戶的銀行在cookie中保存他的授權信息,並且此cookie沒有過期,那麼當用戶的瀏覽器嘗試裝載圖片時將提交這個取款form和他的cookie,這樣在沒經用戶同意的情況下便授權了這次轉賬。
如下圖所示:
在這裏插入圖片描述常見威脅

1:通過郵件、圖片鏈接騙取用戶,如下html所示

<p>創建圖片鏈接:
<a href="http://www.w3cschool.cn/Pj/Index/getList?id=1">
<img src="http://www.baidu.com/link?url=16pic_1596549_b.jpg" alt="HTML 教程" width="32" height="32"></a></p>

含有CSRF攻擊的圖片,這種一般是get方式,有時需要提交表單,採用POST方式提交。此時構造個隱藏的HTML表單提交些數據過去就可以了。參考csrf的post攻擊

2:多窗口瀏覽器就幫了一點忙。
多窗口瀏覽器(firefox、遨遊、MyIE……)便捷的同時也帶來了一些問題,因爲多窗口瀏覽器新開的窗口是具有當前所有會話的。單窗口瀏覽器IE就不會,如我用ie登陸了我的Blog,然後我想看新聞了,又運行一個IE進程,這個時候兩個IE窗口的會話是彼此獨立的,從看新聞的IE發送請求到Blog不會有我登錄的cookie;但是多窗口瀏覽器永遠都只有一個進程,各窗口的會話是通用的,即看新聞的窗口發請求到Blog是會帶上我在blog登錄的cookie。

案例

轉載自csrf危害
案例一:

一個銀行站點存在一個csrf漏洞,用戶A轉賬給B用戶2000元,執行轉賬操作後會對銀行發送一次請求:“http://www.bank.com/money?user=A&num=2000&transfer=B”,然後A用戶就會把自己的2000元轉到B的賬戶下。在發送這個請求給銀行服務器時,服務器首先會驗證這個請求是否爲一個合法的session,並且用戶A確認登陸纔可以驗證通過。

如果此時有一個惡意用戶C想把A用戶的錢轉到自己的賬戶下,那麼他可以構造 http://www.bank.com/money?user=A&num=2000&transfer=C 這個請求,但是這個請求必須有A用戶發出纔可以生效,此時惡意用戶C可以搭建一個自己的網站,在網站中寫入如下代碼 <img src=“http://www.bank.com/money?user=A&num=2000&transfer=C”>,之後誘導A用戶訪問自己的網站,當A訪問這個網站時,這個網站就會把img標籤裏的URL發給銀行服務器,而此時除了這個請求以外,還會把A用戶的cookie一起發到服務器,如果此時A用戶的瀏覽器與銀行的session沒有過期,那麼就會在A用戶毫不知情的情況下執行轉賬給C的操作。

案例二:

一個cms系統的管理後臺,可以發送一個post請求添加一個管理員,url爲"http://www.cms.com/add", 由於沒有加token或者驗證碼限制,惡意攻擊者可以在自己的服務器evil.com上建立一個a.html的文件,a.html文件是一個添加管理員賬戶的表單,上面寫入需要添加的賬戶用戶名及密碼,當網站管理員打開"evil.com/a.html"的時候,並且管理員的session沒有失效,那麼此時a.html就會請求受攻擊網站,在管理員毫不知情的情況下添加一個後臺賬戶。
a.html內容如下:

 <form method="post" action="http://www.cms.com/add" enctype="application/x-www-form-urlencoded">
    <label>賬號:</label><input type="hidden" name="name" value="123456"/> 
    <label>密碼:</label><input type="hidden" name="pwd" value="123456"/>
  </form>
  • 通過以上兩個案例可以得出結論,csrf會根據業務功能場景的不用而利用起來也不同,這些請求都是跨域發起的,而且是在受害者的session沒有失效通過身份認證的情況下發生的。
  • 使用用戶的登陸憑證,讓用戶自己在不知情的情況下,進行修改數據的操作。
  • 但是查詢數據的地方卻不需要保護,因爲csrf是藉助受害者的cookie來進行攻擊者需要的惡意操作的,攻擊者並不能拿到受害者cookie,對於服務器返回的結果也無法解析查看,攻擊者唯一可以做的就是讓服務器執行自己的操作命令,或者說改變網站數據,而查詢操作即不會改變數據也不會把結果返回給攻擊者,所以並不需要保護。

防護措施

對於web站點,將持久化的授權方法(例如cookie或者HTTP授權)切換爲瞬時的授權方法(在每個form中提供隱藏field,如token),這將幫助網站防止這些攻擊。
服務端的CSRF方式方法很多樣,但總的思想都是一致的,就是在客戶端頁面增加僞隨機數。

  1. 檢查HTTP 頭部 Refer 信息
    這是防止 CSRF 的最簡單容易實現的一種手段。根據 RFC 對於 HTTP 協議裏面 Refer 的定義,Refer 信息跟隨出現在每個 Http 請求頭部。Server 端在收到請求之後,可以去檢查這個頭信息,只接受來自本域的請求而忽略外部域的請求,這樣就可以避免了很多風險。當然這種檢查方式由於過於簡單也有它自身的弱點:
  • 首先是檢查 Refer 信息並不能防範來自本域的攻擊。在企業業務網站上,經常會有同域的論壇,郵件等形式的 Web 應用程序存在,來自這些地方的 CSRF 攻擊所攜帶的就是本域的 Refer 域信息,因此不能被這種防禦手段所阻止。

  • 同樣,某些直接發送 HTTP 請求的方式(指非瀏覽器,比如用後臺代碼等方法)可以僞造一些 Refer 信息,雖然直接進行頭信息僞造的方式屬於直接發送請求,很難跟隨發cookie,但由於目前客戶端手段層出不窮,flash,javascript 等大規模使用,從客戶端進行 refer的僞造,尤其是在客戶端瀏覽器安裝了越來越多的插件的情況下已經成爲可能了。

  1. Cookie Hashing(所有表單都包含同一個僞隨機值)
    這可能是最簡單的解決方案了,因爲攻擊者不能獲得第三方的Cookie(理論上),所以表單中的數據也就構造失敗了,但由於網站中存在XSS漏洞而被偷竊的危險。

  2. 驗證碼
    這種方法的出現的作用是對於機器人暴力攻擊的防止。但在 CSRF 的防範上,也有 一些 安全性要求比較高的的應用程序結合驗證圖片和一次性令牌來做雙重保護。由於這種 圖片驗證信息很難被惡意程序在客戶端識別,因此能夠提高更強的保護。當客戶端的瀏覽器可能已經處於一種不安全的環境中的情況下(比如客戶端的安全級別設置較低,客戶端瀏覽器安裝了不安全的插件等)。但個人覺得在易用性方面似乎不是太好,還有聽聞是驗證碼圖片的使用涉及了一個被稱爲MHTML的Bug,可能在某些版本的微軟IE中受影響。

  3. One-Time Tokens(一次性令牌)

    一般通過session token來實現保護。當客戶端請求頁面時,服務器會生成一個隨機數Token,並且將Token放置到session當中,然後將Token發給客戶端(一般通過構造hidden表單)。下次客戶端提交請求時,Token會隨着表單一起提交到服務器端。接收到請求後,服務器端會對Token值進行驗證,判斷是否和session中的Token值相等,若相等,則可以證明請求有效,不是僞造的。
      在實現One-Time Tokens時,需要注意一點:就是“並行會話的兼容”。如果用戶在一個站點上同時打開了兩個不同的表單,CSRF保護措施不應該影響到他對任何表單的提交。考慮一下如果每次表單被裝入時站點生成一個僞隨機值來覆蓋以前的僞隨機值將會發生什麼情況:用戶只能成功地提交他最後打開的表單,因爲所有其他的表單都含有非法的僞隨機值。必須小心操作以確保CSRF保護措施不會影響選項卡式的瀏覽或者利用多個瀏覽器窗口瀏覽一個站點。
      另外,這裏的session token機制也可用於註冊或者cms文章添加等功能上,可以用來防止用戶"重複提交",相比於上面的CSRF方案是這樣的:服務器端第一次驗證相同過後,會將澀session中的Token值更新下,若用戶重複提交,第二次的驗證判斷將失敗,因爲用戶提交的表單中的Token沒變,但服務器端session中Token已經改變了。
      
    下面是tp3.2.3表單驗證的代碼(One-Time Tokens實現方法)

  • 表單
//表單
<!DOCTYPE HTML>
<html>
<body>
  <form method="post" action="Home/index/form" enctype="application/x-www-form-urlencoded">
    <label>賬號:</label><input name="name" value=""/> 
    <label>密碼:</label><input name="pwd" value=""/>
    <button>提交</button>
  </form>
</body>
</html>
  • 表單驗證(防csrf),可以看到利用session保存了token
//生成token代碼省略
;;;;;
// 自動錶單令牌驗證
    public function autoCheckToken($data)
    {
        // 支持使用token(false) 關閉令牌驗證
        if (isset($this->options['token']) && !$this->options['token']) {
            return true;
        }

        if (C('TOKEN_ON')) {
			
            $name = C('TOKEN_NAME', null, '__hash__');
		
            if (!isset($data[$name]) || !isset($_SESSION[$name])) {
                // 令牌數據無效	
		        $this->error='令牌數據無效';
                return false;
            }
      
            // 令牌驗證
            list($key, $value) = explode('_', $data[$name]);			
			
            if (isset($_SESSION[$name][$key]) && $value && $_SESSION[$name][$key] === $value) {
                // 防止重複提交					
                unset($_SESSION[$name][$key]); // 驗證完成銷燬session
                return true;
            }
            // 開啓TOKEN重置
            if (C('TOKEN_RESET')) {
                unset($_SESSION[$name][$key]);
            }
            $this->error='表單重複提交';
            return false;
        }
        return true;
    }
  • 驗證經TP處理後的表單,可以看到生成了隱藏字段_hash_

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章