主頁(yè) > 知識(shí)庫(kù) > 詳解WEB攻擊之CSRF攻擊與防護(hù)

詳解WEB攻擊之CSRF攻擊與防護(hù)

熱門(mén)標(biāo)簽:智能手機(jī) 服務(wù)器配置 鐵路電話系統(tǒng) 銀行業(yè)務(wù) 網(wǎng)站文章發(fā)布 呼叫中心市場(chǎng)需求 檢查注冊(cè)表項(xiàng) 美圖手機(jī)

CSRF 背景與介紹

CSRF定義: 跨站請(qǐng)求偽造(英語(yǔ):Cross-site request forgery),也被稱(chēng)為 one-click attack 或者 session riding,通常縮寫(xiě)為 CSRF 或者 XSRF, 是一種挾制用戶在當(dāng)前已登錄的Web應(yīng)用程序上執(zhí)行非本意的操作的攻擊方法。

簡(jiǎn)單地說(shuō),是攻擊者通過(guò)一些技術(shù)手段欺騙用戶的瀏覽器去訪問(wèn)一個(gè)自己曾經(jīng)認(rèn)證過(guò)的網(wǎng)站并執(zhí)行一些操作(如發(fā)郵件,發(fā)消息,甚至財(cái)產(chǎn)操作如轉(zhuǎn)賬和購(gòu)買(mǎi)商品)。由于瀏覽器曾經(jīng)認(rèn)證過(guò),所以被訪問(wèn)的網(wǎng)站會(huì)認(rèn)為是真正的用戶操作而去執(zhí)行。這利用了web中用戶身份驗(yàn)證的一個(gè)漏洞:簡(jiǎn)單的身份驗(yàn)證只能保證請(qǐng)求發(fā)自某個(gè)用戶的瀏覽器,卻不能保證請(qǐng)求本身是用戶自愿發(fā)出的。

CSRF地位:是一種網(wǎng)絡(luò)攻擊方式,是互聯(lián)網(wǎng)重大安全隱患之一,NYTimes.com(紐約時(shí)報(bào))、Metafilter,YouTube、Gmail和百度HI都受到過(guò)此類(lèi)攻擊。

對(duì)比XSS:跟跨網(wǎng)站腳本(XSS)相比,XSS 利用的是用戶對(duì)指定網(wǎng)站的信任,CSRF 利用的是網(wǎng)站對(duì)用戶網(wǎng)頁(yè)瀏覽器的信任。

CSRF 攻擊實(shí)例

daguanren(大官人)在銀行有一筆存款,輸入用戶名密碼登錄銀行網(wǎng)銀后發(fā)送請(qǐng)求進(jìn)行個(gè)人名下賬戶轉(zhuǎn)賬 :

http://www.bank.example/withdraw?account=daguanren1amount=999for=daguanren2

將daguanren1中的999塊轉(zhuǎn)到了daguanren2賬號(hào)中。通常用戶登錄后,系統(tǒng)會(huì)保存用戶登錄的session值(可能是用戶手機(jī)號(hào)、賬號(hào)等)。但如果這時(shí)daguanren不小心新開(kāi)一個(gè)tab頁(yè)面進(jìn)入了一個(gè)黑客jinlian(金蓮)的網(wǎng)站,而金蓮網(wǎng)站的頁(yè)面中嵌有如下html標(biāo)簽:

!DOCTYPE html>
html>
  !--其他頁(yè)面元素-->

  img src=http://www.bank.example/withdraw?account=daguanren1amount=888for=jinlian width='0' height='0'>

  !--其他頁(yè)面元素-->
/html>

這個(gè)請(qǐng)求就會(huì)附帶上daguanren的session值,成功將大官人的888元轉(zhuǎn)至jinlian的賬戶上。但如果daguanren之前沒(méi)有登錄網(wǎng)銀,而是直接打開(kāi)jinlian的網(wǎng)站,則由于沒(méi)有session值,不會(huì)被攻擊。以上示例雖然是get請(qǐng)求,post請(qǐng)求提交的表單同樣會(huì)被攻擊。

iframe style="display:none" name="csrf-frame">/iframe>
form method='POST' action='http://www.bank.example/withdraw' target="csrf-frame" id="csrf-form">
 input type='hidden' name='account' value='daguanren1'>
 input type='hidden' name='amount' value='888'>
 input type='hidden' name='for' value='jinlian'>
 input type='submit' value='submit'>
/form>
script>document.getElementById("csrf-form").submit()/script>

 

所以要被CSRF攻擊,必須同時(shí)滿足兩個(gè)條件:
1.登錄受信任網(wǎng)站A,并在本地生成Cookie。
2.在不登出A的情況下,訪問(wèn)危險(xiǎn)網(wǎng)站B。

CSRF 攻擊的對(duì)象

