淺談CSRF攻擊方式

2021-02-23 合天智匯

一.CSRF是什麼?


  CSRF(Cross-site request forgery),中文名稱:跨站請求偽造,也被稱為:one click attack/session riding,縮寫為:CSRF/XSRF。

二.CSRF可以做什麼?


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

三.CSRF漏洞現狀


CSRF這種攻擊方式在2000年已經被國外的安全人員提出,但在國內,直到06年才開始被關注,08年,國內外的多個大型社區和交互網站分別爆出CSRF漏洞。

如:NYTimes.com(紐約時報)、Metafilter(一個大型的BLOG網站),YouTube和百度HI.而現在,網際網路上的許多站點仍對此毫無防備,以至於安全業界稱CSRF為「沉睡的巨人」。


四.CSRF的原理

下圖簡單闡述了CSRF攻擊的思想:


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

登錄受信任網站A,並在本地生成Cookie。

2.在不登出A的情況下,訪問危險網站B。

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

1.  你不能保證你登錄了一個網站後,不再打開一個tab頁面並訪問另外的網站。

2.你不能保證你關閉瀏覽器了後,你本地的Cookie立刻過期,你上次的會話已經結束。(事實上,關閉瀏覽器不能結束一個會話,但大多數人都會錯誤的認為關閉瀏覽器就等於退出登錄/結束會話了.)

3.上圖中所謂的攻擊網站,可能是一個存在其他漏洞的可信任的經常被人訪問的網站。

上面大概地講了一下CSRF攻擊的思想,下面我將用幾個例子詳細說說具體的CSRF攻擊,這裡我以一個銀行轉帳的操作作為例子(僅僅是例子,真實的銀行網站沒這麼傻:>)

示例1:

  

銀行網站A,它以GET請求來完成銀行轉帳的操作,如:http://www.mybank.com/Transfer.php?toBankId=11&money=1000

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

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

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

為什麼會這樣呢?原因是銀行網站A違反了HTTP規範,使用GET請求更新資源。在訪問危險網站B的之前,你已經登錄了銀行網站A,而B中的<img>以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>

如果用戶仍是繼續上面的操作,很不幸,結果將會是再次不見1000塊.因為這裡危險網站B暗地裡發送了POST請求到銀行!

總結一下上面3個例子,CSRF主要的攻擊模式基本上是以上的3種,其中以第1,2種最為嚴重,因為觸發條件很簡單,一個<img>就可以了,而第3種比較麻煩,需要使用JavaScript,所以使用的機會會比前面的少很多,但無論是哪種情況,只要觸發了CSRF攻擊,後果都有可能很嚴重。

理解上面的3種攻擊模式,其實可以看出,CSRF攻擊是源於WEB的隱式身份驗證機制!WEB的身份驗證機制雖然可以保證一個請求是來自於某個用戶的瀏覽器,但卻無法保證該請求是用戶批准發送的!

五.CSRF的防禦

我總結了一下看到的資料,CSRF的防禦可以從服務端和客戶端兩方面著手,防禦效果是從服務端著手效果比較好,現在一般的CSRF防禦也都在服務端進行。


1.服務端進行CSRF防禦


服務端的CSRF方式方法很多樣,但總的思想都是一致的,就是在客戶端頁面增加偽隨機數。

(1).Cookie Hashing(所有表單都包含同一個偽隨機值):

這可能是最簡單的解決方案了,因為攻擊者不能獲得第三方的Cookie(理論上),所以表單中的數據也就構造失敗了:>

<?php
    //構造加密的Cookie信息
    $value = 「DefenseSCRF」;
    setcookie(」cookie」, $value, time()+3600);
  ?>

在表單裡增加Hash值,以認證這確實是用戶發送的請求。

<?php
    $hash = md5($_COOKIE['cookie']);
  ?>
  <form method=」POST」 action=」transfer.php」>
    <input type=」text」 name=」toBankId」>
    <input type=」text」 name=」money」>
    <input type=」hidden」 name=」hash」 value=」<?=$hash;?>」>
    <input type=」submit」 name=」submit」 value=」Submit」>
  </form>

 然後在伺服器端進行Hash值驗證

<?php
        if(isset($_POST['check'])) {
             $hash = md5($_COOKIE['cookie']);
             if($_POST['check'] == $hash) {
                  doJob();
             } else {
        //...
             }
        } else {
      //...
        }
      ?>

這個方法個人覺得已經可以杜絕99%的CSRF攻擊了,那還有1%呢....由於用戶的Cookie很容易由於網站的XSS漏洞而被盜取,這就另外的1%。一般的攻擊者看到有需要算Hash值,基本都會放棄了,某些除外,所以如果需要100%的杜絕,這個不是最好的方法。
  

(2).驗證碼

  

