sqli-labs靶场通关笔记:第24关 二次注入

一、审题

这关是一个用户登录界面,还有忘记密码和注册新用户操作,和正常网站很相似了。本关考察内容是二次注入。

二、思考

简单讲解一下什么是二次注入,就是需要进行两次操作。第一次构建的恶意语句被写入数据库中保存,并没有触发。第二次执行SQL语句时触发了第一次的恶意语句,产生攻击效果。

sql 复制代码
<?php
// 包含数据库连接文件
include("../sql-connections/sql-connect.php");

// 检查是否通过POST方法提交了表单
if (isset($_POST['submit'])) {
    // 从POST请求中获取用户名,并使用mysql_escape_string进行转义(防止SQL注入)
    $username = mysql_escape_string($_POST['username']);
    
    // 获取密码和确认密码,并进行转义
    $pass = mysql_escape_string($_POST['password']);
    $re_pass = mysql_escape_string($_POST['re_password']);
    
    // 设置输出文本的字体大小和颜色(黄色)
    echo "<font size='3' color='#FFFF00'>";
    
    // 构建SQL查询:检查数据库中是否已存在该用户名
    $sql = "select count(*) from users where username='$username'";
    
    // 执行SQL查询,如果失败则输出错误信息并终止脚本
    $res = mysql_query($sql) or die('You tried to be smart, Try harder!!!! :( ');
    
    // 获取查询结果的第一行数据
    $row = mysql_fetch_row($res);
    
    // 检查用户名是否已存在(如果查询结果不为0,表示已存在)
    if (!$row[0] == 0) {
        // 使用JavaScript弹出提示框,告知用户用户名已存在
        ?>
        <script>alert("The username Already exists, Please choose a different username ")</script>;
        <?php
        
        // 1秒后重定向到注册页面
        header('refresh:1, url=new_user.php');
    } else {
        // 用户名不存在,继续注册流程
        if ($pass == $re_pass) {
            // 密码和确认密码匹配,构建插入用户数据的SQL查询
            $sql = "insert into users ( username, password) values(\"$username\", \"$pass\")";
            
            // 执行插入查询,如果失败则输出错误信息
            mysql_query($sql) or die('Error Creating your user account,  : '.mysql_error());
            
            // 输出注册成功的提示信息和图片
            echo "</br>";
            echo "<center><img src=../images/Less-24-user-created.jpg><font size='3' color='#FFFF00'>";
            echo "</br>";
            echo "</br>";
            echo "</br>";
            echo "</br>Redirecting you to login page in 5 sec................";
            echo "<font size='2'>";
            echo "</br>If it does not redirect, click the home button on top right</center>";
            
            // 5秒后重定向到登录页面
            header('refresh:5, url=index.php');
        } else {
            // 密码和确认密码不匹配,提示用户
            ?>
            <script>alert('Please make sure that password field and retype password match correctly')</script>
            <?php
            
            // 1秒后重定向到注册页面
            header('refresh:1, url=new_user.php');
        }
    }
}
?>

这是本关注册用户名的源代码, 为了防止sql注入,对获取的用户名和密码进行了转义。mysql_escape_string() 是 PHP 语言里用于处理 SQL 查询的一个函数,其主要功能是对字符串中的特殊字符进行转义操作,不过在 PHP 5.5.0 版本之后已被弃用。

比如注册的用户名是admin'#,函数会将单引号转义为反斜杠单引号,变成username =admin\\'#这样。但是在插入数据这行代码中,变量名username使用了双引号包裹,而双引号会解析转义字符\',将它还原为单引号,导致最终存储到数据库中的用户名还是admin'#。

sql 复制代码
假设用户输入:
username = admin'#
password = 123456

转义后的值:
$username = "admin\'#";  // mysql_escape_string() 的结果
$pass = "123456";

SQL 拼接结果:
INSERT INTO users (username, password) VALUES("admin'#", "123456")

再看一下修改密码的源代码中核心的一句。

sql 复制代码
//通过匹配用户名和原密码来更新密码;
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";

攻击者第一次创建的admin'#用户名被存储到数据库中,当攻击者进行第二次操作,也就是修改密码时,会发生什么?

sql 复制代码
//修改admin"#用户的密码时的语句;
$sql = "UPDATE users SET PASSWORD='123456' where username='admin'#' and password='$curr_pass' ";

但实际上(#' and password='$curr_pass' )被注释掉,语句成为:

sql 复制代码
UPDATE users SET PASSWORD='123456' where username='admin'

结果导致admin管理员用户的密码被修改为123456。

这就是二次注入产生的效果。

三、做法

1.第一次注入恶意语句,可以看到注册成功,而此时管理员admin的密码是admin;

2.二次注入,进行修改密码操作;

3.显示密码修改成功,查看一下结果,发现实际上是admin用户的密码被修改为123456;

相关推荐
枷锁—sha11 小时前
【SRC】SQL注入WAF 绕过应对策略(二)
网络·数据库·python·sql·安全·网络安全
天荒地老笑话么18 小时前
静态 IP 规划:掩码/网关/DNS 的正确组合
网络·网络协议·tcp/ip·网络安全
大方子1 天前
【PolarCTF】rce1
网络安全·polarctf
枷锁—sha2 天前
Burp Suite 抓包全流程与 Xray 联动自动挖洞指南
网络·安全·网络安全
聚铭网络2 天前
聚铭网络再度入选2026年度扬州市网络和数据安全服务资源池单位
网络安全
darkb1rd2 天前
八、PHP SAPI与运行环境差异
开发语言·网络安全·php·webshell
世界尽头与你2 天前
(修复方案)基础目录枚举漏洞
安全·网络安全·渗透测试
枷锁—sha3 天前
【SRC】SQL注入快速判定与应对策略(一)
网络·数据库·sql·安全·网络安全·系统安全
liann1193 天前
3.1_网络——基础
网络·安全·web安全·http·网络安全
ESBK20253 天前
第四届移动互联网、云计算与信息安全国际会议(MICCIS 2026)二轮征稿启动,诚邀全球学者共赴学术盛宴
大数据·网络·物联网·网络安全·云计算·密码学·信息与通信