干安全和运维这么多年,处理用户账号"自己动"的诡异事件,CSRF(跨站请求伪造)绝对是常客。今天不扯教科书上的同源策略定义,直接复盘一线处置CSRF攻击的真实流程。
开篇立规矩:处置CSRF的"四不要"与总原则
接到用户反馈账号出现异常操作,先把手头工作停一下,记住四个绝对不要:
- 不要只加验证码了事:加验证码能防,但必须先查清楚请求到底是从哪个恶意站点发过来的,找到源头才能拔根。
- 不要忽略用户侧受害情况:账号被利用做了什么?转了钱?发了广告?还是改了密码?受害范围必须先摸清。
- 不要没确认请求来源就封IP:CSRF的请求是受害用户自己的浏览器发出的,IP是用户的真实IP,封IP只会误伤正常用户,根本防不住攻击者。
- 不要只修一个接口:全站表单和写操作接口都要查,今天堵了发帖接口,明天他就能去改你的收货地址。
处置总原则就一句话:先确认异常操作的请求来源,再阻断利用链;先查用户受害范围,再全站修复。
正确开局:先定性,再收敛
第一件事,定性。用户账号异常,到底是用户自己手滑误操作、是被CSRF借刀杀人、还是账号密码泄露被盗了?
先看操作时间线,对比异常操作前后的登录记录。排查逻辑按这三层往下收敛:请求来源 → 操作类型 → 影响范围。
现场必须明确区分三种情况:
- 确认CSRF:实锤请求来自受害用户的浏览器,但Referer/Origin指向恶意网站,且非用户本人意图。
- 疑似CSRF:日志里Referer为空,或者Origin不对劲,需要抓包进一步验证。
- 其他:登录IP异地、密码被改,这是账号被盗,走盗号处置流程;操作逻辑正常,可能是用户误操作。
排查主链路:可复制的命令与操作
别干瞪眼,按下面这套动作排查,每一步看到什么现象,对应什么问题,心里要有数。
1. 查异常操作的访问日志(找跨站来源)
bash
# 查Nginx日志,找POST请求且Referer不是本站域名的记录
awk -F'"' '{print $2, $4, $6}' access.log | grep "POST" | grep -v "yourdomain.com" | head -n 20
现象与问题 :看到大量POST请求的Referer是 http://evil.com 或者 null。说明请求是从外部恶意页面发起的。
2. 分析请求来源(看Origin和Referer)
抓包看HTTP头。如果是表单提交,看 Referer;如果是AJAX/Fetch,看 Origin。如果 Origin 是 null 或者跨站域名,且接口没做校验,实锤CSRF。
3. 查用户会话状态(看登录态是否被利用)
bash
# 查Redis或Session存储,看异常操作时的Session是否有效
redis-cli GET "session:受害者的SessionID"
现象与问题:Session存在且未过期。说明攻击者正是利用了用户未退出的登录态来伪造请求。
4. 查受影响账号和操作记录(摸底损失)
sql
-- 查最近24小时内,敏感操作的记录
SELECT user_id, action, ip, create_time
FROM operation_log
WHERE create_time > DATE_SUB(NOW(), INTERVAL 24 HOUR)
AND action IN ('transfer', 'change_password', 'post_article', 'update_config');
现象与问题:查出具体哪些用户被改了密码、转了账或发了垃圾帖,为后续回滚和通知提供依据。
5. 查是否有批量账号受影响(看蠕虫特征)
bash
# 统计同一个恶意Referer对应的不同受害者IP
grep "evil.com" access.log | awk '{print $1}' | sort | uniq -c | sort -nr | head -n 10
现象与问题:同一个恶意Referer对应了几百个不同的用户IP。说明攻击页面被大量用户点击,正在批量利用。
6. 分析触发入口(找裸奔接口)
bash
# 全局搜索代码里没加CSRF防护注解的Controller方法
grep -rn "@PostMapping\|@PutMapping\|@DeleteMapping" src/main/java/ | grep -v "CsrfToken\|RequiresCsrf"
现象与问题:扫出来一堆没做CSRF校验的写操作接口。这些就是被利用的入口。
7. 查同源策略相关配置(看Cookie裸奔没)
检查响应头里的 Set-Cookie,看有没有带 SameSite 属性。如果没有,或者设置的是 None,Cookie就会在跨站请求中被带上,给CSRF提供弹药。
高频现场逐个拆
1. 链接触发的请求(图片/链接直接触发)
- 现象:用户反馈浏览某个论坛时,自己的账号自动关注了一堆陌生人。
- 排查 :抓包发现,恶意页面里嵌了
<img src="https://yoursite.com/api/follow?userId=123">。浏览器加载图片时自动带了Cookie发请求。 - 处理:关注接口改为POST,并在后端校验CSRF Token。GET请求严禁做状态变更。
2. 表单跨站提交(伪造表单)
- 现象:用户没发帖,但社区里出现了他的赌博广告。
- 排查 :看Nginx日志,POST请求的
Referer是恶意网站。攻击者在自己的站写了个隐藏表单,用JS自动提交。 - 处理:发帖接口加上CSRF Token校验,拦截跨站表单提交。
3. 接口型伪造(无校验的接口被跨站调用)
- 现象:用户的收货地址被改成了攻击者的地址。
- 排查 :前端用AJAX调接口,没带自定义Header,浏览器自动带了Cookie。后端没校验
Origin和 Token。 - 处理 :后端拦截器统一校验
Origin/Referer,并强制要求请求头带自定义Token。
4. 登录态下利用(用户未退出就中招)
- 现象:用户白天登录了后台,晚上回家打开电脑发现数据被删了。
- 排查:Session没过期,Cookie一直有效。用户白天浏览了带恶意链接的邮件。
- 处理:缩短Session有效期,敏感操作必须要求重新输入密码或短信验证码。
5. CSRF配合其他漏洞(组合利用)
- 现象:CSRF Token被绕过了。
- 排查:发现系统同时存在XSS漏洞,攻击者先用XSS偷到了CSRF Token,再发起CSRF攻击;或者Token没跟Session绑定,是全局固定的。
- 处理:修复XSS,确保CSRF Token是每次会话随机生成且与Session绑定的。
6. 批量账号异常操作(类似蠕虫传播)
- 现象:短时间内几千个用户自动转发了同一条恶意微博。
- 排查:转发接口没防CSRF,恶意微博里带了自动转发的脚本,用户一点开就中招并继续传播。
- 处理:紧急在网关层拦截该恶意URL的Referer,给转发接口加Token,清理恶意微博。
7. 验证码可重放或缺失
- 现象:以为加了验证码就安全,结果还是被伪造了。
- 排查:验证码没跟Session绑定,或者验证码用完后没销毁,攻击者抓包拿到了验证码值,在伪造请求里重放。
- 处理:验证码必须一次性使用,且与当前用户的Session强绑定。
8. 同源策略配置不当场景
- 现象:明明加了Token,还是被跨站请求了。
- 排查 :Cookie设置了
SameSite=None; Secure,导致跨站请求依然会携带Cookie。 - 处理 :把核心Cookie的
SameSite改为Lax或Strict。
处置与修复:分场景给策略
别慌,按这三档走:
第一档:止血(临时加校验)
- 临时拦截 :在WAF或网关层,配置规则拦截
Referer或Origin为已知恶意域名的请求。 - 临时加验证码:对正在被利用的高危接口,临时强制弹出图形验证码或滑块。
- 【生产环境风险】:临时加验证码可能会卡住正常用户的业务流程,必须跟业务方确认,优先在非核心接口或低峰期操作。
第二档:排查(用户受害范围)
- 异常操作回滚 :
- 账号恢复:密码被改的,通过邮箱/手机帮用户重置。
- 配置还原:收货地址、系统配置被改的,根据操作日志里的"修改前"快照进行数据回滚。
- 【生产环境风险】:回滚数据前必须备份,且要确认回滚操作本身不会触发其他业务逻辑(比如回滚订单状态不能重复退款)。
- 用户通知策略:通过站内信、短信或邮件,告知受影响用户账号存在异常操作,提醒修改密码。
第三档:修复(防伪造机制)
- 修复方案 :
-
防伪令牌校验 :所有写操作接口强制校验CSRF Token。
java// Spring Security 示例,开启CSRF防护 http.csrf().csrfTokenRepository(HttpOnlyCookieCsrfTokenRepository.withHttpOnlyFalse()); -
同源属性 :核心Cookie加上
SameSite=Lax。 -
来源头校验 :在拦截器里校验
Referer或Origin是否包含本站域名。
-
- 修复后验证:自己写个简单的HTML页面,放在本地或外部服务器,用表单或AJAX跨站提交到目标接口,确认被拦截(返回403)。
- 全站接口逐一排查 :用前面提到的
grep命令,把全站写接口扫一遍,补全防护。
根因分析:CSRF为什么老出事?
- 无防伪令牌:最直接的根因,写操作接口裸奔,没加CSRF Token。
- Cookie缺少同源安全属性 :Cookie没设
SameSite,跨站请求照样带Cookie。 - 接口无来源校验 :后端不校验
Referer和Origin,来者不拒。 - 敏感操作无二次确认:改密、转账这种高危操作,只凭一个Cookie就执行了,没要求重新验证身份。
- 安全开发规范缺失:前端和后端都没CSRF防护的意识,框架自带的防护被手动关掉了。
怎么定责? 看请求日志和会话记录。如果代码里没加Token校验,是研发的锅;如果Cookie没配 SameSite,是运维/架构的锅。把Nginx日志、Session记录和代码配置摆在一起,责任清清楚楚。
事后加固要点
- 防伪令牌全覆盖:所有POST/PUT/DELETE接口,必须校验CSRF Token。
- Cookie同源属性 :Session ID和核心鉴权Cookie,必须设置
SameSite=Lax(如果不需要跨站)或Strict。 - 来源头校验 :作为Token的补充防线,在网关层校验
Origin/Referer。 - 敏感操作二次验证:涉及资金、密码、核心配置的修改,必须要求输入密码或短信验证码。
- 接口幂等与审计:关键操作加上幂等性校验(防重放),并详细记录操作日志(包含来源IP、Referer、操作前后数据)。
- 安全测试纳入流程:渗透测试和自动化测试里,必须包含CSRF专项用例。
总结:处置过程中高频踩坑
复盘这次事件,这几个坑千万别踩:
- 只加验证码不查源头:加了验证码是治标,没查恶意Referer,攻击者换个不带验证码的接口继续打。
- 封IP误以为有效:CSRF请求是用户浏览器发的,封IP等于封了正常用户,攻击者换个页面继续搞。
- 只修一个接口漏全站:修了转账接口,结果修改个人资料的接口还在裸奔。
- 忽略用户受害范围:没查清楚到底有多少用户被改了密码,导致大面积客诉。
- 令牌方案落地不全:前端加了Token,但后端拦截器里忘了校验,或者Token没跟Session绑定。
- 同源属性没配 :Cookie没加
SameSite,导致跨站请求依然能带上身份凭证。 - 敏感操作无二次确认:只靠一个Cookie就允许修改密码,一旦被CSRF,用户直接失去账号控制权。
博主说两句 :
CSRF这漏洞,说大不大,说小不小。它不能直接偷数据,但能借刀杀人,让用户自己给自己挖坑。研发兄弟们记住,永远不要信任跨站来的请求,GET请求别做状态变更,写操作必须带Token!
觉得这篇复盘有用的,点赞、收藏、关注走一波!后续还会更新更多一线安全实战干货,有问题的兄弟评论区见,看到必回!