在討論如何抵御 CSRF 之前,先要明確 CSRF 攻擊的對(duì)象,也就是要保護(hù)的對(duì)象。從以上的例子可知,CSRF 攻擊是黑客借助受害者的 cookie(session) 騙取服務(wù)器的信任,但是黑客并不能拿到 cookie,也看不到 cookie 的內(nèi)容。另外,對(duì)于服務(wù)器返回的結(jié)果,由于瀏覽器同源策略的限制,黑客也無(wú)法進(jìn)行解析。因此,黑客無(wú)法從返回的結(jié)果中得到任何東西,他所能做的就是給服務(wù)器發(fā)送請(qǐng)求,以執(zhí)行請(qǐng)求中所描述的命令,在服務(wù)器端直接改變數(shù)據(jù)的值,而非竊取服務(wù)器中的數(shù)據(jù)。所以,我們要保護(hù)的對(duì)象是那些可以直接產(chǎn)生數(shù)據(jù)改變的服務(wù),而對(duì)于讀取數(shù)據(jù)的服務(wù),則不需要進(jìn)行 CSRF 的保護(hù)。比如銀行系統(tǒng)中轉(zhuǎn)賬的請(qǐng)求會(huì)直接改變賬戶的金額,會(huì)遭到 CSRF 攻擊,需要保護(hù)。而查詢余額是對(duì)金額的讀取操作,不會(huì)改變數(shù)據(jù),CSRF 攻擊無(wú)法解析服務(wù)器返回的結(jié)果,無(wú)需保護(hù)。

故:增刪改需要防范CSRF攻擊,而讀無(wú)需防范。

當(dāng)前防御 CSRF 的幾種策略

在業(yè)界目前防御 CSRF 攻擊主要有四種策略:
- 驗(yàn)證 HTTP Referer 字段;
- 在請(qǐng)求地址中添加 token 并驗(yàn)證;
- 在 HTTP 頭中自定義屬性并驗(yàn)證;
- Chrome瀏覽器端啟用SameSite cookie

1、驗(yàn)證 HTTP Referer 字段

什么是HTTP Referer?下面GIF圖是由百度跳轉(zhuǎn)到QQ郵箱頁(yè)面的Referer查看示意:

 

可以看出Referer為

Referer:https://www.baidu.com/

根據(jù) HTTP 協(xié)議,在 HTTP 頭(request 的 header)中有一個(gè)字段叫 Referer,它記錄了該 HTTP 請(qǐng)求的來(lái)源地址。如果黑客要對(duì)銀行網(wǎng)站實(shí)施 CSRF 攻擊,當(dāng)用戶通過(guò)黑客的網(wǎng)站發(fā)送請(qǐng)求到銀行時(shí),該請(qǐng)求的 Referer 值是指向黑客的網(wǎng)站而不是用戶的網(wǎng)站。因此,要防御 CSRF 攻擊,銀行網(wǎng)站只需要對(duì)于每一個(gè)轉(zhuǎn)賬請(qǐng)求驗(yàn)證其 Referer 值,如果是以 www.bank.example開(kāi)頭的域名,則說(shuō)明該請(qǐng)求是來(lái)自銀行網(wǎng)站自己的請(qǐng)求,是合法的。如果 Referer 是其他網(wǎng)站的話,則有可能是黑客的 CSRF 攻擊,拒絕該請(qǐng)求。

這種方法的顯而易見(jiàn)的好處就是簡(jiǎn)單易行,網(wǎng)站的普通開(kāi)發(fā)人員不需要操心 CSRF 的漏洞,只需要在最后給所有安全敏感的請(qǐng)求統(tǒng)一增加一個(gè)攔截器來(lái)檢查 Referer 的值就可以。特別是對(duì)于當(dāng)前現(xiàn)有的系統(tǒng),不需要改變當(dāng)前系統(tǒng)的任何已有代碼和邏輯。

然而,這種方法并非萬(wàn)無(wú)一失。Referer 的值是由瀏覽器提供的,雖然 HTTP 協(xié)議上有明確的要求,但是每個(gè)瀏覽器對(duì)于 Referer 的具體實(shí)現(xiàn)可能有差別,并不能保證瀏覽器自身沒(méi)有安全漏洞。使用驗(yàn)證 Referer 值的方法,就是把安全性都依賴于第三方(即瀏覽器)來(lái)保障,從理論上來(lái)講,這樣并不安全。事實(shí)上,對(duì)于某些瀏覽器,比如 IE6 或 FF2,目前已經(jīng)有一些方法可以篡改 Referer 值。如果 www.bank.example網(wǎng)站支持 IE6 瀏覽器,黑客完全可以把用戶瀏覽器的 Referer 值設(shè)為以 www.bank.example域名開(kāi)頭的地址,這樣就可以通過(guò)驗(yàn)證,從而進(jìn)行 CSRF 攻擊。

