首頁 後端開發 php教程 跨站請求偽造CSRF攻防

跨站請求偽造CSRF攻防

Oct 17, 2016 am 10:46 AM

一.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攻擊,受害者必須依序完成兩個步驟:

  1.登入受信任網站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的程式碼如下:

  

跨站請求偽造CSRF攻防  首先,你登入了銀行網站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[&#39;toBankId&#39;] && isset($_REQUEST[&#39;money&#39;]))
    {
        buy_stocks($_REQUEST[&#39;toBankId&#39;], $_REQUEST[&#39;money&#39;]);
    }
  ?>
登入後複製

  危險網站B,仍然只是包含那句HTMLMLMLML:HTMLs㟎〜

  和示例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[&#39;toBankId&#39;] && isset($_POST[&#39;money&#39;]))
    {
        buy_stocks($_POST[&#39;toBankId&#39;], $_POST[&#39;money&#39;]);
    }
  ?>
登入後複製

  然而,危险网站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种最为严重,因为触发条件很简单,一个就可以了,而第3种比较麻烦,需要使用JavaScript,所以使用的机会会比前面的少很多,但无论是哪种情况,只要触发了CSRF攻击,后果都有可能很严重。

  理解上面的3种攻击模式,其实可以看出,CSRF攻击是源于WEB的隐式身份验证机制!WEB的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的!

五.CSRF的防御

CSRF 的防范机制有很多种,防范的方法也根据 CSRF 攻击方式的不断升级而不断演化。常用的有检查 Refer 头部信息,使用一次性令牌,使用验证图片等手段。出于性能的考虑,如果每个请求都加入令牌验证将极大的增加服务器的负担,具体采用那种方法更合理,需要谨慎审视每种保护的优缺点。

1. 检查 HTTP 头部 Refer 信息,这是防止 CSRF 的最简单容易实现的一种手段。根据 RFC 对于 HTTP 协议里面 Refer 的定义,Refer 信息跟随出现在每个 Http 请求头部。Server 端在收到请求之后,可以去检查这个头信息,只接受来自本域的请求而忽略外部域的请求,这样就可以避免了很多风险。当然这种检查方式由于过于简单也有它自身的弱点:

a) 首先是检查 Refer 信息并不能防范来自本域的攻击。在企业业务网站上,经常会有同域的论坛,邮件等形式的 Web 应用程序存在,来自这些地方的 CSRF 攻击所携带的就是本域的 Refer 域信息,因此不能被这种防御手段所阻止。

b) 同样,某些直接发送 HTTP 请求的方式(指非浏览器,比如用后台代码等方法)可以伪造一些 Refer 信息,虽然直接进行头信息伪造的方式属于直接发送请求,很难跟随发送 cookie,但由于目前客户端手段层出不穷,flash,javascript 等大规模使用,从客户端进行 refer 的伪造,尤其是在客户端浏览器安装了越来越多的插件的情况下已经成为可能了。

2. 使用一次性令牌,这是当前 Web 应用程序的设计人员广泛使用的一种方式,方法是对于 Get 请求,在 URL 里面加入一个令牌,对于 Post 请求,在隐藏域中加入一个令牌。这个令牌由 server 端生成,由编程人员控制在客户端发送请求的时候使请求携带本令牌然后在 Server 端进行验证。但在令牌的设计上目前存在着几个错误的方案:

a) 使用和 Session 独立的令牌生成方式。这种令牌的值和 Session 无关,因此容易被其他用户伪造。这里的其他用户指的是当前 Web 应用程序的其他用户和活跃在网络传输阶段各个设置上的监听者,这种恶意用户可能使用自己的令牌来进行替换以便达到伪造的目的。

b) 完全使用 Session 认证信息作为令牌的生成方式。这种保护方式对于保护 CSRF 是起了作用的,但是可能会造成其他危害,具体来说,如果某些 URL 或者网页被拷贝下来与其他人共享,那么这些 URL 或者拷贝下来的网页中可能会含有用户的会话信息,这种信息一旦被恶意用户获得,就能造成极大的危害。

因此,一个正确的令牌设计应该是使用 Session 信息做 Hash,用得出的哈希值来做 CSRF 的令牌。

3. 使用驗證圖片,這種方法的出現的作用是對於機器人暴力攻擊的防止。但在 CSRF 的防範上,也有一些安全性要求比較高的應用程式結合驗證圖片和一次性代幣來做雙重保護。由於這種圖片驗證資訊很難被惡意程式在客戶端識別,因此能夠提高更強的保護。當客戶端的瀏覽器可能已經處於一種不安全的環境中的情況下(例如客戶端的安全等級設定較低,客戶端瀏覽器安裝了不安全的插件等)。

以上給的這些只是防範CSRF 的比較通用的一些方法,Web 開發人員可以根據自己對自己的應用程序的功能的理解來確定安全級別的要求從而選擇使用不同的保護措施,也推薦在同一應用程式內部結合使用多種方法來進行保護。

註:加防也會極大的影響性能,就如在高速公路上放一個收費站,建議只在重要操作上加防。如位慎重考慮。


本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

在PHP API中說明JSON Web令牌(JWT)及其用例。 在PHP API中說明JSON Web令牌(JWT)及其用例。 Apr 05, 2025 am 12:04 AM

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

會話如何劫持工作,如何在PHP中減輕它? 會話如何劫持工作,如何在PHP中減輕它? Apr 06, 2025 am 12:02 AM

會話劫持可以通過以下步驟實現:1.獲取會話ID,2.使用會話ID,3.保持會話活躍。在PHP中防範會話劫持的方法包括:1.使用session_regenerate_id()函數重新生成會話ID,2.通過數據庫存儲會話數據,3.確保所有會話數據通過HTTPS傳輸。

PHP 8.1中的枚舉(枚舉)是什麼? PHP 8.1中的枚舉(枚舉)是什麼? Apr 03, 2025 am 12:05 AM

PHP8.1中的枚舉功能通過定義命名常量增強了代碼的清晰度和類型安全性。 1)枚舉可以是整數、字符串或對象,提高了代碼可讀性和類型安全性。 2)枚舉基於類,支持面向對象特性,如遍歷和反射。 3)枚舉可用於比較和賦值,確保類型安全。 4)枚舉支持添加方法,實現複雜邏輯。 5)嚴格類型檢查和錯誤處理可避免常見錯誤。 6)枚舉減少魔法值,提升可維護性,但需注意性能優化。

