摘要:,中文為跨站請(qǐng)求偽造是一種利用網(wǎng)站可信用戶的權(quán)限去執(zhí)行未授權(quán)的命令的一種惡意攻擊。防范技術(shù)令牌同步模式,簡稱是在用戶請(qǐng)求的頁面中的所有表單中嵌入一個(gè),在服務(wù)端驗(yàn)證這個(gè)的技術(shù)。
CSRF(Cross-site request forgery,中文為跨站請(qǐng)求偽造)是一種利用網(wǎng)站可信用戶的權(quán)限去執(zhí)行未授權(quán)的命令的一種惡意攻擊。通過偽裝可信用戶的請(qǐng)求來利用信任該用戶的網(wǎng)站,這種攻擊方式雖然不是很流行,但是卻難以防范,其危害也不比其他安全漏洞小。
本文將簡要介紹CSRF產(chǎn)生的原因以及利用方式,然后對(duì)如何避免這種攻擊方式提供一些可供參考的方案,希望廣大程序猿們都能夠?qū)@種攻擊方式有所了解,避免自己開發(fā)的應(yīng)用被別人利用。
CSRF也稱作one-click attack或者session riding,其簡寫有時(shí)候也會(huì)使用XSRF。
[TOC]
本文將會(huì)持續(xù)修正和更新,最新內(nèi)容請(qǐng)參考我的 GITHUB 上的 程序猿成長計(jì)劃 項(xiàng)目,歡迎 Star,更多精彩內(nèi)容請(qǐng) follow me。
什么是CSRF?簡單點(diǎn)說,CSRF攻擊就是 攻擊者利用受害者的身份,以受害者的名義發(fā)送惡意請(qǐng)求。與XSS(Cross-site scripting,跨站腳本攻擊)不同的是,XSS的目的是獲取用戶的身份信息,攻擊者竊取到的是用戶的身份(session/cookie),而CSRF則是利用用戶當(dāng)前的身份去做一些未經(jīng)過授權(quán)的操作。
CSRF攻擊最早在2001年被發(fā)現(xiàn),由于它的請(qǐng)求是從用戶的IP地址發(fā)起的,因此在服務(wù)器上的web日志中可能無法檢測到是否受到了CSRF攻擊,正是由于它的這種隱蔽性,很長時(shí)間以來都沒有被公開的報(bào)告出來,直到2007年才真正的被人們所重視。
CSRF有哪些危害CSRF可以盜用受害者的身份,完成受害者在web瀏覽器有權(quán)限進(jìn)行的任何操作,想想吧,能做的事情太多了。
以你的名義發(fā)送詐騙郵件,消息
用你的賬號(hào)購買商品
用你的名義完成虛擬貨幣轉(zhuǎn)賬
泄露個(gè)人隱私
...
產(chǎn)生原理以及利用方式要完成一個(gè)CSRF攻擊,必須具備以下幾個(gè)條件:
受害者已經(jīng)登錄到了目標(biāo)網(wǎng)站(你的網(wǎng)站)并且沒有退出
受害者有意或者無意的訪問了攻擊者發(fā)布的頁面或者鏈接地址
(圖片來自網(wǎng)絡(luò),出處不明,百度來的?)
整個(gè)步驟大致是這個(gè)樣子的:
用戶小明在你的網(wǎng)站A上面登錄了,A返回了一個(gè)session ID(使用cookie存儲(chǔ))
小明的瀏覽器保持著在A網(wǎng)站的登錄狀態(tài),事實(shí)上幾乎所有的網(wǎng)站都是這樣做的,一般至少是用戶關(guān)閉瀏覽器之前用戶的會(huì)話是不會(huì)結(jié)束的
攻擊者小強(qiáng)給小明發(fā)送了一個(gè)鏈接地址,小明打開了這個(gè)地址,查看了網(wǎng)頁的內(nèi)容
小明在打開這個(gè)地址的時(shí)候,這個(gè)頁面已經(jīng)自動(dòng)的對(duì)網(wǎng)站A發(fā)送了一個(gè)請(qǐng)求,這時(shí)候因?yàn)锳網(wǎng)站沒有退出,因此只要請(qǐng)求的地址是A的就會(huì)攜帶A的cookie信息,也就是使用A與小明之間的會(huì)話
這時(shí)候A網(wǎng)站肯定是不知道這個(gè)請(qǐng)求其實(shí)是小強(qiáng)偽造的網(wǎng)頁上發(fā)送的,而是誤以為小明就是要這樣操作,這樣小強(qiáng)就可以隨意的更改小明在A上的信息,以小明的身份在A網(wǎng)站上進(jìn)行操作
利用方式利用CSRF攻擊,主要包含兩種方式,一種是基于GET請(qǐng)求方式的利用,另一種是基于POST請(qǐng)求方式的利用。
GET請(qǐng)求利用使用GET請(qǐng)求方式的利用是最簡單的一種利用方式,其隱患的來源主要是由于在開發(fā)系統(tǒng)的時(shí)候沒有按照HTTP動(dòng)詞的正確使用方式來使用造成的。對(duì)于GET請(qǐng)求來說,它所發(fā)起的請(qǐng)求應(yīng)該是只讀的,不允許對(duì)網(wǎng)站的任何內(nèi)容進(jìn)行修改。
但是事實(shí)上并不是如此,很多網(wǎng)站在開發(fā)的時(shí)候,研發(fā)人員錯(cuò)誤的認(rèn)為GET/POST的使用區(qū)別僅僅是在于發(fā)送請(qǐng)求的數(shù)據(jù)是在Body中還是在請(qǐng)求地址中,以及請(qǐng)求內(nèi)容的大小不同。對(duì)于一些危險(xiǎn)的操作比如刪除文章,用戶授權(quán)等允許使用GET方式發(fā)送請(qǐng)求,在請(qǐng)求參數(shù)中加上文章或者用戶的ID,這樣就造成了只要請(qǐng)求地址被調(diào)用,數(shù)據(jù)就會(huì)產(chǎn)生修改。
現(xiàn)在假設(shè)攻擊者(用戶ID=121)想將自己的身份添加為網(wǎng)站的管理員,他在網(wǎng)站A上面發(fā)了一個(gè)帖子,里面包含一張圖片,其地址為http://a.com/user/grant_super_user/121
設(shè)想管理員看到這個(gè)帖子的時(shí)候,這個(gè)圖片肯定會(huì)自動(dòng)加載顯示的。于是在管理員不知情的情況下,一個(gè)賦予用戶管理員權(quán)限的操作已經(jīng)悄悄的以他的身份執(zhí)行了。這時(shí)候攻擊者121就獲取到了網(wǎng)站的管理員權(quán)限。
POST請(qǐng)求利用相對(duì)于GET方式的利用,POST方式的利用更加復(fù)雜一些,難度也大了一些。攻擊者需要偽造一個(gè)能夠自動(dòng)提交的表單來發(fā)送POST請(qǐng)求。
只要想辦法實(shí)現(xiàn)用戶訪問的時(shí)候自動(dòng)提交表單就可以了。
如何防范 防范原理防范CSRF攻擊,其實(shí)本質(zhì)就是要求網(wǎng)站能夠識(shí)別出哪些請(qǐng)求是非正常用戶主動(dòng)發(fā)起的。這就要求我們在請(qǐng)求中嵌入一些額外的授權(quán)數(shù)據(jù),讓網(wǎng)站服務(wù)器能夠區(qū)分出這些未授權(quán)的請(qǐng)求,比如說在請(qǐng)求參數(shù)中添加一個(gè)字段,這個(gè)字段的值從登錄用戶的Cookie或者頁面中獲取的(這個(gè)字段的值必須對(duì)每個(gè)用戶來說是隨機(jī)的,不能有規(guī)律可循)。攻擊者偽造請(qǐng)求的時(shí)候是無法獲取頁面中與登錄用戶有關(guān)的一個(gè)隨機(jī)值或者用戶當(dāng)前cookie中的內(nèi)容的,因此就可以避免這種攻擊。
防范技術(shù) Synchronizer token pattern令牌同步模式(Synchronizer token pattern,簡稱STP)是在用戶請(qǐng)求的頁面中的所有表單中嵌入一個(gè)token,在服務(wù)端驗(yàn)證這個(gè)token的技術(shù)。token可以是任意的內(nèi)容,但是一定要保證無法被攻擊者猜測到或者查詢到。攻擊者在請(qǐng)求中無法使用正確的token,因此可以判斷出未授權(quán)的請(qǐng)求。
Cookie-to-Header Token對(duì)于使用Js作為主要交互技術(shù)的網(wǎng)站,將CSRF的token寫入到cookie中
Set-Cookie: CSRF-token=i8XNjC4b8KVok4uw5RftR38Wgp2BFwql; expires=Thu, 23-Jul-2015 10:25:33 GMT; Max-Age=31449600; Path=/
然后使用javascript讀取token的值,在發(fā)送http請(qǐng)求的時(shí)候?qū)⑵渥鳛檎?qǐng)求的header
X-CSRF-Token: i8XNjC4b8KVok4uw5RftR38Wgp2BFwql
最后服務(wù)器驗(yàn)證請(qǐng)求頭中的token是否合法。
驗(yàn)證碼使用驗(yàn)證碼可以杜絕CSRF攻擊,但是這種方式要求每個(gè)請(qǐng)求都輸入一個(gè)驗(yàn)證碼,顯然沒有哪個(gè)網(wǎng)站愿意使用這種粗暴的方式,用戶體驗(yàn)太差,用戶會(huì)瘋掉的。
簡單實(shí)現(xiàn)STP首先在index.php中,創(chuàng)建一個(gè)表單,在表單中,我們將session中存儲(chǔ)的token放入到隱藏域,這樣,表單提交的時(shí)候token會(huì)隨表單一起提交
在服務(wù)端校驗(yàn)請(qǐng)求參數(shù)的buy.php中,對(duì)表單提交過來的token與session中存儲(chǔ)的token進(jìn)行比對(duì),如果一致說明token是有效的
對(duì)于攻擊者來說,在偽造請(qǐng)求的時(shí)候是無法獲取到用戶頁面中的這個(gè)token值的,因此就可以識(shí)別出其創(chuàng)建的偽造請(qǐng)求。
解析Laravel框架中的VerifyCSRFToken中間件在Laravel框架中,使用了VerifyCSRFToken這個(gè)中間件來防范CSRF攻擊。
在頁面的表單中使用{{ CSRF_field() }}來生成token,該函數(shù)會(huì)在表單中添加一個(gè)名為_token的隱藏域,該隱藏域的值為Laravel生成的token,Laravel使用隨機(jī)生成的40個(gè)字符作為防范CSRF攻擊的token。
$this->put("_token", Str::random(40));如果請(qǐng)求是ajax異步請(qǐng)求,可以在meta標(biāo)簽中添加token
使用jquery作為前端的框架時(shí)候,可以通過以下配置將該值添加到所有的異步請(qǐng)求頭中
$.ajaxSetup({ headers: { "X-CSRF-TOKEN": $("meta[name="CSRF-token"]").attr("content") } });在啟用session的時(shí)候,Laravel會(huì)生成一個(gè)名為_token的值存儲(chǔ)到session中。而使用前面兩種方式在頁面中加入的token就是使用的這一個(gè)值。在用戶請(qǐng)求到來時(shí),VerifyCSRFToken中間件會(huì)對(duì)符合條件的請(qǐng)求進(jìn)行CSRF檢查
if ( $this->isReading($request) || $this->runningUnitTests() || $this->shouldPassThrough($request) || $this->tokensMatch($request) ) { return $this->addCookieToResponse($request, $next($request)); } throw new TokenMismatchException;在if語句中有四個(gè)條件,只要任何一個(gè)條件結(jié)果為true則任何該請(qǐng)求是合法的,否則就會(huì)拋出TokenMismatchException異常,告訴用戶請(qǐng)求不合法,存在CSRF攻擊。
第一個(gè)條件$this->isReading($request)用來檢查請(qǐng)求是否會(huì)對(duì)數(shù)據(jù)產(chǎn)生修改
protected function isReading($request) { return in_array($request->method(), ["HEAD", "GET", "OPTIONS"]); }這里判斷了請(qǐng)求方式,如果是HEAD,GET,OPTIONS這三種請(qǐng)求方式則直接放行。你可能會(huì)感到疑惑,為什么GET請(qǐng)求也要放行呢?這是因?yàn)長aravel認(rèn)為這三個(gè)請(qǐng)求都是請(qǐng)求查詢數(shù)據(jù)的,如果一個(gè)請(qǐng)求是使用GET方式,那無論請(qǐng)求多少次,無論請(qǐng)求參數(shù)如何,都不應(yīng)該最數(shù)據(jù)做任何修改。
第二個(gè)條件顧名思義是對(duì)單元測試進(jìn)行放行,第三個(gè)是為開發(fā)者提供了一個(gè)可以對(duì)某些請(qǐng)求添加例外的功能,最后一個(gè)$this->tokensMatch($request)則是真正起作用的一個(gè),它是Laravel防范CSRF攻擊的關(guān)鍵
$sessionToken = $request->session()->token(); $token = $request->input("_token") ?: $request->header("X-CSRF-TOKEN"); if (! $token && $header = $request->header("X-XSRF-TOKEN")) { $token = $this->encrypter->decrypt($header); } if (! is_string($sessionToken) || ! is_string($token)) { return false; } return hash_equals($sessionToken, $token);Laravel會(huì)從請(qǐng)求中讀取_token參數(shù)的的值,這個(gè)值就是在前面表單中添加的CSRF_field()函數(shù)生成的。如果請(qǐng)求是異步的,那么會(huì)讀取X-CSRF-TOKEN請(qǐng)求頭,從請(qǐng)求頭中讀取token的值。
最后使用hash_equals函數(shù)驗(yàn)證請(qǐng)求參數(shù)中提供的token值和session中存儲(chǔ)的token值是否一致,如果一致則說明請(qǐng)求是合法的。
你可能注意到,這個(gè)檢查過程中也會(huì)讀取一個(gè)名為X-XSRF-TOKEN的請(qǐng)求頭,這個(gè)值是為了提供對(duì)一些javascript框架的支持(比如Angular),它們會(huì)自動(dòng)的對(duì)異步請(qǐng)求中添加該請(qǐng)求頭,而該值是從Cookie中的XSRF-TOKEN中讀取的,因此在每個(gè)請(qǐng)求結(jié)束的時(shí)候,Laravel會(huì)發(fā)送給客戶端一個(gè)名為XSRF-TOKEN的Cookie值
$response->headers->setCookie( new Cookie( "XSRF-TOKEN", $request->session()->token(), time() + 60 * $config["lifetime"], $config["path"], $config["domain"], $config["secure"], false ) );寫在最后本文只是對(duì)CSRF做了一個(gè)簡單的介紹,主要是側(cè)重于CSRF是什么以及如何應(yīng)對(duì)CSRF攻擊。有一個(gè)事實(shí)是我們無法回避的:沒有絕對(duì)安全的系統(tǒng),你有一千種防御對(duì)策,攻擊者就有一千零一種攻擊方式,但不管如何,我們都要盡最大的努力去將攻擊者攔截在門外。如果希望深入了解如何發(fā)起一個(gè)CSRF攻擊,可以參考一下這篇文章 從零開始學(xué)CSRF。
作為一名web方向的研發(fā)人員,無論你是從事業(yè)務(wù)邏輯開發(fā)還是做單純的技術(shù)研究,了解一些安全方面的知識(shí)都是很有必要的,多關(guān)注一些安全方向的動(dòng)態(tài),了解常見的攻擊方式以及應(yīng)對(duì)策略,必將在你成長為一名大牛的路上為你“推波助瀾”。
本文將會(huì)持續(xù)修正和更新,最新內(nèi)容請(qǐng)參考我的 GITHUB 上的 程序猿成長計(jì)劃 項(xiàng)目,歡迎 Star,更多精彩內(nèi)容請(qǐng) follow me。
參考wikipedia: Cross-site request forgery
Cross-Site Request Forgeries
淺談CSRF攻擊方式
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/22442.html
摘要:,中文為跨站請(qǐng)求偽造是一種利用網(wǎng)站可信用戶的權(quán)限去執(zhí)行未授權(quán)的命令的一種惡意攻擊。防范技術(shù)令牌同步模式,簡稱是在用戶請(qǐng)求的頁面中的所有表單中嵌入一個(gè),在服務(wù)端驗(yàn)證這個(gè)的技術(shù)。 showImg(https://segmentfault.com/img/remote/1460000008505619); CSRF(Cross-site request forgery,中文為跨站請(qǐng)求偽造)是...
摘要:總結(jié)總的來說,前端最重要的就是一個(gè)這個(gè)代表用戶身份的憑證,保護(hù)好這個(gè)憑證,同時(shí)利用同源策略以及自己加密來識(shí)別用戶,最后以最惡意的眼光對(duì)待用戶的輸入,不要相信用戶的輸入。 前端安全一直是一個(gè)蠻嚴(yán)苛的問題,特別如果設(shè)計(jì)到money更是如此。了解前端安全,在平時(shí)的coding中主動(dòng)考慮,防范于未然,是一個(gè)有追求的程序猿應(yīng)該做的。 未登錄 我們從弱弱的基本開始,第一步當(dāng)然是登錄鑒權(quán)了,如果一個(gè)...
閱讀 2065·2021-10-11 10:59
閱讀 924·2021-09-23 11:21
閱讀 3541·2021-09-06 15:02
閱讀 1610·2021-08-19 10:25
閱讀 3364·2021-07-30 11:59
閱讀 2362·2019-08-30 11:27
閱讀 2574·2019-08-30 11:20
閱讀 2964·2019-08-29 13:15