CSRF 的攻擊過(guò)程

登錄態(tài) Cookie 的 Key 是瀏覽器默認(rèn)自動(dòng)攜帶的,Key 通常是會(huì)話 Cookie,只要瀏覽器不關(guān)閉,Key 一直存在。所以只要用戶 A 曾經(jīng)登錄過(guò)相冊(cè)網(wǎng)站(這里用 http://www.photo.com 舉例),瀏覽器沒(méi)有關(guān)閉,用戶在沒(méi)有關(guān)閉的瀏覽器打開(kāi)一個(gè)黑客網(wǎng)頁(yè)(這里用 http://www.hacker.com),黑客頁(yè)面發(fā)送 HTTP 請(qǐng)求到 http://www.photo.com 的后臺(tái)會(huì)默認(rèn)帶上 http://www.photo.com 的登錄態(tài) Cookie,也就能模擬用戶 A 做一些增刪改等敏感操作。Get 和 Post 都一樣,這就是 CSRF 攻擊原理。這種攻擊過(guò)程也是最常見(jiàn)的攻擊過(guò)程。
上面說(shuō)的增刪改都是寫(xiě)操作,會(huì)對(duì)后臺(tái)數(shù)據(jù)產(chǎn)生負(fù)面影響,所以是能被攻擊的。另外一種讀操作,是具有冪等性,不會(huì)對(duì)后臺(tái)數(shù)據(jù)殘生負(fù)面影響,能否被攻擊到?讀操作也可能是敏感數(shù)據(jù),舉個(gè)例子,比如 www.photo.com 上的私密相冊(cè)數(shù)據(jù)能否被 www.hacker.com 頁(yè)面拿到?這就涉及到前端跨域知識(shí)點(diǎn)了,默認(rèn)大部分情況是拿不到,這里列舉兩種特殊情是可以拿到的:
如果后臺(tái)返回的數(shù)據(jù)是 JSONP 格式的,這種只能是 Get 操作,是能被黑客頁(yè)面拿到的。
如果后臺(tái)是通過(guò) CORS 處理跨域,沒(méi)有對(duì)請(qǐng)求頭的 Origin 做白名單限制,ACAO 響應(yīng)頭是 * 或者包括黑客頁(yè)面,包括 Get/Post/Del 等操作,也是能被黑客頁(yè)面拿到的。
除了這兩種特殊情況,讀操作都是不能被攻擊到的,因?yàn)闉g覽器跨域限制是天然的安全的。關(guān)于跨域知識(shí)細(xì)節(jié),我寫(xiě)過(guò)另外一篇文章。
知道攻擊原理,防護(hù)方法也很簡(jiǎn)單,找到能夠區(qū)分請(qǐng)求發(fā)送的頁(yè)面是自己的頁(yè)面還是黑客的頁(yè)面的方法就可以了。
HTTP 請(qǐng)求頭 Referrer 字段是瀏覽器默認(rèn)帶上,含義是發(fā)送請(qǐng)求的頁(yè)面地址,比如同樣是刪除相冊(cè)的操作 http://www.photo.com/del?id=xxx; 如果是從相冊(cè)自己頁(yè)面發(fā)送出來(lái),Referrre的值是 http://www.photo.com/index.html(以首頁(yè)舉例),如果是從黑客頁(yè)面發(fā)送出來(lái)的Referrer的值是 http://www.hacker.com/index.html(以首頁(yè)舉例),所以后端只要通過(guò)Referrrer做白名單判斷就能防這種常見(jiàn)的CSRF攻擊。
Referrer 會(huì)不會(huì)被偽造或者篡改?在瀏覽器環(huán)境下,Referrer 是瀏覽器自己帶上的,js 是改不了 Rerferrer,所以是不能被偽造和篡改的。瀏覽器插件能改 Referre,通過(guò)網(wǎng)關(guān)或者抓包也能修改 Referrer。除了這幾種特殊情況,用 Referrer 防 CSRF 是安全的。
讀寫(xiě) Cookie 有跨域限制(作用域,Domain,Path),所以我們可以用這個(gè)特性來(lái)區(qū)分是自己頁(yè)面還是黑客頁(yè)面。只要頁(yè)面能讀(或者寫(xiě))www.photo.com 域名 Cookie,就證明是自己的頁(yè)面。懂了原理,方案就很簡(jiǎn)單,比如服務(wù)器通過(guò) cookie 下發(fā)一個(gè) token,token 值是隨機(jī)數(shù),頁(yè)面發(fā)請(qǐng)求的時(shí)候從 cookie 取出 token 通過(guò) HTTP 請(qǐng)求參數(shù)傳給后臺(tái),后臺(tái)比對(duì)參數(shù)里的 token 和 cookie 里的 token 是否一致,如果一致就證明是自己頁(yè)面發(fā)的請(qǐng)求,如果不一致就返回失敗。防 CSRF 的方案就是這么簡(jiǎn)單,這種方法能夠 100%防 CSRF。
