「明明保持著登入,只是打開了『另一個網站』,轉帳或修改設定就在你不知情時被執行了」——這就是 CSRF。本文講解其原理以及可靠的防範方法(不會寫出攻擊步驟)。
為什麼能成立(原理)
瀏覽器在向某個網站發起請求時,會自動附帶該網站的 Cookie。因此,只要使用者正登入著銀行網站,即便是從另一個惡意頁面向銀行發出操作請求,瀏覽器也會把「本人的 Cookie」一併發出去。從伺服器看來,這與本人的正規操作毫無區別。
XSS 是「讓程式碼在受害者的瀏覽器中執行」,而 CSRF 是「擅自借用受害者的登入狀態」的攻擊(→ XSS 是什麼)。
防禦
強制要求 CSRF Token
對改變狀態的操作(表單提交、API)要求一個無法猜測的一次性 Token。由伺服器簽發,請求中若不包含它則拒絕。許多框架都內建提供。
設定 SameSite Cookie
給工作階段 Cookie 加上 SameSite=Lax(或 Strict),不讓源自其他網站的請求附帶 Cookie。近年的預設值是 Lax,僅此一項就能起到很大作用。
不用 GET 來改變狀態
設計上讓瀏覽(GET)不產生副作用。變更一律用 POST/PUT/DELETE,並透過 Token 校驗。
校驗 Origin / Referer
對重要操作,在伺服器端確認請求來源(Origin)是否為本站,拒絕外部來源。
本站觀點:幾乎已「解決」但仍不可大意
憑藉現代框架的 CSRF Token+瀏覽器的 SameSite=Lax 預設值,典型的 CSRF 已大幅減少。話雖如此,在自行實作的 API、老舊結構、省去了 Token 的管理後台中,至今仍然照樣能被命中。即使「全權交給框架」,也最好親自確認一次改變狀態的路徑上是否都通過了 Token 校驗,這樣更安全。
常見的漏洞縫隙
即便了解原理,在實作中也容易在以下兩點出現疏漏。
- 讓 GET 帶有副作用:如果設計成用於瀏覽的 GET 會改變狀態,那麼僅憑一個圖片標籤或一條普通連結就可能讓 CSRF 成立。改變狀態務必使用 POST/PUT/DELETE,並透過 Token 校驗。
- 只有部分路徑忘了做 Token 校驗:在後來追加的 API 或管理功能中,常常會漏掉 Token 校驗。不要因「已交給框架」就放心,請把所有改變狀態的路徑清點一遍。
接著閱讀
FAQ
QCSRF 和 XSS 有什麼區別?
XSS 是讓「指令碼在受害者的瀏覽器中執行」的攻擊,CSRF 則是「借用受害者的登入狀態發出並非本意的請求」的攻擊。CSRF 即使無法執行指令碼,僅憑 Cookie 會被自動傳送這一特性就能成立。
QCSRF 最主要的防禦是什麼?
對改變狀態的操作(POST 等)強制要求 CSRF Token,並給工作階段 Cookie 設定 SameSite(Lax/Strict)。許多框架都內建提供 Token。此外,不用 GET 來改變狀態也是基本原則。
Q只靠 SameSite Cookie 夠嗎?
效果很大,但並非萬能。在舊版瀏覽器、某些轉址、子網域結構等情況下仍可能留有縫隙,因此與 CSRF Token 並用的多層防禦才更安全。