什么是CSRF?
跨站請(qǐng)求偽造(也稱為 CSRF)是一種 Web 安全漏洞,允許攻擊者誘導(dǎo)用戶執(zhí)行他們不打算執(zhí)行的操作。它允許攻擊者部分規(guī)避同源策略,該策略旨在防止不同網(wǎng)站相互干擾。
GET?POST?
實(shí)際上,CSRF不只是只有GET請(qǐng)求可以發(fā)起,POST請(qǐng)求也可以發(fā)起。
通常情況下,CSRF一般都是采用<iframe>, <img><script>這些帶有src
屬性的標(biāo)簽發(fā)起的,而這些標(biāo)簽只能發(fā)起一次GET請(qǐng)求,不能發(fā)起一次POST請(qǐng)求,但是對(duì)于有些網(wǎng)站來說,這些操作并沒用嚴(yán)格區(qū)分POST或者GET操作,所以,攻擊者可以使用GET來請(qǐng)求表單的提交地址。比如在PHP中,如果使用的是$_REQUEST獲取變量,而不是$_POST獲取變量,就會(huì)發(fā)生此問題。(這句化就是說,有些網(wǎng)站對(duì)于一些重要的請(qǐng)求操作,應(yīng)該是只能用POST發(fā)起請(qǐng)求的,但是他沒有嚴(yán)格限制,使得GET也能發(fā)起請(qǐng)求)
對(duì)于一個(gè)表單來說,用戶往往可以通過使用GET來提交表單,比如
<form action="/register" id='register' method='POST'>
<input type=text name='username' value=''/>
<input type=password name='password',value=''/>
<input type=submit name='submit' value='submit'>
</form>
我們可以嘗試構(gòu)造一個(gè)GET請(qǐng)求:
http:
/
/
host
/
register?username
=
test&password
=
passwd
如果服務(wù)器沒有對(duì)請(qǐng)求方法進(jìn)行限制,則這個(gè)請(qǐng)求會(huì)通過。
如果服務(wù)器已經(jīng)區(qū)分了POST和GET,對(duì)于只能用POST提交的鏈接,我們也可以構(gòu)造出一個(gè)POST請(qǐng)求。
比如,在一個(gè)頁面中構(gòu)造好一個(gè)form表單,然后使用Javascript自動(dòng)提交這個(gè)表單。比如,攻擊者在www.b.com/test/html下編寫如下代碼:
<form action="http://www.a.com/register" id='register' method='POST'>
<input type=text name='username' value=''/>
<input type=password name='password',value=''/>
<input type=submit name='submit' value='submit'>
</form>
<script>
var f = documentElementById('register');
f.inouts[0].value='test';
f.inputs[1].value='password';
f.submit;
</script>
攻擊者如果將這個(gè)頁面隱藏在一個(gè)不可見的iframe窗口中,則整個(gè)自動(dòng)提交表單的過程,對(duì)于用戶來說也是不可見的。
CSRF 攻擊的影響是什么?
在成功的CSRF 攻擊中。攻擊者會(huì)導(dǎo)致受害者用戶無意中執(zhí)行某項(xiàng)工作。例如,這可能是更改其賬戶上的電子郵件地址,更改密碼或進(jìn)行資金轉(zhuǎn)賬。根據(jù)操作的性質(zhì),攻擊者可能能夠完全控制用戶的賬號(hào)。如果受感染的用戶在應(yīng)用程序中具有特權(quán)角色,那么攻擊者可能能夠完全控制應(yīng)用程序的所有數(shù)據(jù)和功能。
CSRF 是如何工作的?
要使 CSRF 攻擊稱為可能,必須具備三個(gè)關(guān)鍵條件:
一個(gè)相關(guān)的動(dòng)作。應(yīng)用程序中存在攻擊者有理由誘導(dǎo)的操作。這可能是特權(quán)操作(例如修改其他用戶的權(quán)限)或?qū)τ脩籼囟〝?shù)據(jù)的任何動(dòng)作(例如更改用戶自己的密碼)。
基于 Cookie 的會(huì)話處理。執(zhí)行該操作涉及發(fā)出一個(gè)或多個(gè)HTTP請(qǐng)求,并且應(yīng)用程序僅依賴會(huì)話 cookie 來識(shí)別發(fā)出請(qǐng)求的用戶。沒有其他機(jī)制可用于跟蹤會(huì)話或驗(yàn)證用戶請(qǐng)求。
沒有不可預(yù)測(cè)的請(qǐng)求參數(shù)。執(zhí)行該操作的請(qǐng)求不包含攻擊者無法確定或猜測(cè)其值的任何參數(shù)。例如,當(dāng)導(dǎo)致用戶更改密碼時(shí),如果攻擊者需要知道現(xiàn)有密碼的值,則該功能不會(huì)受到攻擊。
例如,假設(shè)一個(gè)應(yīng)用程序包含一個(gè)允許用戶更改其賬戶上的電子郵件地址的功能。當(dāng)用戶執(zhí)行此操作時(shí),他們會(huì)發(fā)出如下 HTTP 請(qǐng)求:
POST /email/change HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 30
Cookie: session=yvthwsztyeQkAPzeQ5gHgTvlyxHfsAfE
email=wiener@normal-user.com
這符合 CSRF 所需的條件:
攻擊者都更改用戶賬戶上的電子郵件地址的操作很感興趣。執(zhí)行此操作后,攻擊者通常能夠觸發(fā)密碼重置并完全控制用戶的賬戶。
應(yīng)用程序使用會(huì)話 cookie 來識(shí)別發(fā)出請(qǐng)求的用戶。沒有其他令牌或機(jī)制來跟蹤用戶會(huì)話。
攻擊者可以輕松確定執(zhí)行操作所需的請(qǐng)求參數(shù)的值。
有了這些條件,攻擊者就可以構(gòu)建一個(gè)包含以下HTML的網(wǎng)頁:
<html>
<body>
<form action="https://vulnerable-website.com/email/change" method="POST">
<input type="hidden" name="email" value="pwned@evil-user.net" />
</form>
<script>
document.forms[0].submit();
</script>
</body>
</html>
如果受害者用戶訪問攻擊者的網(wǎng)頁,將會(huì)發(fā)送以下情況:
攻擊者的頁面將觸發(fā)對(duì)易受攻擊者的網(wǎng)站的HTTP 請(qǐng)求。
如果用戶登錄到易受攻擊的網(wǎng)站,他們的瀏覽器將自動(dòng)在請(qǐng)求中包含他們的會(huì)話 cookie (假設(shè)未使用SameSite cookie)。
易受攻擊的網(wǎng)站將以正常的方式處理請(qǐng)求,將其為由受害者用戶發(fā)出,并更改電子郵件地址。
備注
盡管 CSRF 通常與基于 cookie 的會(huì)話處理有關(guān),但它也出現(xiàn)在應(yīng)用程序自動(dòng)將一些用戶憑據(jù)添加到請(qǐng)求的其他上下文中,例如 HTTP 基本身份驗(yàn)證和基于證書的身份驗(yàn)證。
使用Burp Suite 插件 構(gòu)建 CSRF 攻擊
手動(dòng)創(chuàng)建 CSRF 漏洞利用所需的 HTML 可能很麻煩,特別是在所需的請(qǐng)求包含大量參數(shù)或請(qǐng)求中有其他怪癖的情況下。構(gòu)建 CSRF 漏洞利用的最簡(jiǎn)單方法是使用內(nèi)置于Burp Suite Professional的CSRF PoC 生成器:
在 Burp Suite Professional 中的任意位置選擇您要測(cè)試或利用的請(qǐng)求。
• 從右鍵單擊上下文菜單中,選擇參與工具/生成 CSRF PoC。
• Burp Suite 將生成一些 HTML 來觸發(fā)選定的請(qǐng)求(減去 cookie,它將由受害者的瀏覽器自動(dòng)添加)。
• 您可以調(diào)整 CSRF PoC 生成器中的各種選項(xiàng),以微調(diào)攻擊的各個(gè)方面。您可能需要在一些不尋常的情況下執(zhí)行此操作以處理請(qǐng)求的古怪功能。
• 將生成的 HTML 復(fù)制到網(wǎng)頁中,在登錄到易受攻擊網(wǎng)站的瀏覽器中查看,并測(cè)試是否成功發(fā)出了預(yù)期的請(qǐng)求以及是否發(fā)生了所需的操作。
CSRF 攻擊條件及與XSS區(qū)別
CSRF 與XSS 區(qū)別:
XSS: 存在XSS漏洞 ——> 構(gòu)造 payload ——> 發(fā)送給受害者 ——> 受害者觸發(fā) ——> 攻擊者得到受害者cookie ——> 攻擊者使用受害者權(quán)限cookie 登錄系統(tǒng)
CSRF: 存在CSRF漏洞 ——> 構(gòu)造payload ——> 發(fā)送給受害者 ——> 受害人點(diǎn)擊打開 ——> 受害人執(zhí)行代碼 ——> 受害者完成攻擊(不知情)
CSRF攻擊一種需要兩個(gè)條件:
1.登錄受信任的網(wǎng)站,本地生成Cookie;
2.在不注銷A情況下,可以訪問網(wǎng)站B
當(dāng)然還要另一些方法滿足CSRF攻擊條件,你無法保證以下情況不會(huì)發(fā)生:
1.不能保證登錄了一個(gè)網(wǎng)站,不再打開另一個(gè)頁面并訪問另外的網(wǎng)站。
2.你不能保證你關(guān)閉了瀏覽器后,本地Cookie立刻過期,并且登錄的會(huì)話未結(jié)束。
由此 CSRF 是一種較難防御,又危險(xiǎn)極大的漏洞!
常規(guī)測(cè)試方法
如何確認(rèn)一個(gè)web系統(tǒng)存在csrf漏洞
1,對(duì)目標(biāo)網(wǎng)站增刪改的地方進(jìn)行標(biāo)記,并觀察其邏輯,判斷請(qǐng)求是否可以被偽造。
–比如修改管理員賬號(hào)時(shí) ,并不需要驗(yàn)證舊密碼 ,導(dǎo)致請(qǐng)求容易被偽造;
–比如對(duì)于敏感信息的修改并沒有使用安全的token驗(yàn)證,導(dǎo)致請(qǐng)求容易被偽造;
2.確認(rèn)憑證的有效期(這個(gè)問題會(huì)提高CSRF被利用的概率)
—雖然退出或者關(guān)閉了瀏覽器,但cookie仍然有效,或者session并沒有及時(shí)過期,導(dǎo)致CSRF攻擊變的簡(jiǎn)單
CSRF是借用戶的權(quán)限完成攻擊,攻擊者并沒有拿到用戶的權(quán)限,而XSS是直接盜取了用戶的權(quán)限,然后實(shí)施破壞。
如何確認(rèn)一個(gè)web系統(tǒng)存在CSRF漏洞
1.對(duì)目標(biāo)網(wǎng)站增刪改的地方進(jìn)行標(biāo)記,并觀察其邏輯,判斷請(qǐng)求是否可以被偽造
確認(rèn)憑證的有效期(這個(gè)問題會(huì)提高CSRF被利用的概率)
CSRF(get/post)實(shí)驗(yàn)演示和解析
CSRFget
我們假設(shè)我們是Lucy,登陸網(wǎng)站修改信息。
我們點(diǎn)擊修改信息并提交,修改成功。我們打開burp查看抓到的數(shù)據(jù)包
這是我們的請(qǐng)求:GET/vul/csrf/csrfget/csrf_get_edit.phpsex=5&phonenum=54151&add=411&email=www&submit=submit
我們并沒有看到CSRF的token,說明并沒有防CSRF的措施。
修改get請(qǐng)求,將地址411修改為shanxi
跨站請(qǐng)求及跨站請(qǐng)求偽造(CSRF)
繞過csrf校驗(yàn):
1.刪除CSRF令牌,不校驗(yàn)。
2.通過變換請(qǐng)求,如POST更換GET,但在使用GET方法時(shí)跳過驗(yàn)證。(變換請(qǐng)求方法)
3.應(yīng)用程序在令牌存在時(shí)驗(yàn)證令牌,但如果省略令牌則跳過驗(yàn)證。(刪除csrf參數(shù))
4.令牌不綁定用戶會(huì)話(用戶加載時(shí)獲取csrf token,替換用戶token)
5.csrf cookie和csrf令牌綁定(替換攻擊者的csrf cookie和csrf令牌)
《借刀殺人》
CSRF 構(gòu)造/發(fā)布請(qǐng)求,已經(jīng)讓用戶在事先不知道的情況下,讓cookie送出cookie的請(qǐng)求,而不是事發(fā)先發(fā)送給用戶的”HTTP 請(qǐng)求”。
CSRF類型
CSRF 按類型分
GET - 使用方式使受害者點(diǎn)擊構(gòu)造的 url 發(fā)出 GET 請(qǐng)求http://get.csrfvul.com/payto?name=hacker&moneynumb=100
POST - 可以使用方式轉(zhuǎn)換為 GET(可嘗試將post請(qǐng)求體改成get形式放至url參數(shù)中如果使用正常響應(yīng)請(qǐng)求GET請(qǐng)求進(jìn)行csrf攻擊)
【危害2】漏洞聯(lián)合——CSRF漏洞使self-XSS漏洞“變廢為寶”
存在self-XSS直接漏洞和CSRF漏洞,如果利用self-XSS漏洞則受害者只是自己,如何攻擊自己以外的目標(biāo)?
目標(biāo)——通過利用CSRF漏洞,使XSSpayload能夠攻擊自己以外的目標(biāo)
過程
構(gòu)造:攻擊者利用CSRF漏洞構(gòu)造出HTTP請(qǐng)求向vul.com;
HTTP Request Body中包含了“觸發(fā)self-XSS漏洞的payload”
觸發(fā):所以當(dāng)victim(點(diǎn)擊鏈接等)觸發(fā)CSRF漏洞時(shí),會(huì)發(fā)出HTTP請(qǐng)求到vul.comvul.com
,實(shí)現(xiàn)受害者在下被XSS攻擊
【危害3】利用CSRF漏洞發(fā)出GET請(qǐng)求
漏洞影響
網(wǎng)絡(luò)場(chǎng)景測(cè)試技巧
請(qǐng)求相同重放 - 智能識(shí)別令牌是否正確滿足設(shè)計(jì):token動(dòng)態(tài)生成 token會(huì)被后端驗(yàn)證且只能被驗(yàn)證一次 經(jīng)過后端驗(yàn)證后的token立即失效
修改令牌值 - 如修改請(qǐng)求正文并發(fā)送請(qǐng)求,查看響應(yīng)正文是否和正常請(qǐng)求的響應(yīng)正文相同
刪除令牌值 - 如修改請(qǐng)求正文para1=aaa&token=
并發(fā)送請(qǐng)求,查看響應(yīng)正文是否和正常請(qǐng)求的響應(yīng)正文相同
完全刪除令牌參數(shù) - 如修改請(qǐng)求正文為para1=aaa
并發(fā)送請(qǐng)求,查看響應(yīng)正文是否和正常請(qǐng)求的響應(yīng)正文相同
HTTP 方法可以由 POST 正確轉(zhuǎn)換為請(qǐng)求method
,如果可以為 GET 方法
瀏覽器的Cookie策略
若能知道瀏覽器的cookie策略,就會(huì)對(duì)CSRF的原理與攻擊方式會(huì)有更深的理解。
瀏覽器所持有的cookie分成兩種,一種是Session Cookie
,叫做臨時(shí)Cookie
,一種是Third-party Cookie
,叫做本地Cookie,也叫做第三方Cookie。
他們之間的區(qū)別在于本地Cookie
是服務(wù)器在Set-Cookie時(shí)設(shè)置了指定的Expire
時(shí)間,只有到了制定的Expire
之后,本地Cookie才會(huì)失效,所以這種Cookie保存在本地。
而臨時(shí)Cookie則沒用綁定Expire
,所以當(dāng)瀏覽器關(guān)閉后,臨時(shí)Cookie也就會(huì)失效了,所以這種臨時(shí)Cookie保存在瀏覽器中。
在瀏覽網(wǎng)站的過程中,如果一個(gè)網(wǎng)站設(shè)置了臨時(shí)Cookie
, 那么在瀏覽器的運(yùn)行過程中,即使瀏覽器打開了新的網(wǎng)頁,臨時(shí)Cookie
也是有效的。
第三方Cookie
是什么:如果我們?cè)L問http://www.a.com
,那么http://www.a.com
就是第一方,如果我們?cè)?code style=";padding: 0px;outline: 0px;user-select: initial !important;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important">http://www.a.com的頁面中,在去訪問http://www.b.com
,那么http://www.b.com
就是第三方。
如果有這么一種情況,瀏覽器從一個(gè)域的頁面中,想要加載另一個(gè)域的資源,由于安全原因,一些網(wǎng)絡(luò)站點(diǎn)會(huì)停止本地Cookie
即第三方Cookie的
發(fā)送。就是說,我們已經(jīng)獲得了http://www.b.com
的cookie值,當(dāng)我們?cè)?code style=";padding: 0px;outline: 0px;user-select: initial !important;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important">http://www.a.com 頁面訪問包含在http://www.a.com
頁面中的http://www.b.com
的鏈接時(shí),仍然不會(huì)把之前獲得的http://www.b.com
的cookie值發(fā)送過去
但是這里也是有一個(gè)前提的,就是http://a.com
頁面包含在http://a.com
頁面中的http://www.b.com
的鏈接時(shí),仍然不會(huì)把之前獲得的http://www.b.com
的cookie值發(fā)過去。
但是這里也是有一個(gè)前提的,就是http://www.a.com頁面中的http://www.b.com包含在<iframe>, <img>, <script> , <link> 等標(biāo)簽中,因?yàn)檫@些標(biāo)簽在IE中,是禁止瀏覽器向這些標(biāo)簽中發(fā)送第三方cookie的。
當(dāng)然,并不是所有的瀏覽器都會(huì)禁止,比如火狐瀏覽器,就默認(rèn)支持發(fā)送第三方cookie。
所以至少對(duì)于IE瀏覽器,攻擊者需要精心構(gòu)造攻擊環(huán)境,比如可以先誘使用戶在當(dāng)前瀏覽器中先訪問目標(biāo)站點(diǎn),使得session cookie有效,然后嘗試CSRF。
P3P頭的副作用
盡管對(duì)于有些CSRF來說,并不是很需要cookie的,但大部分的敏感信息或重要操作都躲藏在認(rèn)證之后,因此瀏覽器攔截第三方cookie的發(fā)送,一定程度上還是降低了CSRF的威力,可是P3P頭的出現(xiàn),使得一切復(fù)雜起來。
P3P Header 是W3C制定的一項(xiàng)關(guān)于隱私的標(biāo)準(zhǔn),全稱是The Platform for Privacy Preferences.
如果網(wǎng)站返回給瀏覽器的HTTP頭部中包含有PHP3頭,則在某種程度上來說,他會(huì)允許瀏覽器發(fā)送第三方cookie,即使是在上文所描述的IE瀏覽器<iframe>
、<input>
也將不在攔截第三方cookie的發(fā)送。
比如存在www.a.com和www.b.com兩個(gè)域,在www.b上存在一個(gè)頁面,他是包含www.a.com的一個(gè)iframe。
http://www.b.com
的內(nèi)容為<iframe width=20 height=30 src=http://www.a.com/test.php></iframe>
然后http://www.a.com/test.php
是對(duì)a.com域設(shè)置cookie的頁面,其內(nèi)容為<?php header("set-cookie:test=axis;path=/")?>
總之這個(gè)頁面就是為www.a.com設(shè)置cookie。當(dāng)我們?cè)?code style=";padding: 0px;outline: 0px;user-select: initial !important;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important">http://www.b.com這個(gè)頁面時(shí),點(diǎn)擊包含www.a.com的頁面,那么就會(huì)轉(zhuǎn)到http://www.a.com/test.php
嘗試設(shè)置cookie,所以瀏覽器會(huì)收到一個(gè)cookie。然而等之后,我們?cè)谌c(diǎn)擊這個(gè)點(diǎn)擊包含www.a.com的頁面,如果上次點(diǎn)擊設(shè)置cookie成功,那么這次點(diǎn)擊就會(huì)自動(dòng)發(fā)送剛才收到的cookie,可是由于cookie跨域限制,上次點(diǎn)擊沒有設(shè)置成功cookie,所以這次訪問,還是再次接收到和上次一樣的cookie,說明上次的cookie并沒有發(fā)送出去。
但是如果加入了P3P頭之后,這種情況就會(huì)發(fā)生改變,第二次點(diǎn)擊那個(gè)頁面就會(huì)發(fā)出第一次收到的cookie值。
因?yàn)镻3P頭在網(wǎng)站中的廣泛應(yīng)用,所以在CSRF的防御,不能僅依賴于瀏覽器對(duì)第三方cookie的防御策略,應(yīng)該從長(zhǎng)計(jì)議。
CSRF的防御
常見CSRF防范措施
增加token驗(yàn)證(常用多點(diǎn)做法 ):
1.對(duì)關(guān)鍵操作增加token參數(shù),token值必須隨機(jī),每次都不一樣;
關(guān)于安全的會(huì)話管理(避免會(huì)話被利用):
1.不要在客戶端端保存敏感信息(比如身份認(rèn)證信息);
2.測(cè)試直接關(guān)閉,退出時(shí),的會(huì)話過期機(jī)制;
3.設(shè)置會(huì)話過期機(jī)制,比如15分鐘內(nèi)無操作,則自動(dòng)登錄超時(shí);
訪問控制安全管理:
1.敏感信息修改時(shí)需要對(duì)身份進(jìn)行二次認(rèn)證,比如修改賬號(hào)時(shí),需要判斷舊密碼;
2.敏感信息的修改使用post,而不是get;
3.通過http頭部中的referer來限制原頁面
增加驗(yàn)證碼:
一般用在登錄(防暴力破解),也可以用在其他重要信息操作的表單中(需要考慮可用性)
簽名與時(shí)間戳防護(hù)處理流程
Token產(chǎn)生
1.Token構(gòu)成
為了防止CSRF攻擊,Token要求不能重復(fù),需要含有時(shí)間戳信息,簽名信息。
下面的圖描述了一個(gè)token的數(shù)據(jù)構(gòu)成:
Token的數(shù)據(jù)結(jié)構(gòu)。
token由三部分組成:
a). 消息[msg]:而msg本身也有兩部分組成:一部分:隨機(jī)字符串,過期時(shí)間戳。
b). 分割符[separator]:用于分隔msg部分與加密后生成的signature簽名部分,這里用的是”.“
c). 簽名[signature]:signature。signature簽名,是對(duì)“msg消息”用特定算法進(jìn)行加密后的串。
CSRF攻擊常規(guī)防護(hù)
1.只使用JSON API,使用Javascript發(fā)起AJAX請(qǐng)求是限制跨域的,并不能通過簡(jiǎn)單的表單來發(fā)送JSON,所以,通過只接收J(rèn)SON可以很大可能避免CSRF攻擊。
2.驗(yàn)證HTTP Referer字段,根據(jù) HTTP 協(xié)議,在 HTTP 頭中有一個(gè)字段叫Referer,它記錄了該HTTP 請(qǐng)求的來源地址。在通常情況下,訪問一個(gè)安全受限頁面的請(qǐng)求來自于同一個(gè)網(wǎng)站,比如上文用戶User想要在網(wǎng)站W(wǎng)ebA中進(jìn)行轉(zhuǎn)賬操作,那么用戶User
3.必須先登錄WebA,然后通過點(diǎn)擊頁面上的按鈕觸發(fā)轉(zhuǎn)賬事件。
這時(shí)該轉(zhuǎn)賬請(qǐng)求的 Referer 值就會(huì)是轉(zhuǎn)賬按鈕所在的頁面的URL,而如果黑客要對(duì)銀行網(wǎng)站實(shí)施CSRF攻擊,他只能在他自己的網(wǎng)站構(gòu)造請(qǐng)求,當(dāng)用戶User通過黑客的網(wǎng)站發(fā)送請(qǐng)求到WebA時(shí),該請(qǐng)求的Referer 是指向黑客自己的網(wǎng)站。
因此,要防御 CSRF 攻擊,網(wǎng)站W(wǎng)ebA只需要對(duì)于每一個(gè)轉(zhuǎn)賬請(qǐng)求其Referer值,如果是以網(wǎng)站webA的網(wǎng)址開頭的域名,則說明該請(qǐng)求時(shí)來自WebA自己多點(diǎn)請(qǐng)求,時(shí)合法的,如果 Referer 是其他網(wǎng)址的話,則有可能是黑客的CSRF攻擊,拒絕該請(qǐng)求。
4.在請(qǐng)求地址添加token驗(yàn)證
CSRF 攻擊之所以能偶成功,是因?yàn)楹诳涂梢酝耆珎卧煊脩舻恼?qǐng)求,該請(qǐng)求中所有的用戶驗(yàn)證信息都是存在于cookie中,因此黑客可以在不知道這些驗(yàn)證信息的情況下直接利用用戶自己的cookie來通過安全驗(yàn)證。要抵御CSRF,關(guān)鍵在于請(qǐng)求中放入黑客無所不能偽造的信息,并且該信息存在于cookie之中。可以在HTTP請(qǐng)求中以參數(shù)的形式加入一個(gè)隨機(jī)產(chǎn)生的token,并在服務(wù)器端建立一個(gè)攔截器來驗(yàn)證這個(gè)token,如果請(qǐng)求中沒有token或者token內(nèi)容不正確,則認(rèn)為可能是CSRF攻擊而拒絕該請(qǐng)求。
這種方法要比檢查Referer 要安全一些,token 可以在用戶登錄參生并放于 session 之中,然后再每次請(qǐng)求時(shí)把token從session中拿出,與請(qǐng)求中的token進(jìn)行比對(duì)。
驗(yàn)證碼
驗(yàn)證碼是對(duì)抗CSRF最簡(jiǎn)單,最有效的防御方法。
CSRF攻擊的過程,往往是在用戶不知情的情況下,構(gòu)造網(wǎng)絡(luò)請(qǐng)求。而驗(yàn)證碼,則強(qiáng)制用戶必須與應(yīng)用進(jìn)行交互,才能完成最終請(qǐng)求。因此在通常情況下,驗(yàn)證碼的存在能很好地遏制CSRF。
但是驗(yàn)證碼并不方便,對(duì)用戶體驗(yàn)并不友好,所以他只能作為一種備選策略存在,無法作為主方法。
Referer Check
Referer Check即參考檢查,其實(shí)他在互聯(lián)網(wǎng)中最常見的應(yīng)用應(yīng)該是防止圖片盜鏈
,但是他也可以用來檢查請(qǐng)求是否存在合法的源
。
常見的互聯(lián)網(wǎng)應(yīng)用,頁面與頁面之間都具有一定的邏輯關(guān)系,這就使得每一個(gè)正常請(qǐng)求的Referer具有一定的規(guī)律。
比如一個(gè)‘論壇發(fā)帖’的操作,在正常情況下,需要先登錄到用戶后臺(tái),或者訪問有發(fā)帖功能的頁面。在提交發(fā)帖的表單時(shí),Referer的值必然是發(fā)帖表單所在的頁面,但如果Referer的值不是這個(gè)頁面,甚至不是發(fā)帖網(wǎng)站的域,那么極大可能就是CSRF攻擊。
但是Referer Check的缺陷也很明顯,服務(wù)器并不是任何時(shí)候都能獲取到Referer,很多用戶出于隱私的考慮,限制了Referer的發(fā)送,而對(duì)于瀏覽器也是同理,某些情況下,比如從HTTPS跳轉(zhuǎn)到HTTP,瀏覽器也不會(huì)發(fā)送Referer。
所以,Referer Check其實(shí)也不是一個(gè)特別好的防御手段,只能作為防御的備用策略。
使用token
CSRF的本質(zhì)
在講token之前,我們需要知道,CSRF之所以能夠攻擊成功,除了利用cookie,更重要
攻擊者只有預(yù)測(cè)出URL的所有參數(shù)與參數(shù)值,才能成功構(gòu)造一個(gè)偽造的請(qǐng)求,反之,則攻擊不成功
基于此,有一個(gè)解決方案,把參數(shù)加密,或者使用一些隨機(jī)數(shù),讓攻擊者無法猜測(cè)到正確的參數(shù)。
比如,一個(gè)刪除的url是:
http://www.a.com/require?username=123&item=123
但是可以通過參數(shù)加密,使得刪除的url值為:
http://www.a.com/require?username=1f69f7d19e9455605f6d941de5257ee1&item=123
這樣就無法猜測(cè)出username的值,從而無法實(shí)施攻擊
但這種方法存在的缺陷是,加密后的URL非常難讀,對(duì)用戶不友好,其次,如果每次URL值都發(fā)生變化,還會(huì)使得URL無法被用戶收藏。所以這種方法有了一個(gè)晉升版,就是構(gòu)造token。
Token的特點(diǎn)
1、Token值必須是隨機(jī)的,可以通過使用安全的隨機(jī)數(shù)生成算法實(shí)現(xiàn)
2、Token值是私密的,不能被第三方知曉。他可以存放在服務(wù)器的cookie中,也可以存放在瀏覽器的cookie中。但唯獨(dú)Token值不能直接放在URL中,因?yàn)橹苯臃旁赨RL中,可能也會(huì)導(dǎo)致瀏覽器通過Refer得方式泄露。
比如下面這個(gè)頁面
http://www.a.com/manage?username=abc&token={隨機(jī)值}
如果在這個(gè)頁面中包含了一個(gè)攻擊者能指定地址的圖片,比如
<img src="http://www.b.com/a">
那么如果點(diǎn)擊這個(gè)圖片,那么可能就會(huì)出現(xiàn)http://www.a.com/manage?username=abc&token={隨機(jī)值}
作為HTTP請(qǐng)求的Referer發(fā)送到http://www.b.com
這個(gè)域中,從而導(dǎo)致Token的泄露。
因此在使用Token時(shí),盡量將其放在表單中,把敏感操作由GET改成POST,以表單的形式提交,避免Token泄露
3、Token需要同時(shí)放在表單和session中。在提交請(qǐng)求時(shí),服務(wù)器只需要驗(yàn)證表單中的Token與用戶session(或者cookie)中的Token值是否相同,如果一致,則是合法請(qǐng)求,如果不一致,或者有一個(gè)為空,則請(qǐng)求不合法,就可能是CSRF攻擊
CSRF 漏洞防御策略
再服務(wù)器端防御CSRF攻擊主要有四種策略:
根據(jù)HTTP協(xié)議,在HTTP頭中有一個(gè)字段叫Referer,它記錄了該HTTP請(qǐng)求的來源地址。在通常情況下,訪問一個(gè)安全受限頁面的請(qǐng)求必須來自于同一個(gè)網(wǎng)站。比如某銀行的轉(zhuǎn)賬是通過用戶訪問http://bank.test/test?page=10&userID=101&money=10000頁面完成,用戶必須先登錄bank.test,然后通過點(diǎn)擊頁面上的按鈕來觸發(fā)轉(zhuǎn)賬事件。當(dāng)用戶提交請(qǐng)求時(shí),該轉(zhuǎn)賬請(qǐng)求的Referer值就會(huì)是轉(zhuǎn)賬按鈕所在頁面的URL(本例中,通常是以bank. test域名開頭的地址)。而如果攻擊者要對(duì)銀行網(wǎng)站實(shí)施CSRF攻擊,他只能在自己的網(wǎng)站構(gòu)造請(qǐng)求,當(dāng)用戶通過攻擊者的網(wǎng)站發(fā)送請(qǐng)求到銀行時(shí),該請(qǐng)求的Referer是指向攻擊者的網(wǎng)站。因此,要防御CSRF攻擊,銀行網(wǎng)站只需要對(duì)于每一個(gè)轉(zhuǎn)賬請(qǐng)求驗(yàn)證其Referer值,如果是以bank. test開頭的域名,則說明該請(qǐng)求是來自銀行網(wǎng)站自己的請(qǐng)求,是合法的。如果Referer是其他網(wǎng)站的話,就有可能是CSRF攻擊,則拒絕該請(qǐng)求。
• 在請(qǐng)求地址中添加token并驗(yàn)證
CSRF攻擊之所以能夠成功,是因?yàn)楣粽呖梢詡卧煊脩舻恼?qǐng)求,該請(qǐng)求中所有的用戶驗(yàn)證信息都存在于Cookie中,因此攻擊者可以在不知道這些驗(yàn)證信息的情況下直接利用用戶自己的Cookie來通過安全驗(yàn)證。由此可知,抵御CSRF攻擊的關(guān)鍵在于:在請(qǐng)求中放入攻擊者所不能偽造的信息,并且該信息不存在于Cookie之中。鑒于此,系統(tǒng)開發(fā)者可以在HTTP請(qǐng)求中以參數(shù)的形式加入一個(gè)隨機(jī)產(chǎn)生的token,并在服務(wù)器端建立一個(gè)攔截器來驗(yàn)證這個(gè)token,如果請(qǐng)求中沒有token或者token內(nèi)容不正確,則認(rèn)為可能是CSRF攻擊而拒絕該請(qǐng)求。
• 在HTTP頭中自定義屬性并驗(yàn)證
自定義屬性的方法也是使用token并進(jìn)行驗(yàn)證,和前一種方法不同的是,這里并不是把token以參數(shù)的形式置于HTTP請(qǐng)求之中,而是把它放到HTTP頭中自定義的屬性里。通過XMLHttpRequest這個(gè)類,可以一次性給所有該類請(qǐng)求加上csrftoken這個(gè)HTTP頭屬性,并把token值放入其中。這樣解決了前一種方法在請(qǐng)求中加入token的不便,同時(shí),通過這個(gè)類請(qǐng)求的地址不會(huì)被記錄到瀏覽器的地址欄,也不用擔(dān)心token會(huì)通過Referer泄露到其他網(wǎng)站。
Token 防御 CSRF Example
針對(duì)使用token 防御 CSRF 攻擊,我這里做一個(gè)簡(jiǎn)單的介紹:
1.要使Token對(duì)攻擊者來說難以偽造,我們可以使用偽隨機(jī)數(shù)生成器來構(gòu)造它 稱為Token 隨機(jī)數(shù),好似在沒一個(gè)參數(shù)中都加入一個(gè)隨機(jī)的Token來此防御,然后把它放到服務(wù)器端的session里,并將Token發(fā)給用戶(注意并沒有保存在cookie中);
2.當(dāng)用戶提交請(qǐng)求時(shí),服務(wù)器攔截器將POST請(qǐng)求中的Token提取出來,與session中的Token進(jìn)行比對(duì),相等即執(zhí)行下一步操作。(這一部分就非常有必要!否則添加了防御的CSRF也是可以繞過的!)
具體代碼:
# 生成 token
session_start();
function set_token(){
$_SESSION['token'] = md5(time()+rand(1,5000));
}
# 使用 token 做驗(yàn)證
function check_token(){
if(isset($_POST['token'])&&$_POST['token'] === $_SESSION['token'])
{
return ture;
}
else
{
return false;
}
}
可以看到,同時(shí)驗(yàn)證了cookie中的sessionid與POST中的Token。
### SDL - 防御與修復(fù)方案
* web框架 - 啟動(dòng)框架中成熟的CSRF防御功能
* 自定義HTTP請(qǐng)求頭(Custom Request Headers)
* 如使用`X-CSRF-token:xxxx`標(biāo)明CSRF_TOKEN的值(即使CSRF利用成功發(fā)出了攜帶Cookie的HTTP請(qǐng)求 但后端判斷`X-CSRF-token`不存在則拒絕請(qǐng)求)
* One-time Token
* 如每次提交表單都包含字段`Token=xxxx`且每次值不同 后端可校驗(yàn)是否正確
* `Set-Cookie`使用`SameSite`屬性
* 后端Response Header`Set-Cookie`中設(shè)置`SameSite`屬性(由Google引入瀏覽器 用于緩解CSRF攻擊),`SameSite`屬性有3種值:
* `Strict`嚴(yán)格
* 例如 域b.com的Response Header有`Set-Cookie: admin_cookie_strict=xxx; SameSite=Strict`,瀏覽器中會(huì)保存這一Cookie字段`admin_cookie_strict=xxx`,但由于`SameSite=Strict`為**嚴(yán)格**,所以瀏覽器對(duì)(非b.com域下發(fā)起的)訪問b.com的**任何跨域請(qǐng)求**都不允許攜帶這一Cookie字段`admin_cookie=xxx`,所以可以防御CSRF攻擊。比如從域a.com下構(gòu)造并發(fā)出跨域請(qǐng)求訪問b.com(嘗試CSRF),絕對(duì)不會(huì)攜帶關(guān)鍵的cookie,從而b.com后端鑒權(quán)失敗,CSRF攻擊失敗
* `Lax`寬松 - 沒有`SameSite`屬性的cookie被瀏覽器默認(rèn)為`SameSite=Lax`
* 例如 域b.com的Response Header有`Set-Cookie: admin_cookie_lax=xxx; SameSite=Lax`,瀏覽器中會(huì)保存這一Cookie字段`admin_cookie_lax=xxx`,但由于`SameSite=Strict`為**寬松**,所以瀏覽器對(duì)(非b.com域下發(fā)起的)訪問b.com的**多種跨域請(qǐng)求**都不允許攜帶這一Cookie字段,只有以下3種方式(任何一種),才能夠攜帶b.com的cookie`admin_cookie_lax=xxx`
* 非同域下的a標(biāo)簽 `<a href="http://b.com"></a>`
* 非同域下的GET表單 `<form method="GET" action="http://b.com/formdemo">`
* 非同域下的link標(biāo)簽 `<link rel="prerender" href="http://b.com"/>`
* `None`無
* `SameSite=None`必須同時(shí)指定`Secure`,例如`Set-Cookie: session_none=abc123; SameSite=None; Secure`
* 二次驗(yàn)證 - 安全但影響用戶體驗(yàn)(適用于僅對(duì)敏感功能處進(jìn)行防御)
* CAPTCHA 增加驗(yàn)證碼機(jī)制
* 再次輸入密碼
* 手機(jī)驗(yàn)證碼
* (不推薦)通過`Referer/Origin`校驗(yàn)來源域名
* 缺陷1.只能防御從"不被信任"的域發(fā)起的偽造的http請(qǐng)求(如果 **父、子、兄弟域名** 或 **CORS中被信任的域名** 有XSS漏洞 配合構(gòu)造一個(gè)偽造請(qǐng)求 此時(shí)referer和Origin的值都是被信任的域 此時(shí)“校驗(yàn)來源域名”無法防御)
* 缺陷2.正常業(yè)務(wù)如果有302跳轉(zhuǎn) 不攜帶Origin
參考OWASP [Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md)
文章來自于互聯(lián)網(wǎng),只做交流分享,如有侵權(quán)請(qǐng)聯(lián)系刪除!原文鏈接:https://www.kanxue.com/chm.htm?id=18479&pid=node1001515
該文章在 2023/12/7 11:18:32 編輯過