最牛「CSRF防禦」,帶你進入大蝦們的圈子!

簡單理解 CSRF

最牛「CSRF防禦」,帶你進入大蝦們的圈子!

什麼是 CSRF?

CSRF,一般稱爲跨站請求僞造,英文名 Cross-site request forgery 縮寫 CSRF,是一種對網站的惡意攻擊。一個跨站請求僞造攻擊迫使登陸用戶的瀏覽器將僞造的HTTP請求,包括該用戶的會話 cookie 和其餘認證信息,發送到一個存在漏洞的web應用程序。這就容許了攻擊者迫使用戶瀏覽器向存在漏洞的應用程序發送請求,而這些請求會被應用程序認爲是用戶的合法請求。與XSS相比,CSRF攻擊每每不大流行(所以對其進行防範的資源也至關稀少)和難以防範,因此被認爲比XSS更具危險性。javascript

CSRF 攻擊過程簡述

最牛「CSRF防禦」,帶你進入大蝦們的圈子! 訪問受信任的站點 C,C 在您的瀏覽器中寫入 Cookie , 您又訪問含有攻擊代碼的站點 B, 站點 B 以您的身份向 A 發送了一個請求,而這個請求並無通過您的贊成或者並非您想要發送的。html

CSRF 的危害有哪些?

CSRF 能夠用訪問者的身份作不少事情,包括但不限於我的信息泄露、也可能會危害財產安全。前端

CSRF 常見攻擊方式

常見的攻擊方式大體能夠分爲如下幾種java

  1. Img 標籤 GET 請求

例如修改當前已登陸用戶密碼web

<img src="//rasp.oneasp.com/account/modifyPassword?new=123"/>
  1. Flash 或隱藏表單的主動提交ajax

    <form action="//rasp.oneasp.com/account/modifyPassword">
       <input type="hidden" name="new" value="123"/>
     </form>
     <script>document.forms[0].submit()</script>
CSRF 如何防護

目前防禦 CSRF 大多在服務器端進行驗證和限制,客戶端解決方案較少,實現成本也較高。服務端主要方式有如下幾種flask

  1. Token 驗證

這種方式能夠過濾 95% 以上的 CSRF ,在表單提交時放入一個 token, 服務器驗證該 token 是否有效。只容許有效的 token 請求, 不然拒絕當前操做。 但這種方式也有必定的侷限性, 對於一些 GET 請求(例如獲取當前用戶信息的 GET 請求)加入 token 驗證可能須要更改後端 API。後端

  1. Referer 驗證

通常對於一些私有 API 徹底能夠拒絕非當前 origin 的 referer,在已知受信站點白名單的狀況下,對於例如多站點共用的 API (例如權限系統)能夠設置可訪問 origin 的列表。須要注意在不少請求頭中並無 referer 或者 referer 不正確。瀏覽器

  1. 隱藏令牌 將獨有的令牌包含在一個隱藏字段中。 這將使得該令牌經過 HTTP 請求體發送,避免其包含在 URL 中從而被暴露出來。該獨有令牌一樣能夠包含在 URL 中或做爲一個 URL 參數。 可是這種方法的巨大風險在於:URL 會暴露給攻擊者, 這樣祕密令牌也會被泄漏。

CSRF 防禦 in Flask

flask-wtf

在 Flask 0.9.0版本後,可使用 Flask-WTF 來防護 CSRF 攻擊,Flask-WTF 默認對全部提交的表單啓用 csrf 防禦安全

wtf的token
<form method="post" action="https://www.oneasp.com">
    {{ form.csrf_token }}
</form>
非wtf的tokan

當使用非WTF表單的時候,能夠將token放在一個隱藏域中,隨表單一塊兒提交

<form method="post" action="https://www.oneasp.com">
    <input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
</form>
AJAX的token

Ajax的token能夠放在隱藏域或其餘標籤中, 在經過js獲取token, 隨Ajax請求提交

<script type="text/javascript">
    var csrftoken = "{{ csrf_token() }}"
	// 或者
	var csrftoken = $('meta[name=csrf-token]').attr('content')
	
	$.ajaxSetup({
	    beforeSend: function(xhr, settings) {
	        if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
	            xhr.setRequestHeader("X-CSRFToken", csrftoken)
	        }
	    }
	})
</script>
自定義 CSRF 驗證失敗後的邏輯

Flask提供裝飾器@csrf.error_handler 來支持定製當CSRF驗證失敗後的返回信息

@csrf.error_handler
def csrf_error(reason):
    return render_template('csrf_error.html', reason=reason), 400

本文系 OneASP 前端工程師陳喜順原創文章。現在,多樣化的攻擊手段層出不窮,傳統安全解決方案愈來愈難以應對網絡安全攻擊。OneASP 自適應安全平臺集成了預測、預防、檢測和響應的能力,爲您提供精準、持續、可視化的安全防禦。想閱讀更多技術文章,請訪問 OneAPM 官方技術博客 本文轉自 OneAPM 官方博客

相關文章
相關標籤/搜索