WAF防护原理与轻量绕过思路 📅 发布时间:2026/9/13 22:51:58 👁 浏览次数: 09-WAF防护原理与轻量绕过思路合法边界声明本篇讨论的绕过思路仅用于两个场景——一是在自建靶场/授权渗透测试中评估防护设备的真实效果二是帮助防守方理解绕过手法从而完善规则。对未授权目标实施任何绕过尝试均属违法行为。WAF 绕过是矛与盾的攻防研究不是攻击教程。一、WAF 是什么放在哪里WAFWeb Application FirewallWeb 应用防火墙与传统的网络层防火墙只看 IP/端口不同它工作在HTTP/HTTPS 应用层检查的是请求的内容语义URL、参数、Header、请求体里有没有攻击特征。按部署形态分三类硬件/软件 WAF反向代理模式串在流量路径上常见为反向代理所有请求先过 WAF干净的才转给后端。代表各类硬件盒子、ModSecurity、安全狗/云锁主机软件型。特点看得见全部流量但自己是性能瓶颈也是单点故障点。云 WAFSaaS 模式把域名 CNAME 接到云厂商流量先过云端清洗再回源。特点接入快、免运维但要求流量真正切过去没切 CNAME 就等于裸奔。RASP运行时应用自我保护严格说不是 WAF它以探针形式插桩进应用进程内部Java Agent / PHP 扩展在函数调用层面看请求。特点能拿到解密后、解码后的最终参数误报低、几乎无法用编码绕过但开销在业务进程里稳定性要谨慎评估。一句话理解三者差异WAF 在门外看信封信封上的字再怎么加密变形它都只看得到表象RASP 在屋里看信纸请求进了应用、解开所有编码后它才检查这决定了绕过 WAF 的核心思想——在信封上做文章让特征变形到 WAF 认不出来但后端解析后还原成攻击载荷。二、WAF 的三类检测原理知己知彼的第一步搞清楚 WAF 到底怎么判断一个请求是恶意的。2.1 规则引擎正则黑名单——绝大多数 WAF 的主力规则形如ModSecurity 经典 SQL 注入规则的思想# 伪规则请求参数中出现 unionselect 组合则拦截 SecRule ARGS (?i)(union(\s|\\|%20)(all(\s|\\|%20))?select) id:1001,deny工作原理对每个请求参数跑一遍规则库商用 WAF 规则上万条命中即按动作处置拦截/告警/打分。优点直观、可解释、性能可控。致命弱点正则匹配的是字符形态不是语义。载荷一旦变形编码、注释、大小写、等价替换正则就可能失明。所以绕过 WAF 的本质就是和正则表达式玩文字游戏。2.2 语义分析部分新一代 WAF对 SQL/DSL 做语法解析AST判断这段输入到底是不是合法 SQL 结构、有没有注入语义。比如1 union select password无论如何变形解析出的语法树都一样正则类绕过手法对它基本失效。弱点性能开销大、覆盖的解析器种类有限SQL 解析得动业务 JSON/GraphQL 里嵌套的语法未必解析得动、仍依赖前置解码与协议解析的正确性。2.3 机器学习/行为模型云 WAF 常见增强基于海量样本训练模型对请求打分结合频率、UA、访问序列等行为特征判断机器人/扫描器。弱点误报率与漏报率的天平难调通常作为辅助打分而不是直接拦截依据。结论先行目前市面上主力仍是规则引擎为主、语义/机器学习为辅。绕过研究的主战场依然是规则引擎的解析差异。三、绕过的总纲解析差异所有绕过手法可以浓缩成一个公式WAF 对请求的理解 ≠ 后端对请求的理解中间的差值就是绕过的空间。这个差值可能产生于编码层WAF 不解或少解一层、协议层WAF 不支持的传输方式、语法层数据库/语言对 SQL/参数的容忍度比 WAF 规则宽、业务层WAF 不知道哪个接口哪个参数才是关键。下面按层展开全部在自建靶场Nginx PHP/MySQL 一款软 WAF或 Vulhub 中的 SQL 注入靶场上验证。3.1 编码与解码差异多层 URL 编码WAF 通常只做一次 URL 解码后端/数据库可能容忍多层。# 原始注入语句1 unionselectuser,password from users--# 单次编码WAF 大概率拦1%27%20union%20select%20user%2Cpassword%20from%20users--%2B# 双重编码部分 WAF 只解一层漏过Tomcat 等容器会二次解码1%2527%2520union%2520select%2520user%252Cpassword%2520from%2520users--%252B解释%25解一次变成%再解一次才变成。WAF 解一层看到的是%27 union ...无单引号特征后端再解一层得到真正的引号——差值产生。十六进制/Unicode 变形-- 字符串用十六进制表示绕过对关键字的字面匹配1unionselect0x75736572-- -- 0x75736572 即 user-- Unicode 编码绕过MySQL 的 utf8 解析1uni%75onselect...-- 部分中间件/数据库解析时还原 u大小写与等价函数-- 大小写混淆1UnIoNSeLeCtuser(),database()-- 等价函数替换WAF 规则盯死了 concat没盯 concat_ws1unionselectconcat_ws(0x7c,user(),database(),version())3.2 注释与空白符变形语法层差异数据库对注释和空白极其宽容而正则规则往往按常见空白写-- 1. 内联注释切割关键字MySQL 特有语法/*! ... */ 内容会被 MySQL 执行1/*!14400union*//*!14400select*/user()-- 2. 注释打断连续特征1union/**/selectuser()1un/**/ion sel/**/ectuser()-- 3. 特殊空白符Tab、换行、%0b 垂直制表符、%a0不间断空格1%0aunion%0bselect%0buser()-- 4. 括号替代空格SQL 里函数调用可以完全无空格1unionselect(user()),(database())解释规则若写成union\sselect\s 匹配普通空白%0b、%a0在部分 WAF 的解码实现里不在\s集合内就漏了而 MySQL 的词法分析认它们是空白。同一个字符两家词法器认识不一致——这就是差值。3.3 传输层与协议差异分块传输编码Chunked Transfer——经典中的经典# burpsuite 手工实践把请求体拆成分块每块几字节WAF 若不组包就看不到完整特征POST /inject.php HTTP/1.1 Transfer-Encoding: chunked3id71 unio5n sel...0解释HTTP 1.1 允许把请求体切成多个 chunk每个 chunk 前标长度。后端 Web 容器Tomcat/Nginx会按协议重组出完整请求体而早期不少 WAF 为了性能只检查了单个 chunk 或根本不处理 chunked 请求体——于是union select横跨多个 chunk特征永远不完整。新版主流 WAF 已支持重组但自建靶场里用旧规则验证原理依然直观。Content-Type 混淆与 multipart# 表单用 text/plain 提交WAF 未按表单解析后端 PHP 依然解析 $_POSTContent-Type: text/plainid1 unionselectuser()--解释WAF 的解析器对application/x-www-form-urlencoded、multipart/form-data、text/plain的解析路径不同。换成 WAF 解析不充分的类型参数可能根本没进检测管线而 PHP 的解析很宽容照样收。multipart 场景同理文件域里藏 payload、boundary 变形都曾让不少 WAF 失明。参数污染HPPHTTP Parameter Pollution# 同名参数出现两次GET /inject.php?id1id2 unionselectuser()--解释HTTP 允许同名参数但不同后端取值策略不同——PHP 取最后一个ASP/ASP.NET 取逗号拼接1,2’ union…JSP 常取第一个。如果 WAF 只检测第一个参数值拿 1干净的后端取的是最后一个带 payload——检测对象与使用对象不一致差值再次产生。HPP 是绕过思路里最能体现架构理解的一个。超长请求/垃圾参数# 在 payload 前塞几十万个垃圾字节aAAAA...(100000个)...id1 unionselectuser()--解释利用 WAF 的性能保护机制——很多 WAF 对超大请求体只检查前 N KB 或直接放行避免拖垮业务payload 藏在 N KB 之后即可通过。这也是评估 WAF 时必测的一项。3.4 业务与逻辑层差异可写参数WAF 规则不理解业务哪些参数最终拼进 SQL 它不知道。找 WAF 没覆盖的冷门入口JSON 接口字段、XML SOAP 报文、排序参数order by、HTTP HeaderX-Forwarded-For 落库的场景、Cookie 中的分页参数……GraphQL/JSON 嵌套深层 JSON 里的注入点很多规则根本没深入解析Header 注入UA/Referer/XFF 写进日志再被二次处理日志型 SQL 注入WAF 只盯参数不盯 Header 之外的字段落点。四、科学评估一台 WAF绕过的正确用途在授权测试/采购评估中绕过思路的正确用法是回答三个问题检测覆盖度用标准化 payload 集如自建靶机上的 SQL/XSS/RCE 样本库打 WAF统计拦截率。重点测上文每一类变形的拦截情况输出绕过矩阵。性能与可用性压测 QPS 下的延迟增加比超长请求、大量参数边界场景的表现误报率拿正常业务报文回放。运维能力规则更新频率、自定义规则灵活性能否按接口精细化白名单、日志检索与告警对接拦没拦得住先不论看得见看不见是底线。一个务实的结论送给甲方不要指望 WAF 拦住所有变形WAF 的定位是挡住扫描器和脚本小子的第一波、给应急响应争取时间。真正的安全底线永远是代码修复 输入输出校验 最小权限。五、防御视角让绕过失效的六层加固攻防对照防守方逐条反制WAF 开启深度解析启用 chunked 重组、multipart 深度解析、多次解码配好解码上限防 DoS、JSON/XML 深层字段检测参数级白名单按接口配置参数名/类型/长度白名单未知参数直接拒绝——让 HPP、垃圾参数、冷门参数全失效统一后端取参策略框架层面禁止重复参数、规范化 Content-Type消灭前后端解析差SQL 预编译是根本WAF 只是缓冲带参数化查询PreparedStatement/ORM 绑定让任何 payload 都只是数据从根上废掉注入纵深布防WAF门外 RASP进程内 数据库审计最后一道任何一层被绕过下一层兜底监控比拦截更重要被绕过的攻击会留下扫描痕迹大量 404、特征变形的参数、频率异常SIEM 告警与 WAF 日志联动“拦不住不代表看不见”。六、小结这一篇没有手把手教你打穿谁而是把 WAF 攻防的底牌摊开原理侧WAF 主力是规则引擎匹配字符形态而非语义这决定了它天生可被绕过绕过侧万变不离解析差异——编码差多层编码、语法差注释/空白/等价函数、协议差chunked/multipart/HPP/超长请求、业务差冷门参数与入口四类手法本质都是在 WAF 与后端的理解差值里藏 payload防御侧WAF 不是银弹定位是缓冲带参数白名单 预编译 RASP 审计的纵深组合才是让绕过研究失去意义的正解。最后提醒一句所有这些手法在靶场里玩得越溜越要清楚它们在真实世界里只有一个合法用途——帮你把自家 WAF 调得更准。下一篇是本系列的收官之作走出靶场复盘真实线上业务的高频漏洞与防御体系聊聊从会复现到能防守的最后一公里。