即便是使用最新的瀏覽器,黑客無(wú)法篡改 Referer 值,這種方法仍然有問(wèn)題。因?yàn)?Referer 值會(huì)記錄下用戶的訪問(wèn)來(lái)源,有些用戶認(rèn)為這樣會(huì)侵犯到他們自己的隱私權(quán),特別是有些組織擔(dān)心 Referer 值會(huì)把組織內(nèi)網(wǎng)中的某些信息泄露到外網(wǎng)中。因此,用戶自己可以設(shè)置瀏覽器使其在發(fā)送請(qǐng)求時(shí)不再提供 Referer。當(dāng)他們正常訪問(wèn)銀行網(wǎng)站時(shí),網(wǎng)站會(huì)因?yàn)檎?qǐng)求沒(méi)有 Referer 值而認(rèn)為是 CSRF 攻擊,拒絕合法用戶的訪問(wèn)。

另外,如果Referer的判斷邏輯寫(xiě)的不嚴(yán)密的話,也容易被攻破,例如

const referer = request.headers.referer;
if (referer.indexOf('www.bank.example') > -1) {
 // pass
}

如果黑客的網(wǎng)站是www.bank.example.hack.com,則referer檢查無(wú)效。

2、在請(qǐng)求地址中添加 token 并驗(yàn)證

CSRF 攻擊之所以能夠成功,是因?yàn)楹诳涂梢酝耆珎卧煊脩舻恼?qǐng)求,該請(qǐng)求中所有的用戶驗(yàn)證信息都是存在于 cookie 中,因此黑客可以在不知道這些驗(yàn)證信息的情況下直接利用用戶的 cookie 來(lái)通過(guò)安全驗(yàn)證。要抵御 CSRF,關(guān)鍵在于在請(qǐng)求中放入黑客所不能偽造的信息,并且該信息不存在于 cookie 之中。可以在 HTTP 請(qǐng)求中以參數(shù)的形式加入一個(gè)隨機(jī)產(chǎn)生的 token,并在服務(wù)器端建立一個(gè)攔截器來(lái)驗(yàn)證這個(gè) token,如果請(qǐng)求中沒(méi)有 token 或者 token 內(nèi)容不正確,則認(rèn)為可能是 CSRF 攻擊而拒絕該請(qǐng)求。

這種方法要比檢查 Referer 要安全一些,token 可以在用戶登陸后產(chǎn)生并放于 session 之中,然后在每次請(qǐng)求時(shí)把 token 從 session 中拿出,與請(qǐng)求中的 token 進(jìn)行比對(duì),但這種方法的難點(diǎn)在于如何把 token 以參數(shù)的形式加入請(qǐng)求。對(duì)于 GET 請(qǐng)求,token 將附在請(qǐng)求地址之后,這樣 URL 就變成

http://url?csrftoken=tokenvalue

而對(duì)于 POST 請(qǐng)求來(lái)說(shuō),要在 form 的最后加上

 input type="hidden" name="csrftoken" value="tokenvalue"/>

該方法有一個(gè)缺點(diǎn)是難以保證 token 本身的安全。特別是在一些論壇之類(lèi)支持用戶自己發(fā)表內(nèi)容的網(wǎng)站,黑客可以在上面發(fā)布自己個(gè)人網(wǎng)站的地址。由于系統(tǒng)也會(huì)在這個(gè)地址后面加上 token,黑客可以在自己的網(wǎng)站上得到這個(gè) token,并馬上就可以發(fā)動(dòng) CSRF 攻擊。為了避免這一點(diǎn),系統(tǒng)可以在添加 token 的時(shí)候增加一個(gè)判斷,如果這個(gè)鏈接是鏈到自己本站的,就在后面添加 token,如果是通向外網(wǎng)則不加。不過(guò),即使這個(gè) csrftoken 不以參數(shù)的形式附加在請(qǐng)求之中,黑客的網(wǎng)站也同樣可以通過(guò) Referer 來(lái)得到這個(gè) token 值以發(fā)動(dòng) CSRF 攻擊。這也是一些用戶喜歡手動(dòng)關(guān)閉瀏覽器 Referer 功能的原因。

3、在 HTTP 頭中自定義屬性并驗(yàn)證

這種方法也是使用 token 并進(jìn)行驗(yàn)證,和上一種方法不同的是,這里并不是把 token 以參數(shù)的形式置于 HTTP 請(qǐng)求之中,而是把它放到 HTTP 頭中自定義的屬性里。通過(guò) XMLHttpRequest 這個(gè)類(lèi),可以一次性給所有該類(lèi)請(qǐng)求加上 csrftoken 這個(gè) HTTP 頭屬性,并把 token 值放入其中。這樣解決了上種方法在請(qǐng)求中加入 token 的不便,同時(shí),通過(guò) XMLHttpRequest 請(qǐng)求的地址不會(huì)被記錄到瀏覽器的地址欄,也不用擔(dān)心 token 會(huì)透過(guò) Referer 泄露到其他網(wǎng)站中去。