描述紮實的原則及其如何應用於PHP的開發。 描述紮實的原則及其如何應用於PHP的開發。 Apr 03, 2025 am 12:04 AM

SOLID原則在PHP開發中的應用包括:1.單一職責原則(SRP):每個類只負責一個功能。 2.開閉原則(OCP):通過擴展而非修改實現變化。 3.里氏替換原則(LSP):子類可替換基類而不影響程序正確性。 4.接口隔離原則(ISP):使用細粒度接口避免依賴不使用的方法。 5.依賴倒置原則(DIP):高低層次模塊都依賴於抽象,通過依賴注入實現。

在PHPStorm中如何進行CLI模式的調試? 在PHPStorm中如何進行CLI模式的調試? Apr 01, 2025 pm 02:57 PM

在PHPStorm中如何進行CLI模式的調試?在使用PHPStorm進行開發時,有時我們需要在命令行界面(CLI)模式下調試PHP�...

如何用PHP的cURL庫發送包含JSON數據的POST請求? 如何用PHP的cURL庫發送包含JSON數據的POST請求? Apr 01, 2025 pm 03:12 PM

使用PHP的cURL庫發送JSON數據在PHP開發中,經常需要與外部API進行交互,其中一種常見的方式是使用cURL庫發送POST�...

如何在系統重啟後自動設置unixsocket的權限? 如何在系統重啟後自動設置unixsocket的權限? Mar 31, 2025 pm 11:54 PM

如何在系統重啟後自動設置unixsocket的權限每次系統重啟後,我們都需要執行以下命令來修改unixsocket的權限:sudo...

See all articles