摘要 {#摘要}
本次实验主要是通过对一个基于 MySQL 数据库的用户身份验证脚本进行审计,发现存在二次注入漏洞。通过分析代码,审计人员指出了存在的安全问题,包括使用过时的转义函数、缺乏密码加密、缺乏会话管理函数、缺乏对用户上传文件的检查和过滤、缺乏对用户输入的验证和过滤等。同时,讨论了一个 SQL 查询语句出现的错误,提供了一些可能的解决方案。在实验中,攻击者成功地构造了一个恶意数据,并将其插入到数据库中,然后利用该数据进行二次注入攻击,成功地修改了管理员账户的密码。最后,建议使用现代的安全编程技术来避免安全问题。
前言 {#前言}
第二十四关,这关的登录界面乍一看还是比较新奇的,他这里有个登录以及用户注册,首先我们可以尝试分析一下他的源码,重点在他修改密码这里,他直接去获取了username的值,并未做任何的过滤,所以我这里就可以尝试往username的值里写一个特殊的传参,然后再利用他去修改密码,而这种先往数据库里写一个特殊参数,然后再调用这个参数去进行注入也被称之为二次注入
📢什么是二次注入
二次注入可以理解为,攻击者构造的恶意数据存储在数据库后,恶意数据被读取并进入到SQL查询语句所导致的注入。防御者可能在用户输入恶意数据时对其中的特殊字符进行了转义处理,但在恶意数据插入到数据库时被处理的数据又被还原并存储在数据库中,当Web程序调用存储在数据库中的恶意数据并执行SQL查询时,就发生了SQL二次注入。
📢二次注入,可以概括为以下两步
- 第一步: 插入恶意数据
进行数据库插入数据时,对其中的特殊字符进行了转义处理,在写入数据库的时候又保留了原来的数据。
- 第二步:引用恶意数据
开发者默认存入数据库的数据都是安全的,在进行查询时,直接从数据库中取出恶意数据
前期准备 {#前期准备}
开启phpstudy,开启apache服务以及mysql服务
实验环节 {#实验环节}
浏览器访问Less-24 {#浏览器访问Less-24}
http://192.168.199.135/sqli-labs-master/Less-24/
pass_change.php代码分析 {#pass_change.php代码分析}
<html>
<head>
</head>
<body bgcolor="#000000">
<?PHP
session_start();
if (!isset($_COOKIE["Auth"]))
{
if (!isset($_SESSION["username"]))
{
header('Location: index.php');
}
header('Location: index.php');
}
?>
<div align="right">
<a style="font-size:.8em;color:#FFFF00" href='index.php'><img src="../images/Home.png" height='45'; width='45'></br>HOME</a>
</div>
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
if (isset($_POST\['submit'\]))
{
# Validating the user input........
$username= $_SESSION["username"];
$curr_pass= mysql_real_escape_string($_POST['current_password']);
$pass= mysql_real_escape_string($_POST['password']);
$re_pass= mysql_real_escape_string($_POST['re_password']);
if($pass==$re_pass)
{
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";
$res = mysql_query($sql) or die('You tried to be smart, Try harder!!!! :( ');
$row = mysql_affected_rows();
echo '<font size="3" color="#FFFF00">';
echo '<center>';
if($row==1)
{
echo "Password successfully updated";
}
else
{
header('Location: failed.php');
//echo 'You tried to be smart, Try harder!!!! :( ';
}
}
else
{
echo '<font size="5" color="#FFFF00"><center>';
echo "Make sure New Password and Retype Password fields have same value";
header('refresh:2, url=index.php');
}
`}
?>
<?php
if(isset($_POST['submit1']))
{
session_destroy();
setcookie('Auth', 1 , time()-3600);
header ('Location: index.php');
}
?>
</center>`
`
</body>
</html>
`
通过gpt进行代码分析和审计可得出以下结果
这段代码是一个PHP脚本,用于更新用户的密码。它包括以下步骤:
1.
首先,代码使用session_start()函数启动会话,并检查是否设置了名为"Auth"的cookie。如果没有设置,则检查是否设置了名为"username"的会话变量。如果没有设置,则将用户重定向到index.php页面。
2.
接下来,代码包含了一个名为sql-connect.php的文件,该文件包含了与MySQL数据库的连接参数。
3.
如果用户提交了表单(即用户已经输入了当前密码、新密码和重新输入新密码),则代码将获取用户的输入,并使用mysql_real_escape_string()函数对其进行转义,以避免SQL注入攻击。
4.
代码将检查新密码和重新输入新密码是否匹配。如果匹配,则使用UPDATE语句将新密码更新到数据库中。
5.
如果更新成功,则代码将输出"Password successfully updated"消息。否则,代码将重定向到failed.php页面。
6.
如果新密码和重新输入新密码不匹配,则代码将输出"Make sure New Password and Retype Password fields have same value"消息,并将用户重定向到index.php页面。
7.
如果用户点击了"submit1"按钮,则代码将销毁会话,并将名为"Auth"的cookie设置为过期状态,并将用户重定向到index.php页面。
从安全角度来看,这段代码存在以下问题:
`
`
*
代码使用mysql_real_escape_string()函数对用户输入进行了转义,但这种方法已经过时,应该使用预处理语句来避免SQL注入攻击。
*
代码没有对密码进行加密,应该使用哈希函数(如bcrypt)来加密密码。
*
代码没有使用会话管理函数(如session_regenerate_id())来保护会话免受会话劫持攻击。
*
代码没有对用户上传的文件进行检查和过滤,可能存在文件包含漏洞。
* `
`
`代码没有对用户输入进行验证和过滤,可能存在跨站脚本攻击(XSS)漏洞。
`
但是仔细看发现只有username这个传参没有用mysql_real_escape_string(),所以我们通过用户名注册进行下手
构造闭合用户名 {#构造闭合用户名}
#原sql语句
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";
#修改username里面字段为admin'#,这样前面两个单引号构造闭合,后面的那个单引号被#键注释掉了
$sql = "UPDATE users SET PASSWORD='$pass' where username='admin'#' and password='$curr_pass' ";
注册账号为admin'# {#注册账号为admin'#}
账号:admin'#
密码:123456
登录这个账号 {#登录这个账号}
用这个我们注册的账号登录进去,发现需要重新设置密码
修改密码 {#修改密码}
原密码:123456
新密码:xz123
如图显示,则修改成功
验证查询 {#验证查询}
登录数据库显示原admin账号的密码admin现在已经变成了我们改成修改后的xz123
登录验证,发现页面上显示的是我们的admin用户
用户名:admin
密码: xz123