然而這種方法的局限性非常大。XMLHttpRequest 請(qǐng)求通常用于 Ajax 方法中對(duì)于頁(yè)面局部的異步刷新,并非所有的請(qǐng)求都適合用這個(gè)類(lèi)來(lái)發(fā)起,而且通過(guò)該類(lèi)請(qǐng)求得到的頁(yè)面不能被瀏覽器所記錄下,從而進(jìn)行前進(jìn),后退,刷新,收藏等操作,給用戶帶來(lái)不便。另外,對(duì)于沒(méi)有進(jìn)行 CSRF 防護(hù)的遺留系統(tǒng)來(lái)說(shuō),要采用這種方法來(lái)進(jìn)行防護(hù),要把所有請(qǐng)求都改為 XMLHttpRequest 請(qǐng)求,這樣幾乎是要重寫(xiě)整個(gè)網(wǎng)站,這代價(jià)無(wú)疑是不能接受的。

4、Chrome瀏覽器端啟用SameSite cookie

下面介紹如何啟用SameSite cookie的設(shè)置,很簡(jiǎn)單。

原本的 Cookie 的 header 設(shè)置是長(zhǎng)這樣:

Set-Cookie: session_id=esadfas325

需要在尾部增加 SameSite 就好:

Set-Cookie: session_id=esdfas32e5; SameSite

SameSite 有兩種模式,Lax跟Strict模式,默認(rèn)啟用Strict模式,可以自己指定模式:

Set-Cookie: session_id=esdfas32e5; SameSite=StrictSet-Cookie: foo=bar; SameSite=Lax

Strict模式規(guī)定 cookie 只允許相同的site使用,不應(yīng)該在任何的 cross site request 被加上去。即a標(biāo)簽、form表單和XMLHttpRequest提交的內(nèi)容,只要是提交到不同的site去,就不會(huì)帶上cookie。

但也存在不便,例如朋友發(fā)送過(guò)來(lái)我已經(jīng)登陸過(guò)的一個(gè)頁(yè)面鏈接,我點(diǎn)開(kāi)后,該頁(yè)面仍然需要重新登錄。

有兩種處理辦法,第一種是與Amazon一樣,準(zhǔn)備兩組不同的cookie,第一組用于維持登錄狀態(tài)不設(shè)定SameSite,第二組針對(duì)的是一些敏感操作會(huì)用到(例如購(gòu)買(mǎi)、支付、設(shè)定賬戶等)嚴(yán)格設(shè)定SameSite。

基于這個(gè)思路,就產(chǎn)生了 SameSite 的另一一種模式:Lax模式。

Lax 模式打開(kāi)了一些限制,例如

a>
link rel="prerender">
form method="GET">

這些都會(huì)帶上cookie。但是 POST 方法 的 form,或是只要是 POST, PUT, DELETE 這些方法,就不會(huì)帶cookie。
但一定注意將重要的請(qǐng)求方式改成POST,否則GET仍然會(huì)被攻擊。
PS:該方式目前僅Chrome支持。

后記

方式1通過(guò)驗(yàn)證HTTP Referer頭信息來(lái)防止跨站請(qǐng)求偽造csrf,在java中可以通過(guò)filter來(lái)實(shí)現(xiàn)。方式2和方式3都是通過(guò)在請(qǐng)求中添加token來(lái)進(jìn)行安全校驗(yàn)的,spring security 提供的csrf防護(hù)就是采用這樣的方式,而且從spring security 4.0開(kāi)始csrf防護(hù)是默認(rèn)開(kāi)啟的。對(duì)于一個(gè)新項(xiàng)目,可以幾種方式都用上,這樣更加安全。如果是一個(gè)已經(jīng)完備的web程序,還是使用方式1修改起來(lái)方便,不然每個(gè)請(qǐng)求都加上csrfToken改動(dòng)很大。關(guān)于spring security csrf可參考我的博文:https://www.jb51.net/article/157547.htm

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家

您可能感興趣的文章:
  • 淺談PHP安全防護(hù)之Web攻擊
  • 詳解常見(jiàn)web攻擊手段

標(biāo)簽:新疆 滄州 紅河 樂(lè)山 河南 沈陽(yáng) 長(zhǎng)治 上海

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《詳解WEB攻擊之CSRF攻擊與防護(hù)》,本文關(guān)鍵詞  ;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 收縮
    • 微信客服
    • 微信二維碼
    • 電話咨詢

    • 400-1100-266