前置知识: 网络安全

CSRF攻击

00:00
4 min Intermediate 2026/6/14

跨站请求伪造攻击原理、攻击方式与防御机制详解。

1. CSRF 攻击原理

1.1 什么是 CSRF

跨站请求伪造(Cross-Site Request Forgery, CSRF)是一种利用用户已认证的身份,在用户不知情的情况下发起恶意请求的攻击方式。

1.2 攻击流程

1. 用户登录受信网站 A → 获得有效 Cookie/Session
2. 用户访问恶意网站 B → B 中包含对 A 的伪造请求
3. 浏览器自动携带 A 的 Cookie → A 服务器认为是合法请求
4. 攻击完成 → 用户账户执行了非预期操作

1.3 与 XSS 的区别

对比项CSRFXSS
攻击目标伪造用户请求注入恶意脚本
是否需要脚本执行不一定必须
能否读取响应不能(同源策略)
Cookie 可见性不可见可见
防御重点请求来源验证输入输出过滤

2. CSRF 攻击方式

2.1 GET 型 CSRF

最简单的攻击方式,通过图片标签或链接触发:

<!-- 转账攻击 -->
<img src="https://bank.com/transfer?to=attacker&amount=10000" />

<!-- 修改密码 -->
<img src="https://example.com/changepwd?newpwd=hacked123" />

<!-- 诱导点击 -->
<a href="https://example.com/delete?id=1">点击领取奖品</a>

2.2 POST 型 CSRF

通过自动提交的表单发起 POST 请求:

<form id="csrf-form" action="https://bank.com/transfer" method="POST">
  <input type="hidden" name="to" value="attacker" />
  <input type="hidden" name="amount" value="10000" />
</form>
<script>
  document.getElementById('csrf-form').submit();
</script>

2.3 AJAX 型 CSRF

利用 XMLHttpRequest 或 Fetch API:

fetch('https://example.com/api/delete', {
  method: 'POST',
  credentials: 'include', // 携带 Cookie
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ id: 1 }),
});

注:当 Content-Typeapplication/json 时,浏览器会先发送 OPTIONS 预检请求(CORS),但某些服务器配置不当仍可能被利用。

2.4 JSON 型 CSRF

某些应用接受 Content-Type: text/plain 或表单格式的 JSON:

<form action="https://api.example.com/action" method="POST" enctype="text/plain">
  <input type="hidden" name='{"action":"delete","id":' value='1,"ignore":"' />
</form>

3. CSRF 防御机制

3.1 CSRF Token

最主流的防御方式,服务器为每个会话/表单生成随机 Token:

服务端生成

# Flask 示例
from flask_wtf.csrf import CSRFProtect

csrf = CSRFProtect(app)

# 模板中自动注入
# <input type="hidden" name="csrf_token" value="{{ csrf_token() }}">

验证流程

1. 服务器生成随机 Token → 存入 Session
2. 表单中嵌入隐藏字段携带 Token
3. 提交时服务器验证 Token 是否匹配
4. 攻击者无法获取 Token → 伪造请求失败
Set-Cookie: session=abc123; SameSite=Strict
效果
Strict完全禁止跨站请求携带 Cookie
LaxGET 导航请求允许,POST/iframe 等禁止
None允许跨站携带(需配合 Secure

推荐:大数场景使用 SameSite=Lax,兼顾安全用户体验

3.3 Referer / Origin 检查

# 验证请求来源
def verify_origin(request):
    origin = request.headers.get('Origin')
    referer = request.headers.get('Referer')
    allowed = ['https://example.com']

    if origin and origin not in allowed:
        return False
    if referer and not any(referer.startswith(a) for a in allowed):
        return False
    return True

局限性

  • 隐私设置可能移除 Referer
  • Origin 在 GET 请求中可能为空
  • 域名可能被绕过
1. 服务器将 Token 写入 Cookie
2. 前端 JavaScript 读取 Cookie → 添加到请求头/参数
3. 服务器验证 Cookie 中的 Token 与请求中的 Token 一致

攻击者无法读取 Cookie,因此无法在请求中附加该 Token

3.5 自定义请求头

// 前端添加自定义头
fetch('/api/action', {
  method: 'POST',
  headers: { 'X-Requested-With': 'XMLHttpRequest' },
});

由于 CORS 限制,跨请求无法添加自定义头,因此 CSRF 攻击无法携带此

4. RESTful API 的 CSRF 防护

策略适用场景
Bearer TokenJWTSPA + API 架构TokenlocalStorage
CSRF Token传统提交
SameSite Cookie所有场景的基础防护
Origin 检查API 网关验证

5. CSRF 攻击检测

5.1 自动化工具

工具
Burp Suite CSRF POC一键生成 CSRF PoC
OWASP ZAP自动化 CSRF 检测
CSRF Tester专用 CSRF 测试工具

5.2 手动测试要点

  • 检查关键操作(转账、改密、删除)是否验证 CSRF Token
  • 验证 Token 是否可预测固定
  • 检查是否验证 Referer/Origin
  • 测试 SameSite Cookie 配置
  • 检查 JSON API 是否仅依赖 Cookie 认证

知识检测

学习进度

-- 已学文档
--% 知识覆盖率

学习推荐

专注模式