CSRF 攻擊(轉(zhuǎn))

CSRF 背景與介紹
本文轉(zhuǎn)自IBM

CSRF(Cross Site Request Forgery, 跨站域請(qǐng)求偽造)是一種網(wǎng)絡(luò)的攻擊方式伶跷,它在 2007 年曾被列為互聯(lián)網(wǎng) 20 大安全隱患之一旋奢。其他安全隱患摔寨,比如 SQL 腳本注入,跨站域腳本攻擊等在近年來(lái)已經(jīng)逐漸為眾人熟知航厚,很多網(wǎng)站也都針對(duì)他們進(jìn)行了防御。然而,對(duì)于大多數(shù)人來(lái)說(shuō)椎侠,CSRF 卻依然是一個(gè)陌生的概念。即便是大名鼎鼎的 Gmail, 在 2007 年底也存在著 CSRF 漏洞措拇,從而被黑客攻擊而使 Gmail 的用戶造成巨大的損失我纪。

CSRF 攻擊實(shí)例
CSRF 攻擊可以在受害者毫不知情的情況下以受害者名義偽造請(qǐng)求發(fā)送給受攻擊站點(diǎn),從而在并未授權(quán)的情況下執(zhí)行在權(quán)限保護(hù)之下的操作丐吓。比如說(shuō)浅悉,受害者 Bob 在銀行有一筆存款,通過(guò)對(duì)銀行的網(wǎng)站發(fā)送請(qǐng)求 http://bank.example/withdraw?account=bob&amount=1000000&for=bob2 可以使 Bob 把 1000000 的存款轉(zhuǎn)到 bob2 的賬號(hào)下券犁。通常情況下术健,該請(qǐng)求發(fā)送到網(wǎng)站后,服務(wù)器會(huì)先驗(yàn)證該請(qǐng)求是否來(lái)自一個(gè)合法的 session粘衬,并且該 session 的用戶 Bob 已經(jīng)成功登陸荞估。黑客 Mallory 自己在該銀行也有賬戶比被,他知道上文中的 URL 可以把錢(qián)進(jìn)行轉(zhuǎn)帳操作。Mallory 可以自己發(fā)送一個(gè)請(qǐng)求給銀行:http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory泼舱。但是這個(gè)請(qǐng)求來(lái)自 Mallory 而非 Bob等缀,他不能通過(guò)安全認(rèn)證,因此該請(qǐng)求不會(huì)起作用娇昙。這時(shí)尺迂,Mallory 想到使用 CSRF 的攻擊方式,他先自己做一個(gè)網(wǎng)站冒掌,在網(wǎng)站中放入如下代碼: src=”http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory ”噪裕,并且通過(guò)廣告等誘使 Bob 來(lái)訪問(wèn)他的網(wǎng)站。當(dāng) Bob 訪問(wèn)該網(wǎng)站時(shí)股毫,上述 url 就會(huì)從 Bob 的瀏覽器發(fā)向銀行膳音,而這個(gè)請(qǐng)求會(huì)附帶 Bob 瀏覽器中的 cookie 一起發(fā)向銀行服務(wù)器。大多數(shù)情況下铃诬,該請(qǐng)求會(huì)失敗祭陷,因?yàn)樗?Bob 的認(rèn)證信息。但是趣席,如果 Bob 當(dāng)時(shí)恰巧剛訪問(wèn)他的銀行后不久兵志,他的瀏覽器與銀行網(wǎng)站之間的 session 尚未過(guò)期,瀏覽器的 cookie 之中含有 Bob 的認(rèn)證信息宣肚。這時(shí)想罕,悲劇發(fā)生了,這個(gè) url 請(qǐng)求就會(huì)得到響應(yīng)霉涨,錢(qián)將從 Bob 的賬號(hào)轉(zhuǎn)移到 Mallory 的賬號(hào)按价,而 Bob 當(dāng)時(shí)毫不知情。等以后 Bob 發(fā)現(xiàn)賬戶錢(qián)少了笙瑟,即使他去銀行查詢?nèi)罩韭ジ洌仓荒馨l(fā)現(xiàn)確實(shí)有一個(gè)來(lái)自于他本人的合法請(qǐng)求轉(zhuǎn)移了資金,沒(méi)有任何被攻擊的痕跡逮走。而 Mallory 則可以拿到錢(qián)后逍遙法外鸠蚪。

CSRF 攻擊的對(duì)象
在討論如何抵御 CSRF 之前,先要明確 CSRF 攻擊的對(duì)象师溅,也就是要保護(hù)的對(duì)象茅信。從以上的例子可知,CSRF 攻擊是黑客借助受害者的 cookie 騙取服務(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ù)蛀蜜。

當(dāng)前防御 CSRF 的幾種策略
在業(yè)界目前防御 CSRF 攻擊主要有三種策略:驗(yàn)證 HTTP Referer 字段;在請(qǐng)求地址中添加 token 并驗(yàn)證增蹭;在 HTTP 頭中自定義屬性并驗(yàn)證。下面就分別對(duì)這三種策略進(jìn)行詳細(xì)介紹磅摹。

