CSRF攻击怎么防护?

wen 网络安全 2

CSRF攻击怎么防护?2024年最全防御指南与实战问答

目录导读

  1. 什么是CSRF攻击?核心原理与危害
  2. CSRF攻击的三种典型场景
  3. 企业级防护:主流防御方案详解(含代码示例)
  4. 开发者必知:前后端分离架构下的CSRF防护
  5. 常见问题与高频问答(FAQ)
  6. 构建分层防御体系的黄金法则

什么是CSRF攻击?核心原理与危害

核心定义

CSRF(Cross-Site Request Forgery,跨站请求伪造)是一种让已登录用户在当前网页不知情的情况下,执行非本意操作的攻击方式,攻击者利用受害者已通过认证的会话,伪造请求至目标网站,实现转账、改密、发布内容等恶意操作。

CSRF攻击怎么防护?

攻击四步原理

  1. 用户登录:用户登录目标网站A(如银行),浏览器保存了Cookie或Session ID。
  2. 诱导访问:攻击者诱导用户访问恶意网站B(如钓鱼链接、含恶意代码的论坛)。
  3. 伪造请求:网站B的代码自动向网站A发送表单提交、图片请求、Ajax等跨域请求。
  4. 执行操作:浏览器自动携带目标网站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请求头的OriginReferer是否与信任域名匹配。

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_token Cookie,前端从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年主流安全社区最佳实践编写而成,旨在提供经网络验证的准确防护方案。

抱歉,评论功能暂时关闭!