1. 思路🚀
本关的SQL语句为:
sql
# 注册
$sql = "insert into users ( username, password) values(\"$username\", \"$pass\")";
# 登录
$sql = "SELECT * FROM users WHERE username='$username' and password='$password'";
# 更新
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";
- 注入类型:字符串型(单引号包裹)、GET操作、POST操作
- 提示:参数需以
'
闭合 - 关键参数:
username
本关卡是很有意思的,知识点是二次排序注入(Second-Order SQL Injection),整个过程:注册新用户→登录→修改密码。
1.1. 那什么是二次排序注入?🔍
二次排序注入 是一种特殊的 SQL 注入攻击方式,它不像传统注入那样直接 在输入时触发漏洞,而是分两步 完成攻击:
- 第一步 :攻击者提交恶意数据,但数据不会立即执行 SQL 注入 ,而是被存储到数据库(如注册、评论、修改资料等场景)。
- 第二步 :当其他功能读取并使用了这些存储的数据时,恶意 SQL 代码被执行,导致攻击成功。
1.2. 二次排序注入 vs. 普通 SQL 注入⭐
对比项 | 普通 SQL 注入 | 二次排序注入 |
---|---|---|
触发方式 | 直接提交恶意输入(如登录、搜索) | 先存储恶意数据,后续操作触发执行 |
过滤绕过 | 依赖输入时的过滤 | 存储时可能不严格过滤,执行时才触发漏洞 |
攻击隐蔽性 | 容易被 WAF 检测 | 更难检测,因为攻击分两步完成 |
常见场景 | 登录框、搜索框 | 用户注册、评论、资料修改、订单系统 |

注:本关卡的文件有很多,不过只需要关注:login_create.php
(注册),login.php
(登录),pass_change.php
(更新)。
2. 攻击注入步骤🎯
以数据库中存在的用户admin
为例,那个最后操作的是用户admin
的密码,攻击注入的整个流程如下:
2.1. 攻击者注册恶意用户名⚡
注册 SQL 的执行语句:
sql
INSERT INTO users (username, password) VALUES ("admin'#", "123456");
数据库存储:
username | password |
---|---|
admin'# |
123456 |

关键点:
- 用户名
admin'#
包含 SQL 注入字符'#
(#
是 MySQL 注释符)。 - 此时 没有直接触发 SQL 注入,只是存储了恶意数据。
2.2. 攻击者登录⚡
登录 SQL 的执行语句:
sql
SELECT * FROM users WHERE username='admin'#' AND password='123456';

2.3. 攻击者修改密码(触发二次注入)⚡
修改密码 SQL 的执行语句:
sql
UPDATE users SET PASSWORD='111111' WHERE username='admin'#' AND password='123456';
#
再次注释掉后面的 AND password='123456'
,实际执行的 SQL:
sql
UPDATE users SET PASSWORD='111111' WHERE username='admin'
结果 :admin
用户的密码被修改为 111111
,而 不是 admin'#
的用户。

3. 攻击成功的原因💥
-
注册时未过滤
'
和#
- 允许攻击者存储恶意用户名
admin'#
。
- 允许攻击者存储恶意用户名
-
修改密码时直接拼接 SQL
- 未对从数据库读取的
username
进行二次过滤,导致'#
被当作 SQL 代码执行。
- 未对从数据库读取的
-
注释符
#
绕过密码验证#
注释掉后续条件,使攻击者能直接修改admin
的密码。
4. 总结🏁
- 二次排序注入 是 先存储恶意数据,后续操作触发 SQL 注入 的攻击方式。
- 危害更大,因为攻击隐蔽,可能绕过传统 WAF 检测。
- 防御核心 :
- 参数化查询(避免拼接 SQL)
- 输入 & 输出双重过滤
- 最小权限原则
如果系统涉及 用户注册、评论、订单修改 等功能,务必检查是否存在二次排序注入风险! 🚨
声明:本文仅用于安全学习,严禁非法测试! ❗❗❗