CSRF
CSRF(Cross Site Request Forgery, 跨站域請求偽造)的定義,相信大家都不陌生。它是指攻擊者透過誘導使用者,開啟已精心設計好的頁面後,傳送請求到某個網站執行某個操作(修改資料)的過程。這裡有以下三個前提:
1、使用者已登入某可信網站(A站,以下所提到的A站都指這裡的某可信網站)
2、A站存在某個請求,可以修改或儲存資訊(例如:/saveinfo)
3、使用者在A站Session過期前開啟攻擊者設計好的的頁面,並自動或觸發傳送請求(/saveinfo)
看起來要求聽苛刻的,但的確存在這種情況。“即便是大名鼎鼎的 Gmail, 在 2007 年底也存在著 CSRF 漏洞,從而被駭客攻擊而使 Gmail 的使用者造成巨大的損失。”
想要了解怎麼應對CSRF,先來看看攻擊者幹些什麼。
攻擊者能幹什麼
因為受同源策略限制,攻擊者並不能拿到A站的任何資訊(Cookies)和響應資訊,他只能利用傳送請求時,會帶上cookies去校驗登入資訊或許可權的特性,去修改使用者的資料,來達到攻擊目的。因此,一般用於獲取資訊而不涉及到修改資訊的請求(Get)就不用擔心會有CSRF危險了,重要的是能修改資訊的請求。當然,如果你用Get去修改資訊,那就需要考慮防範CSRF了。but這樣做本身就違背了HTTP method設定的初衷,同時Get的攻擊方式更為簡單,一個Img標籤加上JavaScript就能觸發。所以不建議這麼做
CRSF預防措施
正所謂兵來將擋,水來土掩。瞭解了攻擊者利用的一些原理,就對應的可以找到一些對應措施
1、在服務端驗證HTTP的Referer欄位。
此方法成本較小,只需要在服務端攔截請求,判斷Referer是否來自於同一域名,如果不是或者不存在CSRF的話,則認為有可能是CSRF攻擊,直接過濾。但這種方法也有弊端,那就是當有些人會擔心Referer會洩露個人資訊時(畢竟像伺服器傳送了自己的來源地址)。這些人會嘗試去關閉Referer。這樣當這些使用者發起請求時就不會帶上Referer,這個請求就會被判成有可能的CSRF攻擊,因為按照上述過濾規則,請求頭中無Referer的有可能會是CSRF攻擊。
2、在請求地址中新增 token 並驗證
此方法的核心思想就是,構造成什麼樣的資訊,來辨別請求是從使用者手中發出,還是被攻擊者利用而發出的,很顯然Cookie不能做到,因為使用者和攻擊者都能將同樣的Cookie帶到伺服器上。
答案就是token(令牌),它由服務端透過一定演算法生成,每當使用者請求頁面的時候,則向使用者返回的頁面中帶上一個全新的token。下次使用者在傳送請求的時候,就帶上該token與伺服器的token進行對比。但這token要放在哪裡呢?
三種情況:
1 對於Get請求,在Url後面動態加上token。 此方法也有一定約束,頁面有很多連結,一個一個加太麻煩,就需要在document載入完以後,透過js來輔助完成了。但這個方法對於動態生成的內容,就無能為力了。
2 Post請求 在form錶帶中加上
<pre>< input type=”hidden” name=token value=”tokenvalue”/>
</pre>
(檢視PC淘寶的個人中心,其修改資料就是用的此方法)由於同源策略,攻擊者是拿不到表單裡的資料的。此方法也跟Get請求有同樣的問題,那就是對於多連結和動態生成的內容,js批次加上token的辦法就不行了,只能手動新增。
3、對於Ajax請求,如果跨域,則預設不會帶上A站的cookie。因此,從某些方面來說,是相對安全的。但是根據w3c對Ajax的一個屬性的描述
4.6.4 The withCredentials attribute
client . withCredentials
True when user credentials are to be included in a cross-origin request. False when they are to be excluded in a cross-origin request and when cookies are to be ignored in its response. Initially false.
大概說的意思是,如果withCredentials為true,則存在跨域請求的時候,使用者的credentials(包括cookie,我是這麼理解的,如有錯歡迎指正)會被帶上。
如果將withCredentials設為true,這樣也會存在上述的安全問題,因為Cookies在傳送請求的同時也被戴上了。
總結
1、攻擊者是利用使用者登入過信任網站後,在會話未過期之前誘導使用者開啟有問題的網站而達到攻擊目的的
2、常見的防禦措施有校驗請求頭的referer,以及新增攻擊者無法獲取的隨機數token(令牌)來達到防禦目的的。
3、token存放的地方有多種,對於POST請求,則構造hideen的input標籤;對於Get則在連結後新增token;對於ajax,則在cookie中新增token。
4、個人覺得相對安全的做法就是既驗證referer,同時也校驗token。如涉及到更隱秘的操作,則需要透過驗證碼或者手動輸入密碼來做防範了。
參考文章:
https://www.w3.org/TR/2014/WD...
https://www.ibm.com/developer...
https://en.wikipedia.org/wiki...
第一次寫Post,過程如此之多,小到markdown語法;大到發現問題、探索分析問題、查閱資料並自測驗證。最後通篇檢查,是否存在有問題的地方。整個過程雖然比較難,但這讓自己對於CRSF有了更深刻的認識。在團隊完成分享後不遺餘力整理的一篇,相信以後會更好。