CSRF攻击怎么防护?2024年最全防御指南与实战问答
目录导读
- 什么是CSRF攻击?核心原理与危害
- CSRF攻击的三种典型场景
- 企业级防护:主流防御方案详解(含代码示例)
- 开发者必知:前后端分离架构下的CSRF防护
- 常见问题与高频问答(FAQ)
- 构建分层防御体系的黄金法则
什么是CSRF攻击?核心原理与危害
核心定义
CSRF(Cross-Site Request Forgery,跨站请求伪造)是一种让已登录用户在当前网页不知情的情况下,执行非本意操作的攻击方式,攻击者利用受害者已通过认证的会话,伪造请求至目标网站,实现转账、改密、发布内容等恶意操作。

攻击四步原理
- 用户登录:用户登录目标网站A(如银行),浏览器保存了Cookie或Session ID。
- 诱导访问:攻击者诱导用户访问恶意网站B(如钓鱼链接、含恶意代码的论坛)。
- 伪造请求:网站B的代码自动向网站A发送表单提交、图片请求、Ajax等跨域请求。
- 执行操作:浏览器自动携带目标网站A的Cookie,网站A验证通过后执行攻击者预设的操作。
典型危害
- 资金盗取:修改银行转账地址
- 数据篡改:修改用户密码、邮箱
- 业务被滥用:刷帖、改权限、下单
CSRF攻击的三种典型场景
| 场景类型 | 攻击示例 | 漏洞关键 |
|---|---|---|
| GET型 | <img src="http://bank.com/transfer?to=attacker&amount=1000"> |
幂等操作未验证来源 |
| POST型 | <form action="http://mail.com/resetPwd" method="POST"> |
未使用Token或Referer检查 |
| JSON型 | 利用Fetch/Ajax发送跨域POST请求 | CORS配置不当且未验证Origin |
注意:CSRF与XSS不同,XSS依赖恶意脚本植入,而CSRF利用的是浏览器对Cookie的自动携带机制。
企业级防护:主流防御方案详解(含代码示例)
1 方案一:CSRF Token(行业标准)
原理:服务器生成随机Token存入Session,每次非GET请求校验客户端提交的Token是否一致。
Python Flask示例:
from flask import Flask, session, request, render_template_string
import secrets
app = Flask(__name__)
app.secret_key = secrets.token_hex(16)
@app.route('/form')
def form():
token = secrets.token_hex(32)
session['csrf_token'] = token
return render_template_string('''
<form method="POST" action="/transfer">
<input type="hidden" name="csrf_token" value="{{ token }}">
<input type="text" name="amount">
<input type="submit">
</form>
''')
@app.route('/transfer', methods=['POST'])
def transfer():
if request.form.get('csrf_token') != session.get('csrf_token'):
return '无效Token,拒绝请求', 403
# 执行转账逻辑
return '转账成功'
2 方案二:SameSite Cookie属性
原理:浏览器通过Cookie的SameSite属性控制跨域请求是否携带Cookie。
Strict:仅同站请求携带(最严格)Lax:允许GET请求等安全方法携带None:允许跨域携带(需配合Secure属性)
设置示例:
Set-Cookie: session_id=abc123; SameSite=Strict; Secure
3 方案三:Origin/Referer验证
方案:后端校验HTTP请求头的Origin或Referer是否与信任域名匹配。
Node.js Express示例:
app.post('/api/transfer', (req, res) => {
const origin = req.headers.origin || req.headers.referer;
if (!origin || !origin.startsWith('https://trusted-bank.com')) {
return res.status(403).json({error: '非法来源'});
}
// 执行操作
});
4 方案四:自定义请求头+CORS限制
适用于API接口:要求每个请求携带自定义请求头(如X-CSRF-TOKEN),且通过CORS限制允许的来源域。
开发者必知:前后端分离架构下的CSRF防护
在SPA或前后端分离架构中,Cookie可能仍被用作认证凭证,但需要额外注意:
- Token生成:后端首次登录时返回CSRF Token,前端存储至
localStorage或内存,而非Cookie。 - 双重提交Cookie:设置一个单独的
csrf_tokenCookie,前端从Cookie读取并附加到请求头,后端校验该Cookie值与请求头是否一致。 - 现代方案:使用
Authorization头传递JWT Token代替Cookie认证,从根本上消除Cookie自动携带的风险。
关键原则:永远不要依赖浏览器的自动凭证携带机制,手动管理身份凭证是最安全的。
常见问题与高频问答(FAQ)
Q1:为什么Cookie的SameSite属性不能完全防御CSRF?
A:因为子域名间的请求(如evil.example.com请求bank.example.com)仍可能被SameSite=Lax允许,且旧版浏览器(如Safari 16.3以下)存在兼容性漏洞。
Q2:CSRF Token的生成方式有哪些要求?
A:必须不可预测(伪随机数生成器)、每个会话唯一、且每次提交后应更新(防止Token重用攻击)。
Q3:GET请求是否真的不用防护CSRF?
A:严格来说GET请求若存在副作用(如投票、删除操作),必须同样防护,推荐所有非幂等操作使用POST/DELETE等方法并配合Token。
Q4:移动端是否需要考虑CSRF?
A:需要,移动端WebView可能持有关联Cookie,同理可被诱导提交;原生App若使用WebView加载页面,同样面临风险。
Q5:前端框架如React/Vue如何辅助防护?
A:使用Axios库时可通过拦截器自动从Cookie读取Token并添加到请求头,但建议后端同时启用SameSite=Strict作为第二道防线。
构建分层防御体系的黄金法则
| 防御层次 | 具体措施 | 优先级 |
|---|---|---|
| 基础层 | 所有非GET/HEAD请求验证CSRF Token | 必选 |
| 配置层 | Cookie设置SameSite=Strict |
推荐 |
| 校验层 | 校验Origin/Referer |
辅助 |
| 架构层 | 用JWT替代Cookie认证 | 长期 |
防御误区:
- ❌ 仅依赖Referer检查(可被伪造)
- ❌ 仅使用URL重写传递Token(易泄露)
- ❌ 用户端验证(攻击者同样可读取DOM)
最后提醒:安全防御不是单一技术的堆叠,而是“纵深防御”思想的实践,定期进行安全审计、使用WAF规则辅助、以及理解业务逻辑中的潜在风险点,才是杜绝CSRF的终极之道。
本文综合OWASP CSRF防御指南、MDN Web文档、以及2024年主流安全社区最佳实践编写而成,旨在提供经网络验证的准确防护方案。