Cross-Site Request Forgery(CSRF,跨站請求偽造)利用瀏覽器會自動附帶 Cookie 等登入憑證的特性,誘使已登入使用者對受信任網站送出非本人意圖的狀態變更。防護核心不是只判斷『這個人有沒有登入』,而是讓伺服器能驗證『這次操作是否由受信任頁面、針對目前工作階段明確發起』。

先講結論:登入證明身分,CSRF 防護證明操作意圖
MITRE CWE-352 將 CSRF 描述為:Web 應用程式未能充分驗證請求是否由送出請求的使用者有意提供。當受害者已登入網站,瀏覽器可能在跨站請求中自動帶上 Session Cookie;若伺服器只看到有效 Session 就執行操作,便無法區分正常請求與第三方網站觸發的偽造請求。
CSRF 的典型影響不是讓攻擊者直接讀取跨來源回應,而是借用受害者的瀏覽器與權限完成動作,例如修改聯絡資料、建立 API Key、變更權限、送出交易或更改系統設定。實際風險受端點功能與受害者權限限制;管理者或高權限帳號被利用時,影響通常更大。
可靠防護應把『身分驗證』與『請求意圖驗證』分開。Session Cookie 證明目前瀏覽器持有登入狀態;Anti-CSRF Token、Origin/Referer、Fetch Metadata 或高風險操作的再次確認,則協助伺服器確認請求確實來自允許的互動脈絡。
- 所有會改變資料或權限的操作使用 POST、PUT、PATCH 或 DELETE,不以 GET 執行狀態變更
- Cookie 型工作階段啟用框架內建 CSRF Middleware,並套用到所有狀態變更端點
- Stateful 應用使用 Synchronizer Token;無伺服器 Token 狀態時使用與 Session 綁定的 Signed Double-Submit Cookie
- 設定合適的 SameSite、Secure、HttpOnly 與 Cookie Scope,並加入 Origin/Referer 或 Fetch Metadata 縱深驗證
- 高風險操作要求重新驗證、交易確認或其他使用者互動證據
- 修復後以真實瀏覽器確認跨站請求被拒絕,而且合法流程、登入與第三方整合仍正常
一次 CSRF 成立需要哪些條件?
第一個條件是受害者瀏覽器持有網站接受的 Ambient Credential,也就是瀏覽器會依請求條件自動附帶的憑證,最常見是 Session Cookie,也可能是 HTTP Authentication 或 Client Certificate。若 API 只接受由應用程式程式碼主動放入 Authorization Header 的 Bearer Token,傳統 CSRF 的成立條件通常不同。
第二個條件是存在可由瀏覽器跨站觸發、且會改變系統狀態的端點。HTML Form、圖片或導覽能建立某些『Simple Request』;即使同源政策阻止攻擊頁面讀取回應,請求仍可能送達伺服器。把刪除、確認或設定變更放在 GET,會使風險更容易被連結、圖片或預載機制觸發。
第三個條件是伺服器沒有驗證不可由外部網站取得或預測的意圖證據。只檢查登入狀態、Cookie 是否存在、User-Agent、固定 Header 或可預測欄位都不夠。攻擊者不一定需要知道回應內容,只要能讓操作成功就可能造成影響。
| 必要條件 | 應確認的問題 | 證據示例 |
|---|---|---|
| 瀏覽器自動帶上憑證 | 跨站導覽或表單送出時,Session Cookie 是否仍會附帶? | Cookie 的 Domain、Path、SameSite、Secure 與實際 Request Header |
| 存在狀態變更端點 | 請求是否會修改資料、權限、交易、設定或工作流程? | 操作前後狀態、HTTP 方法、端點與必要參數 |
| 第三方網站可建立請求 | HTML Form、導覽或可允許的 Content-Type 能否送達端點? | 瀏覽器 Network 紀錄、Origin、Sec-Fetch-Site 與伺服器日誌 |
| 缺少意圖驗證 | Token、Origin 或其他防護是否缺失、未綁定 Session 或只檢查存在? | 正常與跨站請求的控制差異、驗證失敗行為 |
| 受害者擁有可利用權限 | 目前角色能完成什麼操作?影響是否跨租戶或擴大權限? | 專用測試帳號、角色矩陣與最小無害狀態變更 |
瀏覽器為什麼會幫忙送出憑證?Same-Origin Policy 不會擋嗎?
Same-Origin Policy 主要限制一個來源的程式碼讀取另一來源的資料,但不等於禁止所有跨來源請求。瀏覽器長期支援跨站連結、圖片、表單與導覽;只要 Cookie 的 Scope 與 SameSite 規則允許,瀏覽器仍可能把 Cookie 附在目標網站的請求上。
CORS 則是伺服器透過回應標頭允許特定來源的前端程式讀取回應,並在某些非簡單請求前進行 Preflight。它不是通用 CSRF 防火牆:傳統 HTML Form 可送出 application/x-www-form-urlencoded、multipart/form-data 或 text/plain 等 Simple Request,而攻擊者常不需要讀取回應。
因此,『瀏覽器 Console 出現 CORS 錯誤』不能作為 CSRF 已被阻止的證據。檢測時要看請求是否真的到達伺服器、Session 是否被附帶,以及資料是否改變,而不是只看攻擊頁面能否取得 Response Body。
CSRF、XSS、CORS、SSRF 與 Clickjacking 有什麼不同?
這些議題都涉及信任邊界,但攻擊位置與控制點不同。CSRF 借用受害者瀏覽器自動攜帶的身分,目標是讓伺服器執行非預期操作;XSS 則讓攻擊者控制的程式在受信任 Origin 中執行,通常能取得頁面內 Token 或直接發送同源請求,因此 OWASP 明確提醒 XSS 可以繞過大多數 CSRF 防護。
SSRF 是伺服器被誘使向內部或外部資源發出請求,與受害者瀏覽器 Session 不同;Clickjacking 是透過透明或誤導介面讓使用者實際點擊目標頁面。CORS 是瀏覽器的跨來源讀取政策,不是一種弱點類型,也不能代替 CSRF Token。
| 議題 | 被利用的執行位置 | 攻擊者主要目標 | 主要防護方向 |
|---|---|---|---|
| CSRF | 受害者瀏覽器對受信任網站送出請求 | 借用登入狀態執行非本人意圖的操作 | Token、SameSite、Origin/Referer、Fetch Metadata、再次確認 |
| XSS | 受信任網站的 Origin 與 DOM | 執行攻擊者程式、讀取頁面或呼叫同源功能 | 情境式輸出編碼、安全 DOM API、HTML Sanitization、CSP |
| CORS 設定 | 瀏覽器跨來源讀取回應 | 決定哪些來源的前端程式可讀取資源 | 精確 Allowlist、Credentials 規則、避免反射任意 Origin |
| SSRF | 伺服器端網路與服務帳號 | 讓伺服器存取攻擊者指定的目的地 | 目的地 Allowlist、網路分段、Metadata 防護、URL 驗證 |
| Clickjacking | 被 Frame 的目標頁面與使用者點擊 | 欺騙使用者在看不見或誤導的介面上操作 | CSP frame-ancestors、X-Frame-Options、交易確認 |
哪些功能最容易出現 CSRF?不要只看轉帳與刪除
任何會改變伺服器狀態的功能都應納入盤點,包括個人資料、Email/手機、密碼、MFA、收件地址、付款方式、通知設定、API Key、Webhook、團隊成員、角色、內容發布、訂單、退款與管理後台設定。即使單一操作看似低風險,也可能成為帳號接管或權限提升鏈的一部分。
Login CSRF 也常被忽略。若登入端點沒有將登入嘗試綁定到開始流程的瀏覽器脈絡,受害者可能被登入到攻擊者控制的帳號,之後把個資、交易或其他敏感內容誤存到該帳號。OAuth Redirect Endpoint 則需要依授權協定處理 state、nonce、PKCE 與 Issuer,而不是直接套用一般表單 Token。
批次、匯入、Approve、Invite、Preview、Test Connection、Generate Token 等功能也可能有狀態副作用。盤點時應從 Server Route、API Schema、Audit Log 與權限矩陣交叉確認,不應只依畫面按鈕文字判斷。
| 功能類型 | 常見操作 | 可能影響 |
|---|---|---|
| 帳號安全 | 變更 Email、密碼、MFA、恢復資訊、連結第三方帳號 | 帳號接管、通知轉移、復原管道被替換 |
| 權限與整合 | 邀請成員、變更角色、建立 API Key、Webhook、OAuth 連結 | 權限提升、持久存取、資料流向外部 |
| 交易與資產 | 付款、退款、地址、訂單、資產刪除與發布 | 財務損失、資料完整性與服務中斷 |
| 管理與平台設定 | SSO、網域、稽核、網路、掃描與通知策略 | 組織級控制遭改變或安全監控失效 |
| 登入與授權流程 | 登入、OAuth Callback、連結/切換帳號 | Login CSRF、錯誤帳號綁定、授權回應注入 |
怎麼安全檢測 CSRF?必須在真實瀏覽器中驗證
測試前先取得明確授權、資產範圍、測試帳號、允許的狀態變更與還原方式。優先使用專用測試租戶及可回復資料,避免對真實付款、刪除、外部通知、MFA、管理員權限或第三方整合直接操作。
先記錄正常流程的 Request:方法、URL、Content-Type、Cookie、Origin、Referer、Sec-Fetch-*、Token 的位置與操作前後狀態。接著一次只移除或改變一個控制,例如 Token 缺失、Token 不符、不同 Session、跨站 Origin 或不同 Content-Type,確認伺服器是否在執行業務邏輯前拒絕。
真正的 CSRF 複驗需要瀏覽器,因為 Cookie 的 SameSite、導覽類型、Redirect、Preflight 與 Fetch Metadata 都是瀏覽器脈絡的一部分。只在攔截代理中重送一筆帶完整 Cookie 的 Request,不能證明外部網站能讓瀏覽器建立相同請求。
- 列出所有狀態變更路由,先找出錯用 GET、方法覆寫與未經保護的舊版端點
- 為不同角色、租戶與登入方式建立基線,記錄 Cookie 與 Token 來源
- 以外部 Origin 的最小測試頁面驗證瀏覽器實際送出的 Header 與 Cookie
- 只做可回復、無外部副作用的狀態變更,保留操作前後證據
- 對 Login、OAuth、Iframe、跨子網域與第三方整合使用各自正確的流程驗證
- 測試完成後清理資料、撤銷測試 Token 並確認沒有殘留帳號或權限變更
一筆可信的 CSRF 發現需要哪些證據?
報告至少應包含資產、端點、方法、角色、租戶、登入方式、Cookie 屬性、正常 Request 與跨站 Request 的差異。最重要的結果不是攻擊頁面看到什麼,而是伺服器是否接受請求,以及受保護資源的狀態是否真的改變。
證據要說明防護為何失效。例如 Token 完全不存在、只檢查參數名稱、不同 Session 的 Token 仍可使用、Double-Submit 未與 Session 綁定、Origin 驗證在代理後取錯 Host,或 SameSite 設為 None 且沒有其他控制。不要只寫『缺少 CSRF Token』就直接推論可利用。
影響評估應以最小證明為原則:使用測試欄位或可還原設定,證明操作前後差異後停止。若端點理論上可執行更高風險行為,但未在授權範圍驗證,應明確標示為推論,不擷取真實資料或擴大權限。
| 證據 | 應記錄內容 | 判讀與保護要求 |
|---|---|---|
| 資產與身分 | Host、Path、方法、角色、租戶、登入方式與 Session 範圍 | 使用專用帳號,不暴露真實 Cookie 或 Token |
| 正常基線 | 完整流程的 Header、Content-Type、Token 來源與操作前後狀態 | 遮罩秘密值,但保留值是否一致與綁定關係 |
| 跨站脈絡 | 攻擊頁 Origin、導覽方式、Sec-Fetch-Site、Cookie 是否附帶 | 證明由真實瀏覽器建立,不只是在 Proxy 重放 |
| 控制失效 | Token 缺失/不符、Origin 判斷、SameSite、方法或 CORS 行為 | 一次改一個變因,找出實際根因 |
| 狀態變更 | 伺服器回應、Audit Log、資料修改前後與還原結果 | Response Body 不可讀仍可能成立 |
| 修復複驗 | 修復版本、拒絕狀態、合法流程與相鄰端點回歸 | 確認拒絕發生在任何副作用之前 |
核心修復一:Stateful 應用使用 Synchronizer Token Pattern
Synchronizer Token 由伺服器產生並與使用者 Session 關聯,正常頁面把 Token 放進 Hidden Field、JSON 或自訂 Request Header,狀態變更時由後端比對 Request Token 與 Session 內的預期值。外部網站無法讀取同源頁面中的 Token,因此即使瀏覽器自動帶上 Cookie,也無法建立完整的合法請求。
OWASP 建議 Token 必須對每個 Session 唯一、秘密且不可預測。可採每 Session 或每 Request Token;每 Request Token 縮短重播範圍,但需處理瀏覽器返回、平行分頁與重送造成的可用性問題。Token 不應出現在 URL,避免洩漏到瀏覽紀錄、伺服器日誌、Referer 或分析系統。
驗證必須在伺服器端、所有狀態變更邏輯之前執行。Token 缺失、不符、過期或不屬於目前 Session 時,應一致拒絕並留下不含秘密值的安全事件。只在前端 JavaScript 檢查、只判斷欄位存在,或把 Session Cookie 本身當 Token,均無法建立可信的意圖證據。
請求意圖驗證:有 Session 還不夠,Token 必須與伺服器預期值相符
下圖上方是合法同站流程:瀏覽器送出 Session 與只有受信任頁面能取得的 Anti-CSRF Token,伺服器將 Token 與目前 Session 的預期值比對後才執行操作。下方的外部頁面雖能讓瀏覽器附帶 Session,卻沒有相符 Token,因此應在進入商業邏輯前被拒絕。
Token 的角色不是再次證明使用者是誰,而是增加外部網站無法自行補齊的請求條件。若 Token 可以預測、未綁定 Session、只在 Cookie 中自動傳送,或驗證發生在狀態已改變之後,就失去這個安全性質。

