CSRF 1 (轉)

一.CSRF是什麼?javascript

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

二.CSRF能夠作什麼?html

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

三.CSRF的原理瀏覽器

要完成一次CSRF攻擊,受害者必須依次完成兩個步驟:安全

  1.登陸受信任網站A,並在本地生成Cookie。服務器

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

示例1:session

  銀行網站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請求更新資源。

示例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>

,你首先登陸了銀行網站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%的杜絕,這個不是最好的方法。

相關文章
相關標籤/搜索