CSRF防范
什么是CSER
以下是基于 CSRF 攻擊過程的 順序圖 及詳細解釋,結合多個技術文檔中的攻擊流程:
CSRF 攻擊順序圖
攻擊過程分步解讀
- 用戶登錄受信任網站A
? 用戶通過瀏覽器正常登錄網站A(例如銀行網站),服務器生成會話 Cookie 并返回給瀏覽器。
? 關鍵點:此時瀏覽器會存儲該 Cookie,后續所有對網站A的請求都會自動攜帶此 Cookie(如 Set-Cookie: session_id=abc123
)。
- 用戶訪問惡意網站B
? 攻擊者通過釣魚鏈接、誘導廣告等方式,誘使用戶訪問惡意網站B。
? 攻擊代碼示例(來自網頁3):
<!-- 惡意網站B的頁面 -->
<img src="http://網站A/轉賬?to=攻擊者&amount=1000">
<!-- 或通過JS自動提交表單 -->
<script>document.write('<form action="http://網站A/改密碼" method="POST">');document.write('<input type="hidden" name="new_password" value="hacker123">');document.write('</form>');document.forms[0].submit();
</script>
- 瀏覽器自動發送偽造請求
? 惡意網站B的代碼會觸發瀏覽器向網站A發送請求(如轉賬、修改密碼),瀏覽器會自動攜帶用戶已登錄的 Cookie。
? 服務器視角:網站A收到請求后,驗證 Cookie 合法,誤認為是用戶主動操作,執行惡意請求。
- 攻擊完成
? 用戶未感知到任何異常(如無頁面跳轉),但敏感操作已被執行(如資金轉移、密碼重置)。
攻擊成功的關鍵條件
- 用戶已登錄受信任網站A:攻擊依賴用戶的活躍會話。
- 網站A未啟用CSRF防護:如未校驗 Token、Referer 或二次驗證。
- 請求參數可預測:例如通過 GET 請求執行敏感操作(如
GET /轉賬?to=攻擊者
)。
防御措施(引用自網頁5、網頁6)
? Token 驗證:在表單或請求頭中嵌入隨機 Token,服務端校驗 Token 合法性。
? SameSite Cookie:設置 Cookie 的 SameSite=Strict/Lax
屬性,限制跨域請求攜帶 Cookie。
? Referer 檢查:驗證請求來源是否為可信域名。
通過順序圖可以看出,CSRF 攻擊的 核心邏輯是濫用瀏覽器的 Cookie 自動攜帶機制,而防御的關鍵在于 阻斷攻擊者偽造請求的能力。
Security的CSRF簡介
根據 Spring Security 的官方設計理念及社區實踐(綜合多個技術文檔和博客),其 CSRF 防護機制的核心邏輯如下:
一、Spring Security 的 CSRF 防護機制
- 默認啟用的防護
? 自動攔截:Spring Security 從 4.0 版本起默認啟用 CSRF 保護,通過CsrfFilter
攔截所有非安全 HTTP 方法(如 POST、PUT、DELETE)的請求。
? Token 驗證流程:
-
生成 Token:用戶首次訪問時,服務端生成唯一的
CSRF Token
并存儲于HttpSession
或Cookie
中(默認使用HttpSessionCsrfTokenRepository
)。 -
客戶端攜帶 Token:在表單或 AJAX 請求中必須包含該 Token(例如通過隱藏字段或請求頭)。
-
服務端校驗:請求到達時,
CsrfFilter
會對比客戶端提交的 Token 與服務端存儲的 Token,若不一致則拒絕請求(返回 403 錯誤)。 -
核心組件
?CsrfToken
接口:定義 Token 的生成規則,包含token
值、參數名(_csrf
)和請求頭名(X-CSRF-TOKEN
)。
? CsrfTokenRepository
:
? HttpSessionCsrfTokenRepository
(默認):Token 存儲于 Session。
? CookieCsrfTokenRepository
:Token 存儲于 Cookie,適用于前后端分離場景。
? 配置示例:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());}
}
- 前端集成方式
? 表單頁面:通過模板引擎(如 Thymeleaf)自動注入 Token:
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
? AJAX 請求:從 Cookie 或 Meta 標簽獲取 Token 并添加到請求頭:
// 從 Cookie 獲取 Token(需配置 CookieCsrfTokenRepository)
const token = document.cookie.match(/XSRF-TOKEN=([^;]+)/)[1];
fetch('/api/data', {method: 'POST',headers: { 'X-XSRF-TOKEN': token }
});
- 擴展防護策略
? SameSite Cookie 屬性:通過設置 Cookie 的SameSite=Strict/Lax
,限制跨域請求攜帶 Cookie(需瀏覽器支持)。
? 二次驗證:對敏感操作(如轉賬)疊加驗證碼或密碼確認。
二、未啟用 CSRF 防護的危害場景
如果未啟用 CSRF 防護,攻擊者可利用以下漏洞發起攻擊:
-
偽造用戶操作:
? 自動觸發惡意請求:通過惡意頁面嵌入<img>
或自動提交表單,誘導已登錄用戶觸發轉賬、修改密碼等操作。? 示例攻擊代碼:
<img src="http://bank.com/transfer?to=attacker&amount=10000">
-
數據篡改與泄露:
? 賬戶信息泄露:攻擊者篡改用戶郵箱或手機號,后續可通過“忘記密碼”功能接管賬戶。? 業務邏輯繞過:例如自動關注陌生賬號、刪除用戶數據等。
-
企業級風險:
? 供應鏈攻擊:通過管理員賬戶的 CSRF 漏洞植入后門,導致企業系統被滲透。? 合規風險:因數據泄露違反 GDPR 等法規,面臨高額罰款。
三、官方文檔的補充說明
雖然未直接引用 spring.io
官網,但以上機制與官方文檔一致(可通過 Spring Security 官方文檔 驗證):
? 防護原理:基于 Token 的同步器模式(Synchronizer Token Pattern)。
? 禁用場景:僅推薦在純 API 服務(無瀏覽器交互)時通過 http.csrf().disable()
關閉防護。
總結
Spring Security 通過 CSRF Token 的生成與驗證機制 有效防御跨站請求偽造攻擊。若未啟用防護,攻擊者可利用用戶已登錄的會話劫持敏感操作,導致數據泄露、資金損失等嚴重后果。開發者應結合業務場景選擇 Token 存儲方式(Session/Cookie),并確保前端正確集成 Token。
CSRF防范的必要參數
以下是標準的CSRF防護參數及其生成、使用和失效規則的總結表格,結合多個技術文檔和實踐案例:
參數名稱 | 生成者 | 生成時機 | 使用時機 | 失效條件 |
---|---|---|---|---|
CSRF Token | 服務端 | 用戶首次訪問受保護頁面時生成 | 在提交表單或發起狀態變更請求(如POST/PUT/DELETE)時攜帶 | 會話過期失效、單次使用后失效(單次有效性)、超出時間窗口(如5-10分鐘) |
SameSite Cookie | 服務端 | 用戶首次登錄時生成 | 瀏覽器自動管理,用于限制跨域請求攜帶Cookie | Cookie過期失效、瀏覽器關閉(根據SameSite策略) |
二次驗證參數 | 服務端或第三方系統 | 用戶觸發敏感操作(如轉賬)時生成 | 執行關鍵操作前需二次驗證(如短信驗證碼) | 驗證碼使用后失效、超時失效(如5分鐘) |
詳細說明
- CSRF Token
? 生成者:服務端通過CsrfTokenRepository
生成,例如HttpSessionCsrfTokenRepository
(存儲在會話中)或CookieCsrfTokenRepository
(存儲在Cookie)。
? 生成時機:用戶首次訪問需要CSRF防護的頁面時(如登錄頁、表單頁),或每次頁面加載時動態生成新Token。
? 使用時機:必須嵌入到所有非安全方法(POST/PUT/DELETE)的請求中,例如:
? 表單:通過隱藏字段<input type="hidden" name="_csrf" value="token">
。
? AJAX:通過請求頭X-CSRF-TOKEN
或X-XSRF-TOKEN
傳遞。
? 失效條件:
? 會話過期:若用戶會話終止,Token隨之失效。
? 單次有效性:部分系統設計Token僅限單次使用(如支付場景)。
? 時間窗口:設置Token有效期(如10分鐘),超時自動失效。
- SameSite Cookie
? 生成者:服務端在用戶登錄時生成會話Cookie,并設置SameSite
屬性。
? 使用規則:
? SameSite=Strict
:禁止跨域請求攜帶Cookie(適用于高敏感操作)。
? SameSite=Lax
:允許安全跨域請求(如導航鏈接的GET請求)。
? 失效條件:遵循Cookie的過期策略(如會話Cookie在瀏覽器關閉后失效)。
- 二次驗證參數
? 生成者:服務端在用戶觸發敏感操作時生成(如短信驗證碼、動態口令)。
? 使用時機:關鍵操作(如修改密碼、大額轉賬)前需用戶二次確認。
? 失效條件:驗證碼使用后立即失效,或設計為短時間有效(如5分鐘)。
引用來源
? CSRF Token生成與驗證邏輯:
? SameSite Cookie機制:
? 二次驗證參數設計:
通過上述參數組合(如Token+SameSite+二次驗證),可構建多層防御體系,有效阻斷CSRF攻擊。
Security是怎么防范的
Spring Security 通過 CSRF Token 驗證機制 和 防御策略組合 來避免 CSRF 攻擊,以下是其核心實現邏輯及關鍵步驟:
一、CSRF Token 驗證機制
- 生成與存儲 Token
? Token 生成:當用戶首次訪問受保護頁面時,Spring Security 會自動生成一個唯一的隨機 CSRF Token。
? 默認使用 HttpSessionCsrfTokenRepository
,將 Token 存儲在用戶會話(HttpSession)中。
? 若為前后端分離架構,可使用 CookieCsrfTokenRepository
將 Token 存儲于 Cookie 中,并允許前端通過 JavaScript 讀取。
? Token 結構:包含三個核心屬性:token
(隨機值)、parameterName
(參數名,默認為 _csrf
)、headerName
(請求頭名,默認為 X-CSRF-TOKEN
)。
- 客戶端攜帶 Token
? 表單提交:
在 HTML 表單中通過隱藏字段嵌入 Token。例如使用 Thymeleaf 模板引擎自動注入:
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
? AJAX 請求:
通過請求頭傳遞 Token。前端需從 Cookie 或 Meta 標簽中獲取 Token,并添加到請求頭中:
// 從 Cookie 獲取 Token(需配置 CookieCsrfTokenRepository)
const token = document.cookie.match(/XSRF-TOKEN=([^;]+)/)[1];
fetch('/api/data', {method: 'POST',headers: { 'X-XSRF-TOKEN': token }
});
- 服務端驗證 Token
? 攔截與校驗:
CsrfFilter
會攔截所有非安全 HTTP 方法(如 POST、PUT、DELETE),從請求中提取 Token,并與服務端存儲的 Token 對比。
? 若 Token 匹配,請求通過。
? 若 Token 缺失或不匹配,返回 403 Forbidden 錯誤。
二、防御策略擴展
- SameSite Cookie 屬性
? 通過設置 Cookie 的SameSite
屬性限制跨域請求攜帶 Cookie:
? SameSite=Strict
:僅允許同站點請求攜帶 Cookie。
? SameSite=Lax
:允許部分安全跨站點請求(如導航鏈接)。
? 配置示例:
@Bean
public CsrfTokenRepository csrfTokenRepository() {CookieCsrfTokenRepository repository = new CookieCsrfTokenRepository();repository.setSameSite("Lax");return repository;
}
- 雙重驗證(Double Submit Cookie)
? 服務端將 Token 同時存儲在 Cookie 和表單/請求頭中,驗證時需兩者一致。
? 適用于分布式系統,避免依賴會話存儲。
- 安全方法限制
? 默認僅對 POST、PUT、DELETE、PATCH 等狀態修改類請求啟用 CSRF 驗證,而 GET、HEAD、OPTIONS 等安全方法無需驗證。
三、配置與最佳實踐
- 啟用與禁用
? 默認啟用:Spring Security 4.0+ 默認開啟 CSRF 防護。
? 手動關閉(不推薦):
http.csrf().disable();
- 前后端分離配置
? 后端配置 Cookie 存儲 Token:
http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
? 前端從 Cookie 讀取 Token 并添加到請求頭。
- 最佳實踐
? 始終啟用 CSRF 防護:除非服務為純 API 且無瀏覽器交互。
? 結合 HTTPS:防止 Token 被中間人竊取。
? 定期更新依賴:修復已知漏洞。
四、總結
Spring Security 通過 CSRF Token 的生成、傳遞與驗證機制,結合 SameSite Cookie 和 雙重驗證 等策略,有效阻斷攻擊者偽造請求的能力。其設計兼顧靈活性與安全性,開發者需根據架構(如傳統 MVC 或前后端分離)選擇合適的 Token 存儲方式,并遵循最佳實踐以確保全面防護。