csrf防范
什么是cser
以下是基于 csrf 攻击过程的 顺序图 及详细解释,结合多个技术文档中的攻击流程:
csrf 攻击顺序图
用户 浏览器 受信任网站a 恶意网站b 正常操作阶段 访问网站a并登录 发送登录请求 返回登录成功的cookie 存储cookie(保持会话) 攻击触发阶段 访问恶意网站b(如点击链接) 请求页面 返回包含恶意代码的页面(如自动提交表单的js) 伪造请求执行阶段 自动携带cookie发送恶意请求(如转账) 验证cookie合法,执行请求 用户未感知到操作已被篡改 用户 浏览器 受信任网站a 恶意网站b
攻击过程分步解读
用户登录受信任网站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 { @override protected 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 存储方式,并遵循最佳实践以确保全面防护。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论