0x01 基础
说明:本文用于授权范围内的安全测试与防护加固整理,重点放在攻击面如何形成以及如何在服务端做规范化与拦截,避免在真实环境被绕过。
1)逻辑符
常见逻辑运算符会参与 SQL 表达式求值,很多“真假对比”“短路判断”的测试都围绕它们展开:
and(&&)
or(||)
xor(^)
> 有些数据库不支持异或运算
此外还有一些实战中不太常用、但在表达式层面同样存在的运算符:
not(!)
~(位取反)
<<(位左移)
>>(位右移)
2)运算符(加减乘除)
不要小看运算符:它既能参与表达式构造,也常被用于“输入看似合法但语义被改变”的场景。对防护而言,运算符会带来两个核心问题:
- 语义等价变体太多:同一个条件可以用不同表达式写出来。
- 错误与异常侧信道:某些运算会触发数据库错误(例如除零、类型转换失败),若错误被回显或时间差被放大,会暴露信息。
防护侧建议:
- 服务端统一参数类型(例如
id 必须为整数),拒绝任何非数字字符与超长输入。
- 数据库访问统一走参数化查询(prepared statements),不要拼接表达式。
3)注释符
注释符会改变 SQL 的解析边界,是防护绕过里非常常见的一类点。常见形式:
#(MySQL 特有,URL 中需编码为 %23)
--(注意后面需跟空格或换行)
/* */(多行注释,部分方言支持嵌套/特殊注释语法)
;%00(空字符截断,部分环境有效)
防护侧建议:
- 在进入 WAF/规则前做统一解码与规范化(canonicalization),包括 URL 解码、Unicode 归一化等。
- 在应用层对输入做白名单,避免“允许注释符存在”的需求出现。
0x02 通用绕过“思路”与防护要点
这一节按“绕过思路”来拆解:攻击者通常做的是让过滤器看到 A、让数据库执行 B。防护则要做到:过滤、日志、检测都基于同一份规范化后的输入。
1)强制 URL 编码 / 双重解码差异
一些链路会出现“应用解码一次、网关再解码一次”或“上游未解码、下游解码”的不一致,从而导致拦截失效。
防护侧建议:
- 在最靠近入口(网关或应用第一层)完成一次且仅一次的解码与规范化。
- 对“二次解码后出现危险字符”的请求直接拒绝并记录告警。
2)特殊空白字符与“替代空格”问题
很多过滤器只关注普通空格,但 SQL 解析器可能把 TAB、换行等也当作分隔符;还有注释插入分隔的玩法。
常见“空白字符”语义(示意):
| 字符(编码形态) |
含义 |
说明 |
%09 |
TAB(水平) |
水平制表符 |
%0a |
换行 |
LF |
%0d |
回车 |
CR |
/**/ |
注释 |
常被用于插入分隔 |
/*!...*/ |
条件注释 |
MySQL 特有(与版本/关键字解析相关) |
不同数据库对白字符支持不同(示意):
| 数据库 |
空白字符(十六进制) |
| SQLite3 |
0A, 0D, 0C, 09, 20 |
| MySQL5 |
09, 0A, 0B, 0C, 0D, A0, 20 |
| PostgreSQL |
0A, 0D, 0C, 09, 20 |
| Oracle 11g |
00, 0A, 0D, 0C, 09, 20 |
| MSSQL |
01..1F, 20(范围较多) |
防护侧建议:
- 在应用层对输入进行空白归一化(所有空白折叠为单个空格或直接拒绝)。
- 关键字段(如
id、page、sort)坚持强类型白名单,不允许出现任何空白字符。
3)括号、引号、大小写混合等“语法等价变体”
SQL 关键字通常大小写不敏感,括号、引号也会改变解析方式或拼接边界。对防护而言,重点不是记住多少变体,而是:
- 不要依赖黑名单拦截(例如仅拦
select、union 的字符串匹配)。
- 优先使用参数化查询 + ORM 安全 API,把“语法构造权”交回给驱动层。
0x03 MySQL:易受影响点与加固方向
MySQL 方言特性多、兼容性强,导致“同一语义,多种写法”非常常见。与其追逐变体,不如从工程角度做加固。
1)函数/表达式的等价替换:为什么 WAF 容易漏
函数名、比较方式、字符串拼接方式的等价替换,会让基于关键字的规则失效。例如:
- 字符串长度、截取、编码转换、连接字符串、版本/库信息、延时函数、比较函数等,都可能存在替代写法。
防护侧建议:
- 对输入做语法级解析(AST)再判定风险(能力不足时,至少做规范化+参数化)。
- 数据库账号最小权限:线上账号不应具备读取敏感系统表/写文件等权限。
2)注释与关键字分割:过滤与解析不一致
当过滤器以“连续关键字”作为命中条件时,注释插入会造成识别失败。工程上应避免“只做字符串 contains 判断”。
防护侧建议:
- 统一把注释剔除后再检测(注意:剔除过程必须严格,避免被构造绕过)。
- 业务层对 SQL 片段零拼接:不要让用户输入参与列名、排序字段、where 片段。
3)报错与时间侧信道:别让异常成为信息通道
无论是报错回显还是延时差异,本质上都是“把数据库内部状态泄漏给外部”。
防护侧建议:
- 生产环境关闭详细错误回显,统一错误码与提示文案。
- 对接口做超时与速率限制,避免被利用放大时间差。
- 对异常 SQL 频率做监控与告警,可到 安全/渗透/逆向 版块查阅更多防护与检测讨论。
0x04 SQLite:轻量但不等于“安全默认”
SQLite 常见于移动端、本地缓存、小型服务。由于它经常和“拼接 SQL 字符串”一并出现,风险并不低。
1)函数差异与语法特性
SQLite 的函数集合、字符串拼接方式与部分数据库不同。工程上最常见的问题是:
- 以为某些函数不可用就“安全了”,但攻击面可能转移到其他表达式能力上。
- 本地数据库若被注入,仍可能造成数据泄露与业务逻辑被绕过。
防护侧建议:
- 不论 SQLite/MySQL,统一使用参数化接口。
- 不让外部输入拼接到 SQL 关键结构(表名/列名/排序)。
2)关键字大小写与注释分割
SQLite 同样存在关键字大小写不敏感等行为。只靠关键字黑名单很脆弱。
0x05 Access:绕过变体少,但“老系统”风险更集中
Access 常见于历史系统或特定企业内网应用。绕过方式未必花哨,但两个问题很突出:
- 老代码更容易存在字符串拼接。
- 错误处理、权限隔离往往更薄弱。
防护侧建议:
- 尽快完成数据库与驱动升级/迁移;短期内至少加上参数化与输入白名单。
- 对后台管理端、内网系统同样上 WAF/网关策略,不要“内网裸奔”。
0x06 特定环境:编码、服务器解析与参数拼接风险
“绕过”很多时候不是数据库的锅,而是Web 服务器、框架、网关对输入的解析差异导致的。
常见风险点(概念级):
- IIS 对特定 Unicode/编码形式的解析差异
- ASP/IIS 对特殊符号的兼容处理
- Nginx + PHP 链路中的空白、分隔符、解码顺序差异
- 二次解码导致的“前面看起来安全,后面变危险”
- HTTP 参数污染(同名参数多次出现)导致的拼接/取值差异
防护侧建议(工程可落地):
- 统一参数取值策略:同名参数出现多次时,明确取第一个/最后一个/直接拒绝。
- 网关与应用一致的解码规则:避免一个解码、一个不解码。
- 记录规范化前与后的输入:便于定位攻击与误拦截。
- 对数据库相关话题与加固实践,也可在 数据库/中间件/技术栈 做专题沉淀与复盘。
0x07 写在最后:别只问“怎么绕过”,先问“为什么会被绕过?”
如果你的防护策略仍然依赖“拦几个关键字、挡几个符号”,那么遇到解析差异、编码差异、语法等价变体时,就会天然处于被动。
更可靠的路线通常是:
- 参数化查询:从根源消灭拼接语义。
- 强类型与白名单:让输入只能是业务允许的形态。
- 统一规范化:过滤、检测、日志基于同一份 canonical 输入。
- 最小权限与错误收敛:不给报错/延时侧信道机会。

推荐延伸阅读与交流:如需更多防护落地案例,可到 云栈社区 结合实际业务场景进行讨论与排障。