SQL 注入的核心原理是攻击者通过构造恶意输入,篡改数据库执行的 SQL 语句逻辑,但其具体利用方式会因数据库管理系统(DBMS)的语法特性、内置功能和配置差异而有所不同。SQL Server 和 MySQL 作为两种主流的关系型数据库,在 SQL 注入场景中的区别主要体现在以下几个方面:
一、注释符的差异
注释符是 SQL 注入中常用的工具,用于截断原始 SQL 语句的剩余部分,避免语法错误。两种数据库支持的注释符存在差异:
| 数据库 | 常用注释符 | 说明 |
|---|---|---|
| SQL Server | -- (双减号 + 空格)、/* */(多行注释) |
-- 后必须加空格,否则可能被解析为标识符的一部分;/* */ 支持多行注释。 |
| MySQL | -- (双减号 + 空格)、#(井号)、/* */ |
# 是 MySQL 特有的单行注释符,无需空格;-- 后也可加空格或直接换行(部分版本支持)。 |
注入示例 :
假设原始查询为 SELECT * FROM users WHERE username = 'input':
- SQL Server 注入需用
' OR 1=1--(注意--后有空格); - MySQL 注入可用
' OR 1=1#或' OR 1=1--(无需空格)。
二、字符串连接方式的差异
注入时 often 需要拼接字符串(如构造联合查询、生成恶意语句),两种数据库的字符串连接语法不同:
| 数据库 | 字符串连接方式 | 示例 | ||||
|---|---|---|---|---|---|---|
| SQL Server | 使用 + 运算符 |
'a' + 'b' 结果为 'ab' |
||||
| MySQL | 使用 CONCAT() 函数或 ` |
`(需配置) | CONCAT('a', 'b') 结果为 'ab';` |
默认为逻辑或,需开启PIPES_AS_CONCAT` 模式才作为连接符。 |
注入影响 :
在构造联合查询(如 UNION SELECT)时,拼接字段的语法不同。例如,获取版本信息时:
- SQL Server:
UNION SELECT 1, @@version, 3-- - MySQL:
UNION SELECT 1, CONCAT(version()), 3#
三、系统元数据查询的差异
注入时需枚举数据库结构(库名、表名、列名等),但两种数据库存储元数据的系统表 / 视图不同:
| 数据库 | 元数据存储位置 | 常用查询示例(获取表名) |
|---|---|---|
| SQL Server | 系统视图(如 sys.databases、sys.tables、sys.columns) |
SELECT name FROM sys.tables-- (查询当前库所有表) |
| MySQL | information_schema 数据库(通用标准) |
SELECT table_name FROM information_schema.tables WHERE table_schema = database()#(查询当前库所有表) |
差异细节:
- SQL Server 的系统视图与数据库绑定更紧密,需通过
sys.databases先获取库名,再切换库查询表; - MySQL 的
information_schema是全局元数据库,可直接跨库查询(需权限)。
四、堆叠查询(Stacked Queries)的支持差异
堆叠查询指在一个 SQL 语句中通过分号 ; 分隔多个独立语句,攻击者可借此执行额外操作(如删表、插入数据)。两种数据库的支持情况不同:
| 数据库 | 堆叠查询支持情况 | 限制条件 |
|---|---|---|
| SQL Server | 默认支持(多数驱动和接口允许) | 需注入点位于语句开头或中间,且权限足够(如 sa 权限)。 |
| MySQL | 部分支持(依赖驱动和接口) | 传统 mysql_query() 函数不支持,需用 mysqli_multi_query() 等;且部分环境会禁用分号解析。 |
注入示例:
- SQL Server:
' ; DROP TABLE users--(直接执行删表) - MySQL:需接口支持多语句,例如
' ; INSERT INTO users (username) VALUES ('hacker')#。
五、错误信息与盲注函数的差异
当注入无法直接返回结果时,攻击者需通过错误信息或时间延迟判断逻辑是否成立,两种数据库的错误提示和盲注函数不同:
1. 错误信息特征
错误信息是攻击者识别数据库类型的重要依据:
- SQL Server 错误示例:
Invalid column name 'x'(无效列名)、Incorrect syntax near ';'(语法错误)。 - MySQL 错误示例:
Unknown column 'x' in 'where clause'(未知列)、You have an error in your SQL syntax(语法错误)。
2. 时间盲注函数
时间盲注通过延迟执行判断条件是否成立,函数差异如下:
| 数据库 | 时间延迟函数 / 语法 | 示例 |
|---|---|---|
| SQL Server | WAITFOR DELAY '时间' |
IF (1=1) WAITFOR DELAY '0:0:5'-- (延迟 5 秒) |
| MySQL | SLEEP(N) 或 BENCHMARK() |
IF (1=1) SLEEP(5)#(延迟 5 秒) |
六、内置功能与权限滥用的差异
两种数据库的内置函数、存储过程和权限特性不同,导致高阶注入利用方式存在差异:
1. 系统命令执行
- SQL Server :可通过扩展存储过程
xp_cmdshell执行系统命令(需sa权限且启用),例如:
' ; EXEC xp_cmdshell 'whoami'-- - MySQL :无直接执行系统命令的内置函数,需通过
into outfile写文件(如写 Webshell),例如:
' UNION SELECT '<?php eval($_POST[x]);?>' INTO OUTFILE 'C:/web/shell.php'#(需文件权限和secure_file_priv配置允许)。
2. 敏感信息函数
获取数据库用户、版本等信息的函数不同:
- SQL Server :
@@version(版本)、SUSER_SNAME()(当前用户)、DB_NAME()(当前库)。 - MySQL :
version()(版本)、user()(当前用户)、database()(当前库)。
七、其他语法细节差异
- 字符串大小写敏感性 :
- SQL Server 默认不区分大小写(取决于排序规则);
- MySQL 对表名、列名的大小写敏感(取决于操作系统,Linux 敏感,Windows 不敏感)。
- 空值处理 :
- SQL Server 用
NULL,判断空值需用IS NULL; - MySQL 同样用
NULL,但部分场景下''(空字符串)与NULL处理不同。
- SQL Server 用
- 分页语法 :
- SQL Server 用
OFFSET ... FETCH或TOP N; - MySQL 用
LIMIT N, M,注入时构造分页逻辑的语法不同。
- SQL Server 用
总结
SQL Server 和 MySQL 的 SQL 注入差异本质上源于两者的语法设计、系统表结构、内置功能和配置特性。尽管核心注入原理一致,但具体利用手段(如注释符、元数据查询、堆叠查询、盲注函数)均需适配目标数据库的特性。了解这些差异有助于更精准地检测注入攻击,或在渗透测试中针对性构造 payload。