文章目錄
CSRF攻擊
#1 什麼是CSRF攻擊
CSRF跨站點請求僞造(Cross—Site Request Forgery)
攻擊者盜用了你的身份(TOKEN或Cookie等認證),以你的名義往服務器發請求,這個請求對於服務器來說是完全合法的,但是卻完成了攻擊者所希望的操作,而你全然不知,例如:以你的名義發送郵件,轉賬之類的操作
CSRF攻擊過程 :
- 用戶Tom打開瀏覽器,訪問 https://weibo.com/, 輸入賬號密碼登錄微博
- 微博後臺驗證賬號密碼通過之後,會返回一個Cookie,保存到瀏覽器中,此時用戶登錄成功,並能夠像微博發送請求
- 在用戶沒用退出微博登錄時,打開另一個網站A,網站A接收到用戶請求後,返回一些攻擊性代碼,併發出一個請求要求訪問微博
- 瀏覽器在接收到這些攻擊性代碼後,根據網站A的請求,在用戶不知情的情況下,攜帶Cookie往微博發請求,對微博後臺來說,這個請求是完全合法的,所以會根據用戶Tom的Cookie信息以Tom的權限處理該請求,導致來自網站A的惡意代碼被執行。
CSRF攻擊實例 :
小明使用瀏覽器登錄銀行網站後,銀行後臺會返回一個Cookie並存到小明電腦的瀏覽器中,在這個Cookie還沒有過期之前,小明點擊了瀏覽器彈出的廣告,此時跳轉到另外一個網站A,網站A有一段惡意代碼,代碼內容是: 往銀行後臺發送一個轉賬的請求(攜帶Cookie),這時,悲劇發生了,這個 url 請求就會得到響應,錢將從小明的賬號轉移到攻擊者的賬號,而小明當時毫不知情,等以後小明發現賬戶錢少了,即使他去銀行查詢日誌,他也只能發現確實有一個來自於他本人的合法請求轉移了資金,沒有任何被攻擊的痕跡。
#2 Cookie
正常的CSRF攻擊,攻擊發送的請求默認會自動攜帶Cookie
Cookie字段 | 含義 |
---|---|
NAME=VALUE | 賦予 Cookie 的名稱和其值(必需項) |
expires=DATE | Cookie 的有效期(若不明確指定則默認爲瀏覽器關閉前爲止) |
path=PATH | 將服務器上的文件目錄作爲Cookie的適用對象(若不指定則默認爲文檔所在的文件目錄) |
domain=域名 | 作爲 Cookie 適用對象的域名 (若不指定則默認爲創建 Cookie的服務器的域名) |
Secure | 僅在 HTTPS 安全通信時纔會發送 Cookie |
HttpOnly | 加以限制, 使 Cookie 不能被 JavaScript 腳本訪問 |
對於一個Http POST請求 http://xxx.minhung.me/ooooo/create-msg來說
如果滿足下面幾個條件:
- 瀏覽器端某個Cookie的domain字段等於xxx.minhung.me或者minhung.me
- 都是http或者https,或者在不同的情況下Secure屬性爲false
- 要發送請求的路徑,即上面http://xxx.minhung.me/ooooo/create-msg的ooooo跟瀏覽器端Cookie的path屬性必須一致,或者是瀏覽器端Cookie的path的子目錄,比如瀏覽器端Cookie的path爲/test,那麼ooooo必須爲/test或者/test/xxxx等子目錄纔可以
上面3個條件必須同時滿足,否則該Post請求就不能自動帶上瀏覽器端已存在的Cookie
因爲在CSRF攻擊中,訪問的就是設置Cookie的服務端的接口,所以訪問的時候會自動攜帶Cookie
#3 瀏覽器的同源策略
瀏覽器的同源策略,總的而言有以下三點限制:
- 一是來自一個源的js只能讀寫自己源的存儲不能讀寫其他源的存儲,存儲包括Cookie、Session Storage、Local Storage、Cache、Indexed DB等。
- 二是來自一個源的js只能讀寫自己源的DOM樹不能讀取其他源的DOM樹。即如果開始討論,iframe內外層不同源就不能相互操作,外層想獲取內層的內容只能使用點擊劫持配合;實現原理亦如前所述未知。
- 三是一般而言來自一個源的js只能向自己源的接口發送請求不能向其他源的接口發送請求。當然其實本質是,一方面瀏覽器發現一個源的js向其他源的接口發送請求時會自動帶上Origin頭標識來自的源,讓服務器能通過Origin判斷要不要嚮應;另一方面,瀏覽器在接收到響應後如果沒有發現Access-Control-Allow-Origin允許發送請求的域進行請求那也不允許解析。自己之前也抱怨過,又不是服務器不響應服務器響應了不瀏覽器不(允許js)解析是不是沒什麼意義的多此一舉;現在看來,通過自己寫python等方法也確實能請求其他服務器並解析其結果,瀏覽器沒有Access-Control-Allow-Origin允許不解析一是說維護了自己同源策略的思想二是說至少可以保證不會在自己身上出現A域可隨便探測B域的情況,所以也不能說完全沒用。
- 四是來自一個源的js不能隨意操作瀏覽器之外的資源。比如打開命令提示符、執行系統命令等等。倘若你訪問一個網站該網站的js可以直接調用系統命令給你電腦進行添加用戶等操作,那問題就大了。
在瀏覽器的同源策略下, 其他站點的js是不能讀寫別的站點的Cookie、Session Storage、Local Storage、Cache、Indexed DB
#3 前後端分離項目如何避免CSRF攻擊
防禦方案 :
- 用戶操作限制,比如驗證碼
- 請求來源限制,比如限制HTTP Referer才能完成操作
- token驗證機制,比如請求數據字段中添加一個token,響應請求時校驗其有效性
#3.1 防禦一 — 驗證碼
發送請求時,需要驗證碼驗證是否是用戶本人,次方案明顯嚴重影響了用戶體驗,而且還有額外的開發成本
#3.2 防禦二 — HTTP Referer
次方案成本最低,但是並不能保證100%安全,而且很有可能會埋坑
Referer 是 HTTP 請求header 的一部分,當瀏覽器(或者模擬瀏覽器行爲)向web 服務器發送請求的時候,頭信息裏有包含 Referer 。比如我在www.google.com 裏有一個www.baidu.com 鏈接,那麼點擊這個www.baidu.com ,它的header 信息裏就有:
Referer=http://www.google.com
所以,將這個http請求發給服務器後,如果服務器要求必須是某個地址或者某幾個地址才能訪問,而你發送的referer不符合他的要求,就會攔截或者跳轉到他要求的地址,然後再通過這個地址進行訪問。
#3.3 防禦三 — TOKEN
用戶登錄成功後,服務端將用戶名和一些關鍵數據生成一個Token,將Token封裝到Cookie中,然後發送給客戶端,每次客戶端發送請求時,先獲取Cookie中的Token,再攜帶該Token訪問服務端