驗(yàn)證 HTTP Referer 字段
根據(jù) HTTP 協(xié)議滋迈,在 HTTP 頭中有一個(gè)字段叫 Referer,它記錄了該 HTTP 請(qǐng)求的來(lái)源地址户誓。在通常情況下饼灿,訪問(wèn)一個(gè)安全受限頁(yè)面的請(qǐng)求來(lái)自于同一個(gè)網(wǎng)站,比如需要訪問(wèn) http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory帝美,用戶必須先登陸 bank.example碍彭,然后通過(guò)點(diǎn)擊頁(yè)面上的按鈕來(lái)觸發(fā)轉(zhuǎn)賬事件。這時(shí)悼潭,該轉(zhuǎn)帳請(qǐng)求的 Referer 值就會(huì)是轉(zhuǎn)賬按鈕所在的頁(yè)面的 URL庇忌,通常是以 bank.example 域名開(kāi)頭的地址。而如果黑客要對(duì)銀行網(wǎng)站實(shí)施 CSRF 攻擊舰褪,他只能在他自己的網(wǎng)站構(gòu)造請(qǐng)求皆疹,當(dāng)用戶通過(guò)黑客的網(wǎng)站發(fā)送請(qǐng)求到銀行時(shí),該請(qǐng)求的 Referer 是指向黑客自己的網(wǎng)站占拍。因此略就,要防御 CSRF 攻擊捎迫,銀行網(wǎng)站只需要對(duì)于每一個(gè)轉(zhuǎn)賬請(qǐng)求驗(yàn)證其 Referer 值,如果是以 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)的任何已有代碼和邏輯倔幼,沒(méi)有風(fēng)險(xiǎn),非常便捷爽待。

然而损同,這種方法并非萬(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 值。如果 bank.example 網(wǎng)站支持 IE6 瀏覽器荠诬,黑客完全可以把用戶瀏覽器的 Referer 值設(shè)為以 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)我注。

在請(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”/>,這樣就把 token 以參數(shù)的形式加入請(qǐng)求了帮寻。但是,在一個(gè)網(wǎng)站中赠摇,可以接受請(qǐng)求的地方非常多固逗,要對(duì)于每一個(gè)請(qǐng)求都加上 token 是很麻煩的,并且很容易漏掉藕帜,通常使用的方法就是在每次頁(yè)面加載時(shí)烫罩,使用 javascript 遍歷整個(gè) dom 樹(shù),對(duì)于 dom 中所有的 a 和 form 標(biāo)簽后加入 token洽故。這樣可以解決大部分的請(qǐng)求贝攒,但是對(duì)于在頁(yè)面加載之后動(dòng)態(tài)生成的 html 代碼,這種方法就沒(méi)有作用时甚,還需要程序員在編碼時(shí)手動(dòng)添加 token隘弊。

該方法還有一個(gè)缺點(diǎn)是難以保證 token 本身的安全哈踱。特別是在一些論壇之類支持用戶自己發(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 功能的原因奋早。

在 HTTP 頭中自定義屬性并驗(yàn)證
這種方法也是使用 token 并進(jìn)行驗(yàn)證盛霎,和上一種方法不同的是,這里并不是把 token 以參數(shù)的形式置于 HTTP 請(qǐng)求之中耽装,而是把它放到 HTTP 頭中自定義的屬性里愤炸。通過(guò) XMLHttpRequest 這個(gè)類,可以一次性給所有該類請(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)發(fā)起,而且通過(guò)該類請(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ú)疑是不能接受的箱季。

總結(jié)與展望
可見(jiàn),CSRF 是一種危害非常大的攻擊领虹,又很難以防范规哪。目前幾種防御策略雖然可以很大程度上抵御 CSRF 的攻擊,但并沒(méi)有一種完美的解決方案塌衰。一些新的方案正在研究之中诉稍,比如對(duì)于每次請(qǐng)求都使用不同的動(dòng)態(tài)口令,把 Referer 和 token 方案結(jié)合起來(lái)最疆,甚至嘗試修改 HTTP 規(guī)范杯巨,但是這些新的方案尚不成熟,要正式投入使用并被業(yè)界廣為接受還需時(shí)日努酸。在這之前服爷,我們只有充分重視 CSRF,根據(jù)系統(tǒng)的實(shí)際情況選擇最合適的策略获诈,這樣才能把 CSRF 的危害降到最低仍源。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市舔涎,隨后出現(xiàn)的幾起案子笼踩,更是在濱河造成了極大的恐慌,老刑警劉巖亡嫌,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嚎于,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡挟冠,警方通過(guò)查閱死者的電腦和手機(jī)于购,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)知染,“玉大人肋僧,你說(shuō)我怎么就攤上這事】氐” “怎么了色瘩?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)逸寓。 經(jīng)常有香客問(wèn)我,道長(zhǎng)覆山,這世上最難降的妖魔是什么竹伸? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上勋篓,老公的妹妹穿的比我還像新娘吧享。我一直安慰自己,他們只是感情好譬嚣,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布钢颂。 她就那樣靜靜地躺著,像睡著了一般拜银。 火紅的嫁衣襯著肌膚如雪殊鞭。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,462評(píng)論 1 302
  • 那天尼桶,我揣著相機(jī)與錄音操灿,去河邊找鬼。 笑死泵督,一個(gè)胖子當(dāng)著我的面吹牛趾盐,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播小腊,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼救鲤,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了秩冈?” 一聲冷哼從身側(cè)響起本缠,我...
    開(kāi)封第一講書(shū)人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎漩仙,沒(méi)想到半個(gè)月后搓茬,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡队他,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年卷仑,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片麸折。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡锡凝,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出垢啼,到底是詐尸還是另有隱情窜锯,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布芭析,位于F島的核電站锚扎,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏馁启。R本人自食惡果不足惜驾孔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一芍秆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧翠勉,春花似錦妖啥、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至朽们,卻和暖如春怀读,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背华坦。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工愿吹, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人惜姐。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓犁跪,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親歹袁。 傳聞我的和親對(duì)象是個(gè)殘疾皇子坷衍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容