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 校驗。不要因「已交給框架」就放心,請把所有改變狀態的路徑清點一遍。
CSRF、XSS 與 SSRF 的比較
這三個名稱相近的攻擊,可以用「誰送出請求、依靠什麼」來區分。
| 攻擊 | 誰送出請求 | 被濫用的是什麼 | 主要防禦 |
|---|---|---|---|
| CSRF | 使用者的瀏覽器(使用者不知情) | 瀏覽器自動附帶 Cookie | CSRF Token、SameSite Cookie |
| XSS | 在使用者瀏覽器中執行的攻擊者指令碼 | 頁面輸出時缺少跳脫 | 輸出時跳脫、CSP |
| SSRF | 你的伺服器 | 會去抓取指定 URL 的功能 | 目的地允許清單、封鎖內部位址 |
CSRF 與 XSS 都經由使用者的瀏覽器作用。但如果頁面有 XSS,頁面內的指令碼就能讀到 CSRF Token,CSRF 防禦也就被繞過了。CSRF 防護的前提,是 XSS 已經處理好。
實際案例:偽造的投稿被當成本人所為
2012 年,有人透過橫濱市網站的意見表單,發布了攻擊小學的恐嚇文。看起來是發送來源的電腦持有人遭到逮捕,後來才發現是誤捕。同年 12 月,據日本媒體報導,東京警方說明該投稿是利用 CSRF 送出的:訪客打開留言板上張貼的連結後,瀏覽器就被迫送出了投稿。
從中可以得到兩個教訓。
- CSRF 的請求看起來與本人的完全相同:伺服器只看得到使用者的 IP 位址與 Cookie。光憑紀錄,無法分辨是使用者自己送的,還是被迫送出的。
- 不需登入的表單也在範圍內:那個意見表單不需要登入。凡是不希望被他人觸發的送出(投稿、申請、通報),不論是否需要登入,都要加上 Token。
CSRF 至今仍是常見的弱點。在 MITRE 於 2025 年 12 月公布的「CWE Top 25」(最危險的 25 種軟體弱點)中,CSRF(CWE-352)排名第三。
如何檢查自己的網站
在工作階段 Cookie 上明確設定 SameSite
用瀏覽器的開發人員工具(Application → Cookies)或網站健檢確認工作階段 Cookie 的 SameSite 屬性。Chrome 與 Edge 會把沒有此屬性的 Cookie 當作 Lax,但 Safari 與 Firefox 預設不會這樣做。不要依賴瀏覽器的預設值,請自己設定 SameSite=Lax 或 Strict。
檢查 CSRF 的豁免設定
確認框架的 CSRF 防護是否在某些路由上被關閉(Django 的 csrf_exempt、Laravel 的例外清單、Rails 的 skip_forgery_protection 等)。若有關閉的理由(例如接收 webhook 的路由),請改用簽章驗證來保護。
找出會改變狀態的 GET 路由
在路由清單中找出會刪除、更新或登出的 GET 路由。改成 POST 等方法,並透過 Token 校驗。
為重要操作再加一道確認
變更密碼或電子郵件地址、匯款、授予權限時,除了 Token 之外,再要求輸入目前的密碼或多因素認證。即使請求被偽造,本人確認也能擋下它。
出處(一手資料)
- OWASP, "Cross-Site Request Forgery Prevention Cheat Sheet" — cheatsheetseries.owasp.org(Token、Sec-Fetch-Site、SameSite 的極限、XSS 繞過 CSRF 防禦、不以 GET 改變狀態)
- MITRE, "2025 CWE Top 25 Most Dangerous Software Weaknesses"(2025 年 12 月)— cwe.mitre.org(CWE-352 排名第三)
- web.dev, "SameSite cookies explained" — web.dev(哪些瀏覽器把沒有屬性的 Cookie 當作 Lax)
- INTERNET Watch,遠端操控惡意軟體事件的報導(2012 年 12 月 14 日,日文)— internet.watch.impress.co.jp(警方說明橫濱市的投稿使用了 CSRF)
- @IT,冒充型惡意軟體與 CSRF 導致誤捕的報導(2012 年 11 月,日文)— atmarkit.itmedia.co.jp
- IPA「安全なウェブサイトの作り方」(日文)— ipa.go.jp