2025年了,还在用UA伪装、单层编码去直接撞WAF,大概率会撞得头破血流。我今年在给某客户的Web应用做授权评估时,最值得重视的方向反而是标题里的白名单绕过——不是跟WAF正面对抗,而是先把它放行的通道摸清楚,再从通道里构造载荷。这篇文章把我在实战中积累的完整思路、步骤和踩坑记录下来,适合已经有一定渗透测试基础、想在授权项目里提升效率的从业者。所有内容均基于已签署授权协议的模拟目标,请勿对未授权系统使用。
1. 项目定位与2025年WAF绕过的实际变局
1.1 为什么白名单绕过成了高级渗透测试的主线
过去几年很多团队还在研究怎么把攻击载荷伪装得更像正常流量,但2025年的主流云WAF和商业WAF在规则引擎和语义分析上已经迭代了好几轮。直接构造SQL注入或XSS载荷,哪怕做三层编码,被拦截的概率也非常高。我在实际测试中发现,真正容易出问题的地方,反而是“白名单”构建的逻辑边界。
所谓白名单,通常指WAF或业务网关对某些流量不做检测,比如IP白名单、路径白名单、参数白名单、认证后的接口白名单。设计初衷是降低误报、保证业务连续性,但实际开发配置时,白名单往往被写得太宽、太模糊,形成了一个独立的攻击面。高级渗透测试之所以能低成本穿透,靠的不是更花哨的载荷,而是先摸清哪些通道被放行了,然后在放行通道里做文章。
1.2 2025年WAF检测机制的变化要点
现在的WAF不再单纯依赖正则特征库,很多已经引入语义分析、请求上下文建模和动态基线学习。这意味着旧一套“用随机字符串打断特征词”的做法效果下滑。但从另一个角度看,语义分析模型通常只覆盖认为“可能有风险”的流量,对标记为白名单的请求往往直接放行,甚至跳过解码流程。这恰恰给白名单绕过留出了空间。
我归纳出2025年比较值得关注的WAF检测机制变化:
- 规则引擎从正则匹配转向特征+语义混合分析,精确度提升但计算开销大。
- 对完整二进制协议体(如multipart、JSON、XML)的解析存在复用盲区,不同组件对同一报文的理解不同。
- 云WAF经常只对默认80/443端口流量做深度检测,对非标端口或内部域名往往宽松。
- 白名单IP、内部UA、特定路径前缀、HTTP头标记是常见的“放行后门”。
这些背景决定了白名单绕过的实战策略:与其硬碰检测模型,不如先找逻辑豁免。下面我详细拆解整个项目的设计思路和具体操作。
2. 核心攻击面分析与绕过思路梳理
2.1 白名单到底“白”在哪里:六类常见豁免面
在项目里,我习惯把白名单分成六类,分别对应不同的利用姿势:
| 白名单类型 | 常见配置位置 | 典型绕过思路 |
|---|---|---|
| IP白名单 | WAF规则、防火墙策略 | 寻找可以伪造来源IP的入口,或利用边缘节点/代理转发 |
| 路径白名单 | WAF URL匹配规则 | 利用路径规范化差异、编码差异、大小写差异绕过URL匹配 |
| 参数白名单 | 业务WAF规则、网关配置 | 通过参数污染、同名参数、数组参数绕过字段级检测 |
| UA/Header白名单 | 自研WAF、反爬模块 | 伪造内部UA或特定业务Header,直接获得放行 |
| 认证后白名单 | 网关、业务逻辑层 | 利用低权限账号访问本应受控的管理接口 |
| 文件类型白名单 | 上传组件、网关 | 双扩展名、大小写扩展名、分号截断、特殊字符解析差异 |
每种类型的核心都不是“怎么构造复杂载荷”,而是“确认WAF不会对这个通道做检测”。拿路径白名单举例,真实的配置往往是/api/health/*这类前缀匹配,但开发者大概率不会去想过/api/health/../admin这种路径规范化问题。等到请求经过WAF时是健康检查路径,到达后端时却变成了管理接口路径,检测自然被完全跳过。
2.2 绕过思路的核心:协议解析差异
在我做过的模拟项目中,绝大多数白名单绕过都能归类为“WAF解析请求的方式”和“后端应用解析请求的方式”不一致,也就是协议解析差异。这个思路比单纯研究载荷特征重要得多。
比如WAF从请求行读取URL为/api/health/../admin时,经过路径规范化后可能判断它属于/api/health/前缀,于是放行。而Nginx或Tomcat在接收同一URL时,会先做路径拼接,再交给应用路由,实际命中的却是/admin。这类差异就是白名单绕过的核心原理。
再比如参数解析差异。WAF如果读取username=admin&password=123,把password识别为普通参数做注入检测;但应用框架如果支持数组参数username=admin&password[]=123或username=admin&password=123&password=456,取到的参数内容与WAF看到的不一致,检测自然失效。这就是为什么现代绕过测试里“参数混淆”越来越重要。
2.3 项目初始信息收集:目标画像与指纹识别
正式测试前,我不管思路多清晰,都会先做足信息收集。这一步能直接决定后续绕过的成功率和效率。我的标准流程包括以下几项:
- 识别WAF类型和版本,判断是否存在已知绕过路径。商业WAF版本更新频繁,但有部分规则的解析差异一直没修复。
- 确认流量入口是云WAF、硬件WAF还是自研规则引擎。不同类型对应不同的绕过难度。
- 寻找后端技术栈,确认应用框架、中间件版本,这决定了解析差异的利用方式。
- 记录正常业务流量特征,区分基线流量与被白名单豁免的流量。
- 测试若干已知路径是否直接返回“放行”标志,比如在URL后加
?或#,观察响应是否仍被WAF拦截。
经验里最容易踩的坑是只依赖自动化指纹工具,忽略手动测试。很多自研WAF通过改写响应头、生成随机token来混淆指纹,工具识别完全不准。我对每个目标都会手工构造一个无害请求,比如/index?id=1,然后逐步加入典型特征词,观察拦截比例,这样反而能得到最真实的检测强度画像。
3. 关键技术解析与实操要点
3.1 编码类绕过:从基础到容易被忽视的高级用法
编码绕过是最基础的手段,但2025年在白名单场景里依然有效,关键在于时机。如果WAF把某个路径判定为白名单后直接放行,你就不需要编码;如果参数值还没被完全豁免,就需要判断WAF解码顺序与后端解码顺序的差异。
最基本的几种:
- URL双重编码:
%2527,WAF先解一次得到%27,后端再解一次得到单引号。 - Unicode规范化:
/、s这类全角/半角字符,后端在做标准化时可能转成正常ASCII。 - HTML实体编码:适用于XSS检测绕过,
<经过解析变成<。 - JSON/XML嵌套编码:WAF只做浅层解码,后端框架却会自动解析多层嵌套结构。
但真正值得用的是“编码叠加路径差异”。比如目标路径既被当作白名单又被后端做二次解码,我可以构造一个白名单前缀,后面跟双重编码的管理路径。WAF看到的是/api/health/ok,后端解码后实际访问的是/admin%2Fconsole。这种手法比单纯替换编码符号有效得多。
3.2 分块传输与报文歧义利用
分块传输编码(Chunked Transfer Coding)是绕过WAF的经典手法,2025年仍然有效,但要做得更细。原理很简单:WAF是一个独立中间件,它不一定按照完整的报文语义去重组块,尤其是经过代理链时,块边界处理可能不一致。
实际操作中,我会用两种方式制造歧义:
- 分块大小故意写错。部分解析器严格按十六进制长度读取,另一部分解析器遇到格式错误会直接读取剩余所有内容。于是WAF看到的是一小段无害数据,后端看到的是完整攻击载荷。
- 在块扩展字段里塞入垃圾数据。很多组件对
Chunked-Encoding的处理存在容错差异,垃圾数据可能让WAF提前终止解析,直接跳过检测。
这项技术需要大量试错,因为不同组件对Chunked实现差异极大。我在模拟项目里,靠构造一系列无效块大小,最后让后端拼接出完整恶意载荷,而WAF全程没有触发任何规则。但有一个前提:目标必须支持HTTP/1.1且关闭了强制HTTP/2。如果目标是HTTP/2,分块传输这条路基本走不通,就得换成连接合并或报文走私的思路。
3.3 参数污染与参数分裂的高级玩法
参数污染(HPP)在OWASP里面属于API安全常见问题,但在WAF绕过场景里,它和白名单有很强的结合空间。如果WAF的规则只检测特定参数名,而业务框架允许同名参数共存且取最后一个值或拼接所有值,就存在完整的绕过链路。
举个例子,目标接口是/search?keyword=正常词,WAF对keyword参数做SQL注入检测,但放行query参数。我尝试提交keyword=正常词&query=恶意载荷,WAF只检查了keyword,后端却同时读取了query并拼进SQL查询。有些框架甚至会把keyword和query的所有值合并成一个数组再交给业务逻辑,这又增加了利用面。
参数分裂则关注数组格式与嵌套格式:id[0]=正常&id[1]=恶意,WAF如果只按字符串处理id参数,根本不会去检查括号里的内容。后端框架如果支持复杂参数绑定,就会直接解析出两个值。2025年大多数主流框架对复杂参数支持度都很高,这给测试者提供了很大的操作空间。
3.4 路径规范化与大小写混淆的组合拳
路径规范化是我个人最偏爱的绕过方式,因为它的逻辑足够清晰,而且后端中间件的路径处理规则相对稳定。Nginx、Tomcat、Jetty之间对../、//、/.、%2e%2e的处理存在细微差别。WAF在做白名单前缀匹配时用的是未规范化路径,而后端在路由前做了规范化,就形成绕过。
常见的路径变体包括:
- 目录穿越式:
/api/health/../../admin - 双斜杠式:
//api//health///admin - 点号截断:
/api/health/./admin - 编码斜杠:
/api/health%2f..%2fadmin - 分号参数:
/api/health/;/admin
加上大小写混淆可以进一步提高成功率,比如/API/Health/../Admin。有些WAF规则是大小写敏感的,后端中间件却默认大小写不敏感,这种组合在真实项目里命中率相当不低。我在一次授权测试里,就是用/Api/Health/%252e%252e/Admin这种形态打穿了路径白名单。
3.5 从检测引擎的语义模型漏洞入手
2025年的WAF虽然引入语义分析,但语义模型通常是基于AST(抽象语法树)或局部语法规则,对超长表达式、重复嵌套、注释插入的容忍度有限。这里的绕过策略不再是简单加注释符号,而是破坏模型对语句结构的完整判断。
比如SQL注入,部分语义模型把UNION SELECT当作一个强信号,但把它拆成UN/**/ION/**/SE/**/LECT后,模型无法在解码结果里还原原始token,就会放行。这本质上是让WAF的“理解”与后端SQL解析器的“理解”产生偏差。XSS也是类似,模型看到<svg/onload=...>会拦截,但看到<svg/onload = ...>或<svg/onload=/**/...>可能就判定为合法属性。
这类手法的核心前提,还是目标处于“非严格白名单”流量里。如果WAF对整条路径都放行,语义分析完全不会被触发,我会直接跳过编码装饰,用原始载荷打进后端,这样才能获得最稳定的结果。测试时务必按“先确认放行,再逐步降低编码复杂度”的顺序操作。
4. 实操流程与核心环节实现
4.1 识别白名单边界:从被动观察到主动探测
实操里的第一步不是直接打载荷,而是找到白名单的确切边界。我一般先做被动观察,查阅目标网站的JS文件、移动端接口、历史URL,找出开发者主动声明的公开路径,比如/help、/status、/version。然后进入主动探测阶段,针对每一个候选路径,构造典型恶意特征词变量,观察拦截结果。
以某模拟项目为例,我知道目标有/api/health路径,就先请求/api/health?q=or 1=1,发现返回正常结果,说明该路径确实不在WAF检测范围。再从路径前缀列表里测试/api/health_extra和/api/health/../等变体,逐步确认白名单边界是精确匹配还是前缀匹配。大多数情况是前缀匹配,这给后续利用留了很大空间。
4.2 结合解析差异构造有效载荷
确认白名单边界后,就要决定用哪类解析差异。如果后端是Nginx,我会优先测试路径规范化;如果后端是Spring系列,就会往参数污染方向走。在构造有效载荷时,我坚持“先简后繁”原则。
第一轮直接使用最简形态,比如/api/health/../admin,目标是确认后端是否解析到被管控路径。如果后端返回404或302,至少说明路径被识别了;如果直接返回200,那说明权限校验本身就有问题。第二轮再叠加编码,比如/api/health/%2e%2e/admin、/api/health/..%2fadmin,通过响应差异判断后端解码次数。
这种做法能有效区分“WAF放行但后端不解析”和“WAF放行且后端正常解析”两种情况。很多初学者喜欢一上来就使用复杂编码组合,最后无法判断到底是哪一层出了问题。
4.3 实战案例:从路径白名单到管理接口
为了把流程说透,我整理一段模拟项目中的完整过程。目标是一个带云WAF的Web应用,信息收集发现/manage后台存在管理接口,但只能从内网访问。WAF明确配置了/manage的拦截规则,直接访问会弹出验证页面。
我继续探测其他路径,发现/api/health完全放行。于是尝试/api/health/../manage,返回302跳到登录页,但WAF没有再拦截。继续尝试/api/health/..%2f..%2fmanage,后端将其解析为/manage,直接返回后台管理页面。整个过程中WAF看到的都是健康检查路径,完全没有触发防护规则。
4.4 分块传输绕过在模拟目标上的执行过程
另一个项目里,目标WAF对keyword参数做了基于语义的注入检测。我决定尝试Chunked方式。先用Burp Suite把请求改为Transfer-Encoding: chunked,把原始载荷切分后分发到多个chunk中,并在chunk size字段里插入额外数据。
第一轮发送时,WAF直接把请求判定为“非法分块”并返回400。第二轮我把第二个chunk的大小字段故意从5改成0x5,部分解析器接受十六进制格式,WAF解析直接出错,流到了后端。后端接受后把多个chunk拼接成完整载荷,成功触发了目标接口的注入点。这个案例说明,同一个报文在不同组件之间的结构理解差异,就是白名单绕过的最大助力。
4.5 工具与流量构造建议
工具选择上,我一般不用现成的绕过工具,而是自己手工构造。Burp Suite的Repeater足够完成90%的报文修改,剩下10%用Python写一个简单的socket脚本,精确控制分块大小和Header顺序。
很多人容易忽略的一个细节是请求顺序。WAF有时会根据会话状态做检测,比如登录后的接口放行力度更大。因此测试时要确认目标是否要求先登录、先获取cookie或先通过特定Header校验,不然构造的绕过请求可能直接被业务逻辑拒绝,而不是被WAF拦截,容易误判。我的习惯是每次构造请求前,先用浏览器完整走一遍正常业务流,把所有上下文信息抓出来。
5. 常见问题与排查技巧实录
5.1 载荷未被拦截但目标也没有预期响应
这是最常见的情况,很多测试者以为“没被拦截就等于成功”,但实际上后端可能根本没有解析到注入点,或者参数拼接方式与预期不同。我的排查步骤是:
- 确认响应码与响应体变化。如果响应体完全不变,可能是参数名不对。
- 检查后端是否对特殊字符做了过滤或转义,导致载荷失效。
- 换用更简单的探测值,如
1和0的差异,确认参数是否进入SQL拼接逻辑。 - 通过时间盲注或布尔盲注验证,而不是只依赖显式输出。
很多时候问题出在“WAF放行”和“后端可达”之间还有一层应用层编码处理。举个例子,后端对输入先做了addslashes(),单引号被转义,单靠WAF绕过没用,还得叠加后端编码层面的处理。
5.2 分块传输全被拦截的问题排查
Chunked失败时,我首先确认目标服务器是否支持HTTP/1.1。开启HTTP/2强制连接后,Transfer-Encoding会被忽略或直接拒绝。其次,检查是否需要在请求头里显式设置Connection: keep-alive,因为部分代理链会关闭长连接导致报文体被重写。
还有一个隐蔽坑:CDN节点可能对分块报文做重新封装,导致后端收到的是已经被重新组包的完整报文,WAF自然能检测到。这种情况下,需要寻找不同CDN边缘节点,或者尝试直接访问源站IP,绕过CDN再做分块测试。
5.3 判断解析差异方向的经验
解析差异方向错了会导致测试完全无效。我通常用“标志性字符”验证解析行为:在URL里放%2e%2e,如果后端返回路径穿越相关结果,说明后端先解码再做路径拼接;如果返回404,说明后端直接按原字符串匹配路径,没有解码过程。这样能快速判断该往哪条路深入。
再比如参数解析,当提交a=1&a=2时,后端如果取第一个值,结果页一般会显示1;取最后一个值则显示2;取数组则入参数组。判断出框架的处理方式后,再构造与之匹配的载荷,成功率会显著提升。
5.4 排查中容易忽略的传输层问题
绕过技术本身没问题,但请求被其他安全设备拦截也经常发生。有些目标在WAF前还有一层IPS或服务器防火墙,对畸形请求、超长URL、异常Content-Type直接丢弃。遇到这种情况,我会先用一个完全合法的请求确认通路,再逐步增加畸形程度,看哪一步开始异常。这个二分法能快速定位拦截层。
另外,请求大小也是隐藏变量。部分设备只检测包体前几千字节,把载荷放在包体末尾有可能绕过检测;反过来,也有设备对超大包直接放行以减轻压力。构造请求时故意把包体膨胀到几MB,然后观察响应时延和拦截结果,往往能探索出防护设备的检查上限。
6. 防御侧加固思路与个人总结
6.1 从攻击视角看白名单配置的正确姿势
看了这么多绕过手法,再回头看防御,最核心的一条:白名单不能只是路径或参数的简单排除。正确做法是把白名单控制在最小粒度,比如精确匹配健康检查路径/api/health,而不是前缀匹配/api/health/*;同时对放行请求做二次校验,确认来源IP、User-Agent、请求内容长度都在合理范围。关键是白名单放行之后,后端依然要做权限校验,不能跳过认证和鉴权。
6.2 验证白名单安全性的自查方案
我建议每个企业安全团队定期做一次“白名单视角”测试,即站在攻击者角度,梳理所有被WAF放行的路径和参数,然后逐一测试与后端路由的真实差异。这个自查可以复用本文提到的路径规范化、参数污染、Chunked三种基础手法。如果白名单里存在任何路径能通过../访问到其他接口,就应该立即收紧规则并立即修复后端路由逻辑。
更稳妥的方式是把白名单流量镜像到日志分析系统里,对内容做脱敏检测。就算WAF不检查,后置的安全分析还是能看到异常模式。
6.3 为什么WAF不是安全终点
我做了大量绕过测试后最深的体会是,WAF是安全防护的一部分,不是终点。白名单绕过之所以能成功,很多情况下不是WAF太弱,而是应用层对请求的理解偏差、后端接口权限校验缺失、运维配置过度放行这几个因素叠加的结果。把重点放在后端验证、日志监控和接口最小化权限上,比单纯升级WAF规则有效得多。
6.4 最后再分享一个小技巧
测试白名单绕过时,尽量在请求里保留原始业务参数的骨架,只替换其中一部分。这能让WAF的语义分析模型认为流量与正常业务高度相似,还能让后端日志看起来合理。我在多个项目里用这个方法明显减少了触发告警的次数。但切记测试结束后要清理所有测试数据,并向目标团队提交详细的修复建议,这才是一次完整且负责任的授权渗透测试。