一文带你学习跨站点请求伪造(CSRF)
一文帶你學習跨站點請求偽造(CSRF)
- 1.何為CSRF
- 2.瀏覽器的Cookie策略
- 3.P3P頭的副作用
- 4.CSRF攻擊流程
- 5.CSRF的分類
- GET型
- POST-表單型
- POST-JSON型
- 6.CSRF的快速驗證
- 7.CSRF的防御
- 驗證碼
- Referer Check
- Anti CSRF Token
1.何為CSRF
CSRF的全名是Cross Site Request Forgery,翻譯成中文就是跨站點請求偽造
CSRF是一種挾制用戶在當前已登錄的Web應用程序上執行非本意的操作的攻擊方法。跟跨站腳本(XSS)相比,XSS 利用的是用戶對指定網站的信任,CSRF 利用的是網站對用戶網頁瀏覽器的信任
例如現在有一個網站,只需要請求這個URL,就能夠把編號為“156713012”的博客文章刪除。
http://blog.sohu.com/manage/entry.do? m=delete&id=156713012攻擊者首先在自己的域構造一個頁面:
其內容為:
<img src="http://blog.sohu.com/manage/entry.do? m=delete&id=156714243" />攻擊者誘使目標用戶訪問這個頁面,從而執行CSRF攻擊
該用戶看到了一張無法顯示的圖片,但是不幸的式此時該用戶的博客已經被刪除
回顧整個攻擊過程,攻擊者僅僅誘使用戶訪問了一個頁面,就以該用戶身份在第三方站點里執行了一次操作。
這個刪除博客文章的請求,是攻擊者所偽造的,所以這種攻擊就叫做“跨站點請求偽造”。
CSRF漏洞的根本是:簡單的身份驗證只能保證請求是發自某個用戶的瀏覽器,卻不能保證請求本身是用戶自愿發出的💄
2.瀏覽器的Cookie策略
瀏覽器所持有的Cookie分為兩種:一種是“Session Cookie”,又稱“臨時Cookie”;另一種是“Third-party Cookie”,也稱為“本地Cookie”。
兩者的區別在于,Third-party Cookie是服務器在Set-Cookie時指定了Expire時間,只有到了Expire時間后Cookie才會失效,所以這種Cookie會保存在本地;而Session Cookie則沒有指定Expire時間,所以瀏覽器關閉后,Session Cookie就失效了。
例如:
<? php header("Set-Cookie: cookie1=123; "); header("Set-Cookie: cookie2=456; expires=Thu, 01-Jan-2030 00:00:01 GMT; ", false); ?>IE出于安全考慮,默認禁止了瀏覽器在<img>、<iframe>、<script>、<link>等標簽中發送第三方Cookie
攻擊者則需要精心構造攻擊環境,比如誘使用戶在當前瀏覽器中先訪問目標站點,使得Session Cookie有效,再實施CSRF攻擊?
在當前的主流瀏覽器中,默認會攔截Third-party Cookie的有:IE 6、IE 7、IE 8、Safari;不會攔截的有:Firefox 2、Firefox 3、Opera、Google Chrome、Android等。
3.P3P頭的副作用
瀏覽器攔截第三方Cookie的發送,在某種程度上來說降低了CSRF攻擊的威力。可是這一情況在“P3P頭”介入后變得復雜起來。
P3P Header是W3C制定的一項關于隱私的標準,全稱是The Platform for Privacy Preferences。
如果網站返回給瀏覽器的HTTP頭中包含有P3P頭,則在某種程度上來說,將允許瀏覽器發送第三方Cookie。在IE下即使是<iframe>、<script>等標簽也將不再攔截第三方Cookie的發送💍
在網站的業務中,P3P頭主要用于類似廣告等需要跨域訪問的頁面。
正因為P3P頭目前在網站的應用中被廣泛應用,因此在CSRF的防御中不能依賴于瀏覽器對第三方Cookie的攔截策略,不能心存僥幸。
很多時候,如果測試CSRF時發現<iframe>等標簽在IE中居然能發送Cookie,而又找不到原因,那么很可能就是因為P3P頭在作怪。
4.CSRF攻擊流程
具體的攻擊流程如下:
5.CSRF的分類
GET型
在web應用中,很多接口通過GET進行數據的請求和存儲,如果未對來源進行校驗,并且沒有token保護,攻擊者可以直接通過發送含有payload的鏈接進行誘導點擊;亦可以通過評論區或類似功能處發布圖片,通過修改img地址的方式保存至頁面,用戶訪問便會進行自動加載造成攻擊
<!-- 不論什么手段,只要能讓受害者訪問一個鏈接即可 --> <img src="https://bank.example.com/withdraw?amount=1000&to=Bob" />POST-表單型
首先,測試時,為了擴大危害,可以嘗試將POST數據包轉換成GET數據包,后端如果采用例如@RequestMaping("/")這種同時接受POST和GET請求的話,就可以成功
利用起來無非也是構造一個自動提交的表單,然后嵌入到頁面中,誘導受害者訪問,受害者訪問后會自動提交表單發起請求
<form action=http://bank.example.com/csrf method=POST> <input type="text" name="amount" value="1000" /> </form> <script> document.forms[0].submit(); </script>POST-JSON型
如果我們發現請求頭中的Content-Type值是application/json,基本上就可以確定采用了前后端分離了
這種一般有4種利用手法:
- json轉param
部分網站可能同時支持json和表單格式,所以我們可以嘗試進行轉換,如把 {"a":"b"} 轉換為 a=b,服務端可能也會解析
- 閉合JSON
構造閉合語句,比較雞肋
- ajax發起請求
當跨域影響用戶數據HTTP請求(如用XMLHttpRequest發送get/post)時,瀏覽器會發送預檢請求(OPTIONS請求)給服務端征求支持的請求方法,然后根據服務端響應允許才發送真正的請求。
HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Access-Control-Allow-Origin: http://localhost:63342 Access-Control-Allow-Credentials: true Access-Control-Max-Age: 1800 Access-Control-Allow-Methods: POST Access-Control-Allow-Headers: content-type,access-control-request-headers,access-control-request-method,accept,origin,x-requested-with Content-Length: 0 Date: Wed, 11 Mar 2015 05:16:31 GMT然而如果服務端對Content-Type進行校驗,則不會響應這個OPTIONS請求,從而利用失敗。但是更多的情況下服務端可能不會校驗Content-Type,或者不會嚴格校驗Content-Type是否為application/json,所以很多情況下這是可用的
payload:
<script>windows.onload = () => {var xhr = new XMLHttpRequest()xhr.open("POST", "http://test.example.com/csrf")xhr.setRequestHeader("Accept", "*/*")xhr.setRequestHeader("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3")xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8")xhr.withCredentials = true // 攜帶cookiexhr.send(JSON.stringify({"a":"b"})} </script>- flash+307跳轉
flash已經被淘汰了
6.CSRF的快速驗證
非JSON的情況下,使用burp可以快速生成POC,也可以自己寫,反正原理都是發起請求即可
修改參數,之后通過BP的瀏覽器進行測試:
訪問BP生成的網址:
提交,可以看到數據已經被修改了,代表存在CSRF漏洞:
7.CSRF的防御
驗證碼
驗證碼被認為是對抗CSRF攻擊最簡潔而有效的防御方法。
CSRF攻擊的過程,往往是在用戶不知情的情況下構造了網絡請求。而驗證碼,則強制用戶必須與應用進行交互,才能完成最終請求。因此在通常情況下,驗證碼能夠很好地遏制CSRF攻擊。但是驗證碼并非萬能。
很多時候,出于用戶體驗考慮,網站不能給所有的操作都加上驗證碼。因此,驗證碼只能作為防御CSRF的一種輔助手段,而不能作為最主要的解決方案。
Referer Check
Referer Check在互聯網中最常見的應用就是“防止圖片盜鏈”。同理,Referer Check也可以被用于檢查請求是否來自合法的“源”。
比如一個“論壇發帖”的操作,在正常情況下需要先登錄到用戶后臺,或者訪問有發帖功能的頁面。在提交“發帖”的表單時,Referer的值必然是發帖表單所在的頁面。如果Referer的值不是這個頁面,甚至不是發帖網站的域,則極有可能是CSRF攻擊。
無法依賴于Referer Check作為防御CSRF的主要手段(黑客可能篡改Referer)。但是通過Referer Check來監控CSRF攻擊的發生,倒是一種可行的方法💎
Anti CSRF Token
CSRF為什么能夠攻擊成功?其本質原因是重要操作的所有參數都是可以被攻擊者猜測到的。
出于這個原因,可以想到一個解決方案:把參數加密,或者使用一些隨機數,從而讓攻擊者無法猜測到參數值。
這樣,在攻擊者不知道salt的情況下,是無法構造出這個URL的,因此也就無從發起CSRF攻擊了
比如,一個刪除操作的URL是:
http://host/path/delete? username=abc&item=123把其中的username參數改成哈希值:
http://host/path/delete? username=md5(salt+abc)&item=123但是這個方法也存在一些問題。首先,加密或混淆后的URL將變得非常難讀,對用戶非常不友好。其次,如果加密的參數每次都改變,則某些URL將無法再被用戶收藏。最后,普通的參數如果也被加密或哈希,將會給數據分析工作帶來很大的困擾,因為數據分析工作常常需要用到參數的明文。
因此,我們需要一個更加通用的解決方案來幫助解決這個問題。這個方案就是使用Anti CSRF Token。
回到上面的URL中,保持原參數不變,新增一個參數Token。這個Token的值是隨機的,不可預測:
http://host/path/delete? username=abc&item=123&token=[random(seed)]由于Token的存在,攻擊者無法再構造出一個完整的URL實施CSRF攻擊。
總結
以上是生活随笔為你收集整理的一文带你学习跨站点请求伪造(CSRF)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OKR使用经验 11-12双月
- 下一篇: 家族文化是一项很重要的文化内涵