- CSRF 利用了伺服器信任用戶會話而不驗證請求真實來源這一事實。
- 有效的緩解措施:同步令牌、避免使用 GET 進行狀態變更以及驗證 Origin/Referer。
- ASP.NET Core 原生支援:IAnitiforgery、篩選驗證和自訂標頭。
- SameSite Cookies、WAF 和良好的用戶實踐可顯著降低風險。

如果你從事 Web 開發或安全工作,就應該了解跨站請求偽造 (CSRF) 是什麼。 CSRF是一種隱蔽攻擊,它利用使用者現有的會話,強迫使用者的瀏覽器在未經其同意的情況下執行操作。
這種現象並非新鮮事,但仍值得關注,因為瀏覽器會自動將 cookie 或標頭等憑證附加到某些請求中。即使請求源自惡意頁面、iframe 或偽裝的鏈接,伺服器也會「信任」使用者並處理該請求。
什麼是 CSRF?為什麼它至今仍在造成問題?
簡而言之,CSRF 攻擊是指網站 A 誘騙已認證使用者的瀏覽器向網站 B 發送請求,而該使用者已登入網站 B,從而使網站 B 將該操作視為有效操作。關鍵在於網站對使用者的信任,而不是使用者對網站的信任。
與利用使用者對頁面的信任在頁面上下文中註入和執行程式碼的 XSS 不同,CSRF 濫用了伺服器接受任何附帶有效憑證(例如會話 cookie)的請求此特性。這兩個問題可能會疊加,加劇其危害。
一些歷史背景與法醫上的難題
此類漏洞早在 20 世紀 90 年代末就已為人所知,CSRF/XSRF 一詞由 Peter Watkins 於 2001 年提出。攻擊路徑通常指向使用者的合法 IP 位址,這使得責任認定變得複雜,需要進行專門的取證分析。
多年來,雖然鮮有詳細記錄的公開攻擊案例,但該問題反覆出現,並因其影響和發生頻率多次出現在OWASP Top 10中。
攻擊原理(條件和流程)
CSRF攻擊成功需要滿足幾個條件:使用者在目標應用程式中保持活躍會話;瀏覽器自動將cookie、基本憑證/摘要或身分驗證上下文附加到請求中;以及應用程式在沒有額外驗證機制的情況下接受狀態變更。
攻擊者利用社交工程手段(例如電子郵件、聊天或誘人的網站)誘騙受害者加載某個頁面,該頁面會觸發對存在漏洞的網站的惡意請求。使用者可能只需造訪該頁面即可:使用者自行提交的表單、嵌入的圖片或 iframe 就足以啟動該要求。
典型向量:GET、POST 甚至“儲存”
遺憾的是,有些應用程式會使用 GET 請求來改變狀態。在這種情況下,第三方頁面上一個簡單的`<img src="Dangerous-URL" />` 標籤會在載入圖片時執行相應的操作。因此,作為一項基本原則,GET 請求不應該修改資源。
使用 POST 請求時,典型的攻擊手段是偽裝成 HTML 表單的請求,該表單透過 JavaScript 自動提交,或使用者誤以為是其他內容而提交。瀏覽器會將合法網域的會話 cookie 附加到該表單上,伺服器隨後處理變更(例如轉帳、刪除記錄、變更電子郵件地址等)。
有時,攻擊程式碼可以直接插入受害者的網站(由於存在其他漏洞),嵌入到 IMG 標籤或 iframe 中。這種「儲存型 CSRF」攻擊會降低攻擊者的懷疑,因為互動似乎仍然發生在受信任的域內。
對帳戶和系統的實際影響
其後果包括未經授權的金融交易、配置變更、權限重新分配或資料刪除。如果受害者擁有管理員角色,攻擊者可以篡改應用程式邏輯或啟用影響更多使用者的後門。
即使是看似微不足道的操作,例如更改個人資料郵箱地址,也可能導致帳戶無法找回或助長後續的詐欺行為。主要問題在於,所有這些操作都是「以使用者名義」進行的,而且使用者往往毫不知情。
具體(且非常常見)的例子
想像一下,有一個管理面板,允許你使用類似 /users/delete/63 的 URL 發送 GET 請求來刪除使用者。如果經過驗證的管理員造訪包含<img src="https://admin-site/users/delete/63" />的第三方頁面,瀏覽器將發出請求,帳戶將被刪除。
另一個經典案例:網路銀行。如果可以透過 GET 請求(例如/transfer?amount=500&account=XXXX)來操控轉賬,那麼一個看似無害的連結就足以讓已登入使用者觸發向攻擊者帳戶的轉帳。
POST 要求的流程類似:當頁面載入時,會自動提交一個包含「金額」和「帳戶」欄位的隱藏表單。合法網域的銀行會話 cookie和伺服器會處理轉帳。
瀏覽器和協議因素
使用 HTTPS 本身並不能完全阻止攻擊:惡意網站很容易誘騙瀏覽器發出安全性請求。基本驗證和摘要式驗證也存在漏洞:使用者通過驗證後,瀏覽器會自動重新傳送憑證,直到會話結束。
SameSite Cookie 策略有所幫助,但其中也存在一些細微差別。當 SameSite=Strict 時,瀏覽器不會在跨網站上下文中傳送 Cookie,從而有效消除大部分 CSRF 攻擊。然而,當 SameSite=None(且設定為 Secure)時,Cookie 會在網站之間傳輸,增加攻擊面。
使用者良好實踐
雖然問題主要出在應用程式上,但養成一些習慣可以降低風險。例如,用完後登出登入、定期刪除 cookie 以及避免使用「保持登入狀態」選項,都能最大限度地減少風險。
將任務分開也很有幫助:使用一個瀏覽器處理敏感任務,另一個瀏覽器進行一般瀏覽,或使用隱身模式避免保存憑證。阻止腳本的擴充功能會限制自動化(儘管它們並非完美的解決方案)。
應用防禦措施
第一條黃金法則:不要使用 GET 要求更改狀態。將 POST/PUT/DELETE 請求保留給修改資源的操作,可以減少諸如圖片或偽裝連結之類的簡單攻擊向量。
目前最廣泛使用的 CSRF 緩解方法是同步令牌模式:伺服器頒發一個與使用者身分關聯的唯一隨機令牌,客戶端在下一個狀態變更請求中傳回該令牌。如果令牌與使用者身分和 cookie 不匹配,則拒絕該要求。
另一個有用的驗證層是來源驗證:檢查是否有 Origin/Referer 標頭。如果請求並非來自預期網域,則處理將被封鎖。注意:某些用戶端會因為隱私而隱藏 Referer,因此必須謹慎實現此驗證。
WAF(Web應用防火牆)也能提供協助。企業級解決方案,例如F5 BIG-IP ASM或託管平台中的整合保護服務,會新增規則來識別並阻止可疑模式,防止它們到達您的應用程式。
令牌的限制和常見錯誤
如果正確實施,令牌可以提供保護。如果應用程式在缺少令牌時繞過驗證過程,攻擊者只需發送一個空令牌即可。同樣危險的是使用可重複使用的令牌池而不是為每個使用者分配單獨的令牌:竊取一個有效的令牌就足以冒充其他使用者的會話。
將令牌儲存在可透過 JavaScript 存取的 cookie 中也是一個糟糕的做法,除非採取安全措施:XSS 攻擊者可以讀取並重複使用該 cookie。提高安全性的方法是將會話 cookie 和令牌合併到一個單獨的表單或標頭中,並對兩者進行驗證。
與SPA、代幣和XSS的關係
在採用基於令牌的身份驗證(例如 JWT)的應用程式中,將令牌作為 Bearer 物件而不是 cookie傳送到 Authorization 標頭中,可以降低 CSRF 攻擊的風險,因為瀏覽器不會自動附加令牌。即便如此,如果存在 XSS 漏洞,攻擊者仍然可以從本機儲存中竊取令牌。
因此,除了 CSRF 之外,還需要保護伺服器的輸出,避免渲染未轉義的 HTML,並實作內容安全性原則 (CSP)。如果雙方都存在漏洞,CSRF 和 XSS 會相互加劇。
ASP.NET Core 中的 CSRF:開發人員必備知識
ASP.NET Core 內建了多種安全緩解措施。使用 `method="post"` 的表單可以自動在 Razor 視圖中包含防偽令牌(TagHelpers 和 BeginForm 等輔助方法預設會插入這些令牌)。您也可以明確地註入這些令牌,並使用過濾器在伺服器端進行驗證。
驗證功能可透過 `ValidateAntiForgeryToken` 或更便利的 `AutoValidateAntiForgeryToken` 等屬性啟用。後者會在不安全的方法(POST/PUT/DELETE)中要求提供令牌,並在 GET/HEAD/OPTIONS/TRACE 中避免要求提供令牌。如果需要例外處理,`IgnoreAntiForgeryToken` 屬性可以覆寫特定操作的令牌要求。
對於 API 和 SPA,IAnitiforgery 服務可讓您產生和儲存令牌,並透過自訂標頭(例如X-XSRF-TOKEN)接收這些令牌。像 Angular 這樣的框架通常會讀取「XSRF-TOKEN」 cookie 並將其值傳送到該標頭中,伺服器必須驗證該標頭。
最小 API 可以明確驗證令牌(透過中間件或端點過濾器),建議在身份驗證和授權之後執行防偽中間件,避免在不適當的情況下讀取請求正文。
微調:AntiforgeryOptions 允許自訂隱藏欄位名稱、預期標頭以及是否發出 X-Frame-Options 標頭(預設為 SAMEORIGIN)。在開發環境中,有時會放寬 cookie 的 Secure 標誌;但在實際環境中,建議強制使用 HTTPS。
請注意,使用同步令牌模式時,開啟多個標籤頁並瀏覽不同流程可能會導致先前的令牌失效:通常只有最近造訪的頁面才擁有有效的令牌。如果您的使用者體驗依賴多個並發標籤頁,請考慮其他方案。
另一個需要注意的地方是同一網域或子網域下的共享主機。共用 *.domain.com 位址可能導致一個應用程式幹擾另一個應用程式的 Cookie,因此使用不同的網域隔離應用程式可以提高隔離性。
最後,Windows身份驗證(NTLM/Kerberos)並不能讓你免受攻擊:瀏覽器會隱式地發送身份驗證上下文,如果沒有令牌或來源檢查,仍然可能發生 CSRF 攻擊。
CDN、交叉加載以及為何需要謹慎
網站向第三方(例如 YouTube 影片、CDN 庫等)請求內容是很常見的。如果這種請求交換沒有得到妥善控制,攻擊者可以利用站點間路由漏洞,強制瀏覽器發送帶有附加憑證的請求。
除了嚴格的 cookie 政策外,還要審查 iframe 和嵌入式物件的使用情況,在拉取 CDN 時套用 SRI,並使用定義完善的 CSP 和 CORS限制接受的來源。
團隊的額外良好實踐
它針對修改狀態的表單和端點變更建立安全審查機制。它會自動執行測試,驗證令牌是否存在以及驗證是否正確,並將任何重新引入帶有副作用的 GET 請求的回歸標記為「阻塞」。
它實現了日誌記錄功能,用於檢測罕見模式(例如,沒有令牌或具有意外來源標頭的表單提交),並支援 WAF,以減少雜訊並阻止已知的漏洞利用簽章。
重要提示:僅靠 CSRF 無法解決的問題
防偽令牌並不能解決腳本注入問題,也不能取代授權控制。它首先驗證使用者是否有權執行操作,然後驗證令牌,並在必要時檢查來源/引用頁。縱深防禦至關重要。
別忘了向產品團隊解釋「為什麼」:避免發送會改變狀態的 GET 請求或在某些操作中要求額外的令牌,這不是技術上的異想天開,而是為了直接保護業務免受欺詐和操縱。
CSRF攻擊的危險之處在於其隱藏性:請求源自受害者的瀏覽器,使用其憑證,看起來合法無誤。透過結合完善的令牌機制、來源驗證、適當的Cookie策略、負責任的REST設計,以及在適當情況下使用Web應用防火牆(WAF)保護,可以在不影響使用者體驗的前提下,大幅縮短攻擊視窗。
對字節世界和一般技術充滿熱情的作家。我喜歡透過寫作分享我的知識,這就是我在這個部落格中要做的,向您展示有關小工具、軟體、硬體、技術趨勢等的所有最有趣的事情。我的目標是幫助您以簡單有趣的方式暢遊數位世界。