核心修復二:Stateless 架構使用 Signed Double-Submit Cookie
Double-Submit Cookie 讓前端把 Token 以 Cookie 與 Request Parameter/Header 兩個通道送出,伺服器比較兩者。Cookie 會自動附帶,但外部網站通常無法讀取 Token 並把相同值放入 Request Body 或自訂 Header,因此可建立額外驗證條件。
新系統不應使用未綁定 Session 的 Naive Double-Submit。OWASP 建議使用 Signed Double-Submit Cookie,以伺服器秘密產生 HMAC,明確綁定會隨登入 Session 改變的值與隨機值。這能降低攻擊者透過可控制子網域、DNS 接管或 Cookie Injection 植入自選 Token 的風險。
簽章不等於加密,也不能把 Session ID 明文放進 Client Token。伺服器應使用恆定時間比較、妥善管理 HMAC Key,並在登入 Session 改變時讓舊 Token 失效。若採用 Cookie Prefix,__Host- 可進一步限制 Secure、Path=/ 且不得設定 Domain,但仍需確認目標瀏覽器與部署條件。
| 模式 | 適合情境 | 必要安全條件 | 常見失敗 |
|---|---|---|---|
| Synchronizer Token | 伺服器維護登入 Session 的 Web 應用 | Token 與 Session 關聯、不可預測、由 Request 明確送回 | Token 放在 URL、只驗證存在、漏套用部分路由 |
| Signed Double-Submit Cookie | 無法保存 Server-side CSRF Token 狀態的架構 | HMAC 簽章、與登入 Session 綁定、Cookie 與 Header/參數雙通道 | 只簽隨機值未綁 Session、Cookie Scope 過寬 |
| Naive Double-Submit | 既有系統的過渡盤點,不建議新設計 | 至少使用不可預測值並評估 Cookie Injection | 攻擊者可寫入同網域 Cookie 時植入匹配值 |
| Custom Header | 同源 SPA 或受控 API Client | 瀏覽器程式主動加入 Header、CORS 精確 Allowlist | CORS 反射任意 Origin 或允許不受控子網域帶 Credentials |
SameSite Cookie 怎麼選?Strict、Lax、None 都有取捨
SameSite 控制 Cookie 在跨 Site 請求中的傳送。Strict 只在 Same-Site 請求附帶,防護最強,但使用者從外部連結進站時可能失去登入脈絡;Lax 允許部分頂層、安全方法導覽,通常較兼顧可用性;None 允許跨 Site 傳送,並必須搭配 Secure,常見於確實需要第三方嵌入或跨站流程的情境。
MDN 說明部分瀏覽器在未指定時會採較寬鬆的 Lax 預設,且可能短暫允許最近設定的 Cookie 隨跨站 POST 傳送。安全設計應明確設定屬性,不依賴瀏覽器預設;同時要理解 Same-Site 與 Same-Origin 不同,兄弟子網域可能屬於 Same-Site,因此不受控子網域會影響信任模型。
SameSite 是強而實用的縱深控制,但不能普遍取代 Token。合法 SSO、OAuth、付款、嵌入式內容、舊瀏覽器、Client-side CSRF 或同 Site 不同 Origin 情境都需要額外設計。Session Cookie 仍應搭配 Secure、HttpOnly、最小 Domain/Path 與適當生命週期。
| 設定 | 典型跨 Site 行為 | 適用考量 | 不能忽略的限制 |
|---|---|---|---|
| Strict | 跨 Site 請求不帶 Cookie | 高敏感後台或不需外部導流的工作階段 | 外部連結、SSO 或跨站流程可能失去登入狀態 |
| Lax | Same-Site 請求與部分頂層安全方法導覽可帶 Cookie | 多數一般網站 Session 的實用起點 | 狀態變更 GET 仍危險;瀏覽器預設行為可能有相容差異 |
| None; Secure | Same-Site 與 Cross-Site 均可帶 Cookie | 確實需要第三方嵌入或跨站互動 | 必須有 Token、Origin 或其他完整 CSRF 防護 |
Origin、Referer 與 Fetch Metadata:建立伺服器端縱深防線
對狀態變更請求,伺服器可先驗證 Origin 是否精確符合允許來源;若 Origin 不存在,再依風險政策檢查 Referer。比對時必須解析 Scheme、Host 與 Port,不能使用字串開頭或包含判斷,也不能信任由外部 Client 任意提供的 X-Forwarded-Host;部署在 Proxy/CDN 後要建立可信代理清單與正確的 Target Origin 設定。
Fetch Metadata 由瀏覽器提供 Sec-Fetch-Site、Sec-Fetch-Mode、Sec-Fetch-Dest 與 Sec-Fetch-User 等請求脈絡。OWASP 建議將 Sec-Fetch-Site: cross-site 的非安全方法預設視為不可信並拒絕,再依真正需要的導覽與資源例外調整。對未傳送 Sec-Fetch-* 的舊 Client,仍需 Origin/Referer 或 Token 等 Fallback。
這些 Header 適合作為 Token 之外的縱深控制與監控訊號。導入前可先 Report-only:記錄會被拒絕的請求、來源、路由與業務流程,修正合法例外後再阻擋,避免一次性政策中斷 Webhook、SSO、舊版 App 或企業代理流量。
| 控制 | 主要訊號 | 適合用途 | 部署注意 |
|---|---|---|---|
| Origin 驗證 | Request 的 Scheme、Host、Port | 狀態變更與 CORS API 的來源確認 | 精確解析並考慮信任代理,不做模糊字串比對 |
| Referer Fallback | 發起頁面的完整或部分 URL | Origin 缺失時的次要來源訊號 | 可能受 Referrer-Policy、隱私工具或代理影響 |
| Sec-Fetch-Site | same-origin、same-site、cross-site、none | 快速拒絕明顯跨站的非安全方法 | 舊 Client 可能缺失;same-site 不等於 same-origin |
| Sec-Fetch-Mode/Dest/User | 導覽模式、資源類型與使用者啟動訊號 | 細化頂層導覽與資源例外 | 建立明確 Allowlist,不以複雜例外掩蓋根因 |
| 使用者互動 | 再次登入、MFA、交易確認、目前密碼 | 高風險與不可逆操作 | 不能用容易點擊劫持的普通確認框取代 |
AJAX、SPA 與 API 還需要 CSRF 嗎?先看憑證如何傳送
如果 Web API 透過 Cookie 驗證,無論前端是傳統頁面、SPA、GraphQL 或 REST,都仍要考慮 CSRF。可讓前端從受信任頁面取得 Token,再以自訂 Header 送出;第三方網站無法以普通 HTML Form 加入自訂 Header,瀏覽器也會對跨來源非簡單請求執行 CORS Preflight。
此模式的前提是 CORS 嚴格限制可信 Origin。Access-Control-Allow-Origin 不應反射任意來源,不應以寬鬆正規式接受可被接管的子網域;使用 Credentials 時不能搭配 *。預檢、實際回應與錯誤回應都要維持一致政策。
如果 API 只接受應用程式主動加入 Authorization Header 的 Bearer Token,而且瀏覽器不會自動附帶該 Token,傳統 Cookie 型 CSRF 的可利用性通常較低。但 Token 儲存、XSS、瀏覽器擴充功能、Redirect 與 Mobile Deep Link 仍有其他風險;不能因此省略授權、Token Scope、撤銷與輸入驗證。
Login CSRF、OAuth 與 OpenID Connect 要怎麼防?
Login CSRF 的目的可能是讓受害者登入攻擊者帳號,之後把資料或操作留在錯誤帳戶。傳統登入表單可使用 Pre-Session 與登入流程綁定的 CSRF Token,登入成功後再輪替 Session,避免把未驗證流程直接併入正式工作階段。
OAuth Client 的 Redirect Endpoint 需要防止外部第三方注入授權回應。RFC 9700 要求 Client 防止 CSRF:可使用一次性且與 User Agent Session 安全綁定的 state;OpenID Connect 的 nonce 可提供相應保護;已確認 Authorization Server 支援並強制 PKCE 的情境,也可依規範使用 PKCE 的保護。state 若承載應用狀態,還要防止內容被竄改或交換,使用後應立即失效。
同時連接多個 Authorization Server 的 Client 還要防止 Mix-Up Attack,驗證回應中的 Issuer 或採不同 Redirect URI。一般表單的 Hidden CSRF Token、OAuth state、OIDC nonce 與 PKCE 解決的脈絡不同,實作與測試時不可只看到『有一個隨機值』就視為等價。
高風險操作需要比 Token 更強的交易確認
Anti-CSRF Token 能證明請求來自受信任流程,但不一定能證明使用者理解交易內容。變更密碼、MFA、收款帳戶、API Key、管理員角色、SSO 或大額交易等高風險操作,應要求重新輸入目前密碼、完成 MFA、確認交易摘要或使用與特定交易資料綁定的授權步驟。
確認畫面應重新呈現關鍵資料,例如對象、金額、權限與不可逆後果,而不是只顯示『確定嗎?』。伺服器端要把確認憑證與具體交易內容、使用者、Session、期限與一次性使用綁定,避免攻擊者將已確認的低風險操作替換成另一筆交易。
此層也能降低 XSS、Session Riding、誤操作與被竄改前端流程的部分影響,但不能取代底層 CSRF 防護。設計目標是讓一般操作順暢、高風險操作有可稽核且與交易內容一致的明確意圖。
常見錯誤修法:看似有 Token,實際仍可繞過
最常見問題是防護覆蓋不完整:新 API 有 Middleware,舊 Controller、GraphQL Mutation、檔案上傳、方法覆寫、批次端點或管理後台卻沒有;或只有 UI 按鈕帶 Token,直接呼叫 Endpoint 仍可成功。防護必須在伺服器路由層預設啟用,再用小而明確的例外清單管理。
另一類問題是 Token 設計錯誤,包括固定值、可預測值、只驗證欄位存在、接受任意 Session 的 Token、把 Token 只放在會自動傳送的 Cookie、在 URL 傳送,或用可被子網域植入的 Naive Double-Submit。Token 也不應被寫入錯誤訊息、分析事件或完整 Request Log。
只加 SameSite、只檢查 Referer、只看到 CORS 錯誤、只用 WAF 或要求自訂 Header 卻允許任意 Credentialed Origin,都不足以結案。正確修復要能明確說明保護的端點集合、主要控制、Fallback、Cookie 政策、例外與複驗結果。
| 錯誤修法 | 為何不足 | 正確方向 |
|---|---|---|
| 只檢查使用者已登入 | Cookie 本來就會隨符合條件的跨站請求附帶 | 加入不可由第三方網站補齊的意圖驗證 |
| 只確認 Token 參數存在 | 固定值、空值或其他 Session Token 仍可能通過 | 比對目前 Session 的不可預測 Token,缺失或不符即拒絕 |
| Token 只放 Cookie | 瀏覽器會自動傳送 Cookie,沒有第二個明確通道 | Hidden Field/Header 加 Session 綁定,或使用 Signed Double-Submit |
| 只設定 SameSite | 跨站業務、同 Site 子網域、舊 Client 或錯誤 GET 仍可能有風險 | SameSite 加 Token、Origin 或 Fetch Metadata 的縱深組合 |
| 只依賴 CORS | Simple Request 可能送達,攻擊者不必讀取回應 | 在 Server 端驗證請求意圖,CORS 僅限制受信任讀取來源 |
| 只修畫面中的一個 Form | 相同端點、API、方法與其他角色路徑可能未覆蓋 | 在框架/路由層預設保護所有狀態變更端點 |
從盤點到上線:CSRF 修復流程怎麼安排?
第一步建立狀態變更端點清冊,包含方法、認證方式、Cookie、角色、資料敏感度、呼叫端與跨站依賴;先消除會改變狀態的 GET,並確認所有方法覆寫、舊版 API 與背景流程。第二步選擇框架內建防護,依架構採 Synchronizer Token 或 Signed Double-Submit Cookie。
第三步設定 Cookie Scope 與 SameSite,加入 Origin/Referer 或 Fetch Metadata 縱深政策,並為 SSO、OAuth、Webhook、第三方嵌入與舊 Client 建立可審核例外。第四步對高風險操作加入重新驗證與交易確認,確保拒絕發生在資料修改、外部通知或工作佇列建立之前。
上線可先以觀測模式記錄 Token、Origin 與 Fetch Metadata 不符合的請求,確認合法流量後逐步阻擋。CI 應加入 Middleware 覆蓋、Endpoint Contract 與 Browser Integration Test,避免新路由在重構後脫離防護。
- 建立狀態變更端點、認證方式與跨站依賴清冊
- 移除狀態變更 GET,統一方法與 Content-Type 政策
- 啟用框架內建 CSRF 防護,Token 驗證預設套用所有非安全方法
- 明確設定 Session Cookie 的 SameSite、Secure、HttpOnly、Domain、Path 與生命週期
- 導入 Origin/Referer、Fetch Metadata 與高風險交易確認
- 以 Report-only、分階段阻擋、稽核日誌與回歸測試安全上線
修復後怎麼複驗?正向、負向與回歸條件都要通過
複驗不只確認原始攻擊請求回傳 403。先以正常流程取得新 Session 與 Token,確認合法操作成功;再驗證 Token 缺失、不符、過期、屬於其他 Session、重複使用或來自跨站脈絡時,伺服器會在任何副作用前拒絕。
接著以真實瀏覽器測試 SameSite、Origin、Referer、Sec-Fetch-Site、Redirect、頂層導覽、Form Content-Type 與 CORS Preflight。多分頁、瀏覽器返回、Session 續期、登入/登出、OAuth Callback、Mobile WebView 與第三方整合也要做回歸,避免安全控制造成大量誤拒。
最後檢查所有同根因路由,而不是只重測報告中的一個 URL。若修復採 Framework Middleware,應以自動化測試證明所有狀態變更端點都經過相同政策,並針對明確例外驗證補償控制。
| 複驗項目 | 預期結果 | 必要證據 |
|---|---|---|
| 合法同站請求 | 目前 Session 與有效 Token 可完成操作 | 正常流程、Request Header、操作前後狀態 |
| Token 缺失或錯誤 | 在業務邏輯與副作用前一致拒絕 | 狀態未改變、無外部通知或工作建立 |
| 跨 Session/跨使用者 Token | 即使 Token 格式正確也拒絕 | 兩個專用帳號與獨立 Session 的交叉測試 |
| 跨站瀏覽器請求 | Cookie/SameSite 與 Server Policy 按設計拒絕 | Origin、Referer、Sec-Fetch-*、Network 與 Server Log |
| 方法與 Content-Type 變化 | GET 無副作用,未允許格式與方法不可繞過 | Route Matrix、Form/JSON/Method Override 測試 |
| 合法例外與整合 | OAuth、SSO、Webhook、Mobile 與嵌入流程正常且有專屬控制 | 協定驗證、Allowlist、簽章或一次性狀態證據 |
| 同根因範圍 | 所有角色、版本、GraphQL Mutation 與管理端點均受保護 | 自動化覆蓋清單與版本化複驗結果 |
如果 CSRF 已被利用,事件處理不能只補 Token
先確認受影響端點、時間範圍、角色、Session 與實際狀態變更,暫停高風險功能或加上臨時 Origin/Token Gate。依影響撤銷 Session、API Key、OAuth Grant、Webhook 與變更後的憑證,還原未授權設定、權限、交易或資料,並保留 Audit Log、Proxy Log、應用程式事件與版本資訊。
因 CSRF 請求通常看起來像由受害者本人瀏覽器送出,來源 IP 與 User-Agent 可能不具直接辨識力。調查要結合異常 Origin/Referer、Sec-Fetch-Site、操作時間、導覽序列、Token 驗證事件與狀態變更後的後續行為;若系統過去未記錄這些欄位,也應把可稽核性納入修復。
完成遏止後,要找出控制為何未覆蓋:路由例外、舊版 API、狀態變更 GET、SameSite 需求、代理設定、前端 Token 傳遞或 Framework 升級。再以同根因搜尋、單元測試、Browser Test 與部署監控確認問題不會在下一次新增端點時復發。
團隊可以直接使用的 CSRF 檢查清單
CSRF 防護最容易失敗在『大多數頁面有做,但少數高價值端點漏掉』。把下列項目納入 Architecture Review、Pull Request、API Contract、Release Gate 與定期弱點檢測,會比在事件後逐頁補 Token 更可靠。
- 所有狀態變更端點都使用非安全 HTTP 方法,GET/HEAD/OPTIONS 不產生副作用
- Cookie 型 Session 的所有狀態變更請求都經 Framework CSRF Middleware 或等效伺服器端驗證
- Token 不可預測、與目前 Session 綁定、不放 URL、不記錄明文,缺失或不符即在副作用前拒絕
- Stateless 架構使用 Signed Double-Submit Cookie,不使用可被 Cookie Injection 繞過的簡化版本
- Session Cookie 明確設定 SameSite、Secure、HttpOnly、最小 Domain/Path 與合理有效期
- Origin/Referer、Fetch Metadata 與 CORS 使用精確 Allowlist,可信 Proxy 與合法例外有文件
- 登入、OAuth、OIDC、SSO、Webhook、Iframe 與 Mobile Client 使用各自適用的協定控制
- 高風險交易要求重新驗證或與交易內容綁定的明確確認
- CI 具備合法、Token 缺失、錯誤、跨 Session、跨站與相鄰端點的 Browser Regression Test
- Audit Log 能記錄防護決策與狀態變更,但不保存完整 Session 或 Anti-CSRF Token
CSRF 治理的重點:讓每次狀態變更都有可驗證的意圖
CSRF 的本質不是 Cookie 本身不安全,而是網站把瀏覽器自動附帶的登入狀態誤當成使用者對這一次操作的明確意圖。有效防護要在伺服器端建立外部網站無法偽造的請求條件,並以 HTTP 方法、Cookie 政策、來源脈絡與高風險確認形成分層控制。
對多數 Cookie 型 Web 應用,最穩健的起點是框架內建 CSRF 防護、Synchronizer Token 或 Signed Double-Submit Cookie,再加上 SameSite、Origin/Referer、Fetch Metadata 與安全 CORS。OAuth 與 OIDC 則依 RFC 的 state、nonce、PKCE 與 Issuer 驗證處理,不與一般表單 Token 混用。
最後,修復必須能被複驗與持續維護:端點清冊、Middleware 預設、例外審核、Browser Test、稽核日誌與弱點修復 SLA 缺一不可。當新功能每次上線都能回答『身分如何驗證、意圖如何驗證、失敗如何記錄』,CSRF 才不會在下一條路由重新出現。


