CSRF攻擊與Django防範

什麼是CSRF

CSRF,全稱 Cross Site Request Forgery,跨站請求僞造,是一種欺騙受害用戶在已登陸的web應用上按照攻擊者的指令執行惡意操做的攻擊行爲。攻擊的影響範圍取決於受害用戶所擁有的的權限,由於攻擊者是依賴用戶在當前會話中的鑑權進行惡意操做的。html

CSRF是如何工做的

CSRF僅在用戶已被受權的狀況下才能生效。經過CSRF,攻擊者能夠繞開web應用的鑑權機制,進而利用受害者的用戶權限對web應用進行惡意操做。好比網上銀行等場景。web

下面是CSRF攻擊的兩個主要組成部分:django

  1. 第一步是欺騙用戶點擊一個連接或者加載一個頁面,一般是利用一些社交手段誘使用戶點擊一個惡意連接。
  2. 第二部是在這個惡意連接中,經過用戶的瀏覽器向web應用發起一個僞造的請求。這個僞造請求看起來是合法的,可是攜帶的是攻擊者僞造的數據。與此同時,瀏覽器會在請求中帶上與該web應用關聯的cookie。由於cookie中包含了用戶以前登錄的token鑑權信息,在用戶沒有登出或者token沒有過時以前,該鑑權信息是持續有效的。這樣攻擊者就能夠依靠該cookie直接獲取到用戶的權限進行惡意操做了。

(HTTP session和cookie機制請見cookie與session的區別以及在Django中的實現)api

CSRF攻擊實際上就是利用了HTTP會話的cookie機制,由於瀏覽器會在每次請求中都帶上與web應用關聯的cookie。瀏覽器

CSRF攻擊示例

假設這是一個合法的url,用於向指定的User用戶轉帳1000塊錢。bash

http://example.com/transfer?amount=1000&account=User
複製代碼

當用戶發送該請求時,若是用戶已經登陸過web應用且鑑權經過,則瀏覽器會在請求中自動攜帶包含鑑權信息的cookie,這樣用戶進行轉帳時就不須要再次進行登陸驗證;若是用戶還未登陸鑑權,則會須要先進行登陸鑑權,而後瀏覽器才能進一步攜帶cookie信息發起轉帳請求。 web應用須要拿到轉帳請求中攜帶的cookie用於驗證用戶信息,才能得知是要從哪一個用戶的帳戶中將錢轉出。cookie

1. 使用GET請求進行攻擊

若是web應用能夠接受GET請求,那攻擊者只須要在惡意連接的html中加入以下的代碼,經過img標籤自動向web應用僞造一個轉帳請求。利用瀏覽器自動攜帶cookie的機制,就能夠從用戶帳戶中盜走1000塊錢。session

<img src="http://example.com/transfer?amount=1000&account=Fred" />
複製代碼

該場景中的web應用除了存在CSRF漏洞之外,還有一個問題:任何的GET請求都應該是「只讀「的,不該該對數據產生任何影響。因此該場景中的web應用設計是不合理的。post

2. 使用POST請求進行攻擊

下面是使用POST進行攻擊的html表單代碼網站

<h1>You Are a Winner!</h1>
<form action="http://example.com/api/account" method="post">
 <input type="hidden" name="Transaction" value="withdraw" />
 <input type="hidden" name="Amount" value="1000" />
 <input type="submit" value="Click Me"/>
</form>
複製代碼

試想以下攻擊場景:

  1. 用戶登陸web應用example.com,並進行了鑑權。
  2. web應用對用戶進行受權,並在響應中攜帶了包含鑑權token的cookie。
  3. 用戶在沒有登出的狀況下,又打開了一個包含上述html表單的惡意頁面。(注意該表單中的action是將請求發送到存在漏洞的web應用,而不是惡意頁面自己,這就是Cross-Site,跨站請求)
  4. 用戶點擊惡意頁面中的"Click Me"按鈕提交,瀏覽器在請求中攜帶cookie發給web應用。
  5. 僞造的請求利用攜帶的cookie經過了web應用的鑑權,取得了用戶所擁有的的權限,進行惡意操做。

值得注意的是,SSL是沒法防禦CSRF攻擊的。由於攻擊者只須要在僞造請求中指定https訪問便可。

防範CSRF攻擊

最經常使用的CSRF防範機制就是使用csrf token機制。

  1. csrf token基於一個隨機生成的祕鑰secret,並經過salt hash方式加密生成csrftoken,插入到Cookie中。該csrftoken在用戶登陸階段生成,在session結束前保持不變。

  1. 每個響應的POST表單中,都會插入一個隱藏的csrfmiddlewaretoken字段。該字段的值也是對1中的secret進行salt hash,每次請求表單頁面都會使用一個隨機的salt,因此每次響應中表單裏面插入的csrfmiddlewaretoken都是不同的。

  1. 對於每一次HTTP請求,只要request method不是GET, HEAD, OPTIONS or TRACE,都會要求同時在request header的cookie中攜帶csrftoken,以及在request body中攜帶csrfmiddlewaretoken,並對兩者進行校驗。若是缺失或者校驗不經過,則返回403 error。

  1. 在校驗csrftoken和csrfmiddlewaretoken時,不是直接對比兩個token,而是解密後對比兩者的祕鑰secret是否相同。由於即便用戶每次請求在表單中得到的csrfmiddlewaretoken都是變化的,可是在整個session中,secret是保持不變的。

注意,在POST表單中使用csrf token時,要確保表單是提交給本身的web應用的,而不是提交給外部的應用。好比在表單action中指定提交到baidu或者其餘網站,別人是沒法識別請求中的csrf token的,而且同時也存在泄漏csrf token的風險。

總結

cookie由於其自動在請求中攜帶的特色,很容易受到CSRF攻擊。攻擊者不須要獲取用戶的cookie,也能夠直接利用用戶的cookie進行惡意操做。CSRF攻擊的影響取決於用戶所擁有的權限。

因此咱們在web應用設計中要注意,一方面是要嚴格遵照HTTP規範,GET請求必定是」只讀「的,避免接收GET請求進行狀態變動(如數據修改等);另外一方面是對於全部設計狀態變動的請求,如POST、PUT、DELETE等,都須要進行csrf token校驗。

【本文參考】

Introduction to CSRF

Cross Site Request Forgery protection

相關文章
相關標籤/搜索