這個方案的思路是:每次的用戶提交都需要用戶在表單中填寫一個圖片上的隨機字符串,厄....這個方案可以完全解決CSRF,但個人覺得在易用性方面似乎不是太好,還有聽聞是驗證碼圖片的使用涉及了一個被稱為MHTML的Bug,可能在某些版本的微軟IE中受影響。

  

(3).One-Time Tokens(不同的表單包含一個不同的偽隨機值)

 

在實現One-Time Tokens時,需要注意一點:就是「並行會話的兼容」。如果用戶在一個站點上同時打開了兩個不同的表單,CSRF保護措施不應該影響到他對任何表單的提交。考慮一下如果每次表單被裝入時站點生成一個偽隨機值來覆蓋以前的偽隨機值將會發生什麼情況:用戶只能成功地提交他最後打開的表單,因為所有其他的表單都含有非法的偽隨機值。必須小心操作以確保CSRF保護措施不會影響選項卡式的瀏覽或者利用多個瀏覽器窗口瀏覽一個站點。

  

以下我的實現:

  1).先是令牌生成函數(gen_token()):


<?php
     function gen_token() {
     //這裡我是貪方便,實際上單使用Rand()得出的隨機數作為令牌,也是不安全的。
    //這個可以參考我寫的Findbugs筆記中的《Random object created and used only once》
          $token = md5(uniqid(rand(), true));
          return $token;
     }

2).然後是Session令牌生成函數(gen_stoken()):

<?php
       function gen_stoken() {
      $pToken = "";
      if($_SESSION[STOKEN_NAME]  == $pToken){
        //沒有值,賦新值
        $_SESSION[STOKEN_NAME] = gen_token();
      }    
      else{
        //繼續使用舊的值
      }
       }
     ?>

3).WEB表單生成隱藏輸入域的函數:  

<?php
       function gen_input() {
            gen_stoken();
            echo 「<input type=\」hidden\」 name=\」" . FTOKEN_NAME . 「\」
                 value=\」" . $_SESSION[STOKEN_NAME] . 「\」> 「;
       }
     ?>

4).WEB表單結構:

<?php
          session_start();
          include(」functions.php」);
     ?>
     <form method=」POST」 action=」transfer.php」>
          <input type=」text」 name=」toBankId」>
          <input type=」text」 name=」money」>
          <? gen_input(); ?>
          <input type=」submit」 name=」submit」 value=」Submit」>
     </FORM>

5).服務端核對令牌:

這個很簡單,這裡就不再囉嗦了。

上面這個其實不完全符合「並行會話的兼容」的規則,大家可以在此基礎上修改。

 

轉載自segmentfault


關注我們吧!

相關焦點

  • CSRF 攻擊的應對之道
    導讀:CSRF(Cross Site Request Forgery, 跨站域請求偽造)是一種網絡的攻擊方式
  • SpringBoot 如何防禦 CSRF 攻擊?
    這是一種非常常見的 Web 攻擊方式,其實是很好防禦的,但是由於經常被很多開發者忽略,進而導致很多網站實際上都存在 CSRF 攻擊的安全隱患。今天就來和大家聊一聊什麼是 CSRF 攻擊以及 CSRF 攻擊該如何防禦。
  • CSRF 攻擊及防禦
    這時,Mallory 想到使用 CSRF 的攻擊方式,他先自己做一個網站,在網站中放入如下代碼: src=」http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory 」,並且通過廣告等誘使 Bob 來訪問他的網站。
  • Go 語言安全編程系列(一):CSRF 攻擊防護
    1、工作原理在 Go Web 編程中,我們可以基於第三方 gorilla/csrf 包避免 CSRF 攻擊,和 Laravel 框架一樣,這也是一個基於 HTTP 中間件避免 CSRF 攻擊的解決方案,其中包含的中間件名稱是 csrf.Protect。
  • CSRF攻擊防禦原理
    CSRF是現代WEB程序要面對的共通性問題,在很多流行的WEB框架中,都會將CSRF的問題直接在WEB框架層面解決。我們先拋出CSRF這個問題,然後介紹基於時間與籤名的防護手段,並且給出的這種防禦手段的具體代碼實現。
  • Django 前後端分離csrf token獲取方式
    需求一般Django開發為了保障避免 csrf 的攻擊,如果使用Django的模板渲染頁面,那麼則可以在請求中渲染設置一個csrftoken的
  • 淺談XSS攻擊的那些事(附常用繞過姿勢)
    本文《淺談XSS攻擊的那些事(附常用繞過姿勢)》 由一葉知安團隊原創投稿安全脈搏首發,作者geek痕,安全脈搏獨家首發表本文,如需要轉載,請先聯繫安全脈搏授權
  • XSS及CSRF攻擊防禦
    持久型通常是因為伺服器端將用戶輸入的惡意腳本沒有經過驗證就存儲在資料庫中,並且通過調用資料庫的方式,將數據呈現在瀏覽器上,當頁面被用戶打開的時候執行,每當用戶打開瀏覽器,惡意腳本就會執行。持久型的 XSS 攻擊相比非持久型的危害性更大,因為每當用戶打開頁面,惡意腳本都會執行。
  • 淺析CSRF的防禦和攻擊案例
    利用受害者在被攻擊網站已經獲取的註冊憑證,繞過後臺的用戶驗證,達到冒充用戶對被攻擊的網站執行某項操作的目的。白名單白名單的話其實和CORS的繞過差不多, 無非都是看他的正則寫得有沒有問題, 比如下面的例子那我們可以用來繞過, 再比如下面的例子那可以用來繞過, 這都是正則沒寫好的例子, 大廠的正則也會有或多或少的問題2333因此這個防禦方式應當作為輔助而不是主要的防禦方式
  • 前端安全知識—關於XSS攻擊和CSRF攻擊
    Site Scripting)是最常見和基本的攻擊 WEB 網站方法,攻擊者通過注入非法的 html 標籤或者 javascript 代碼,從而當用戶瀏覽該網頁時,控制用戶瀏覽器。跨站腳本攻擊可能造成以下影響:存儲型 xss 案例在項目開發中,評論是個常見的功能,如果直接把評論的內容保存到資料庫,那麼顯示的時候就可能被攻擊。
  • DVWA之CSRF跨站腳本攻擊
    最近一直在研究跨站腳本攻擊的一些技術,研究過了XSS攻擊技術之後就來學習了CSRF跨站腳本攻擊,兩者之間是有很大的區別的。
  • 文庫 | CSRF知識總結
    利用受害者在被攻擊網站已經獲取的註冊憑證,繞過後臺的用戶驗證,達到冒充用戶對被攻擊的網站執行某項操作的目的csrf與xss區別XSS:跨站腳本(Cross-site scripting,通常簡稱為XSS)是一種網站應用程式的安全漏洞攻擊,是代碼注入的一種。它允許惡意用戶將代碼注入到網頁上,其他用戶在觀看網頁時就會受到影響。
  • 【黑客養成】python中的CSRF
    CSRF 背景與介紹CSRF(Cross Site Request Forgery, 跨站域請求偽造)是一種網絡的攻擊方式,它在 2007 年曾被列為網際網路
  • 通過DVWA學CSRF
    簡介在本文中,您將學習跨站點請求偽造攻擊。
  • 5分鐘科普CSRF攻擊與防禦
    三、CSRF攻擊原理及過程第二個隱藏頁面(test2):進階版:假如博客園還是有個加關注的接口,已經限制POST,但博文內容是直接貼進HTML(未過濾),那就遭受XSS攻擊。那麼就可以直接把上面代碼嵌入博文,那麼只要有人打開我這篇博文,還是會自動關注我,這組合攻擊方式稱為XSRF。
  • 邪惡的CSRF (1)!
    我們知道,攻擊時常常伴隨著各種各樣的請求,而攻擊的發生也是由各種請求造成的。            從前面這個名字裡我們可以關注到兩個點:一個是「跨站點」,另一個是「偽造」。前者說明了CSRF攻擊發生時所伴隨的請求的來源,後者說明了該請求的產生方式。所謂偽造即該請求並不是用戶本身的意願,而是由攻擊者構造,由受害者被動發出的。
  • Burp Suite | CSRF Token Tracker —— 繞過CSRF限制進行暴力破解
    一、簡介CSRF是跨站請求偽造,不攻擊網站伺服器,而是冒充用戶在站內的正常操作。
  • CSRF漏洞詳解
    3、幾種攻擊類型(1)GET類型的CSRFGET類型的CSRF利用非常簡單,只需要一個HTTP請求這種類型的CSRF一般是由於程式設計師安全意識不強造成的一般會這樣利用:<img src=http://wooyun.org/csrf?
  • CSRF 原理與防禦案例分析
    ,與 XSS 相似,但與 XSS 相比更難防範,是一種廣泛存在於網站中的安全漏洞,經常與 XSS 一起配合攻擊。  CSRF 能夠造成的危害1、篡改目標網站上的用戶數據; 2、盜取用戶隱私數據; 3、作為其他攻擊向量的輔助攻擊手法;
  • 利用Window.Opener繞過CSRF保護
    日前,我在一項Web應用中,發現了一個有趣的防範CSRF攻擊的安全機制。  那麼現在我們就需要設置window.opener來實現CSRF攻擊。  3.利用  通過分析我找到了一種通過使用HTTP標籤中href屬性來創建Opener值的方法。