绕过Cloudflare WAF的反射型XSS漏洞挖掘实战

发布时间:2026/7/4 10:27:11
绕过Cloudflare WAF的反射型XSS漏洞挖掘实战 1. 项目概述当XSS遇上Cloudflare WAF在Web安全领域跨站脚本攻击XSS算得上是“元老级”的漏洞了但时至今日它依然是漏洞赏金计划Bug Bounty和渗透测试中的常客。原因很简单只要应用存在动态内容渲染且对用户输入处理不当XSS就有机可乘。然而随着Cloudflare这类云安全服务商的普及直接、赤裸的XSS Payload往往在到达服务器之前就被其Web应用防火墙WAF无情地拦截了。这给漏洞挖掘者带来了新的挑战你的对手不再仅仅是开发者的代码逻辑还有一个时刻在云端分析流量特征的“智能守卫”。我最近在一次针对某个远程协作平台为保护项目隐私我们姑且称之为“RDP项目”的授权测试中就遇到了这个经典的攻防场景。目标主站防护严密但在对其一个用于文档预览的子域名进行测试时我嗅到了一丝机会。最终我不仅发现了一个反射型XSS漏洞更关键的是成功绕过了Cloudflare WAF的检测规则。这个过程与其说是一次简单的漏洞发现不如说是一场与WAF规则引擎的“猫鼠游戏”。今天我就把这次挖掘之旅的完整思路、技术细节和绕过技巧拆解开来希望能给同样在WAF“铜墙铁壁”下寻找突破口的同行们一些启发。2. 核心思路从信息收集到WAF特性分析2.1 目标锁定与攻击面测绘任何有效的漏洞挖掘都始于精准的信息收集。对于RDP项目我的第一步是进行全面的子域名枚举。使用像subfinder、amass这样的工具配合多个公共DNS数据集和证书透明度日志我很快拉出了一张目标资产清单。在快速浏览和初步访问后一个名为preview.rdp-project.com的子域名引起了我的注意。它的功能很明确接收一个文档ID或URL参数然后渲染一个预览页面。这类“参数化内容渲染”的功能点天生就是反射型XSS的温床。注意在进行任何测试前确保你拥有目标的明确授权。未经授权的测试是违法的。本文所有技术讨论均在合法授权的安全评估范围内进行。初步的手工测试很快印证了我的猜想。我在URL参数中尝试插入经典的scriptalert(1)/script页面原样输出了这段字符串但并没有弹窗。查看页面源代码发现我的输入被直接放在了HTML正文的某个div里。这是一个典型的反射点但为什么没执行检查响应头果然看到了X-XSS-Protection: 0现代浏览器已弃用此头但这是一个线索更重要的是没有明显的输出编码痕迹。问题可能出在WAF上——我的Payload在到达应用逻辑前就被过滤了。2.2 Cloudflare WAF行为初探为了验证是Cloudflare在起作用我设计了几次探测请求基础探测发送script标签。结果请求被正常响应Payload被原样显示无弹窗。这说明应用本身没有过滤但浏览器未执行。WAF触发探测发送更明显的恶意Payload如scriptprompt(1)/script或包含javascript:协议。结果有时会收到Cloudflare的拦截页面HTTP 403有时则不会。这种不一致性很有趣说明WAF规则并非铁板一块它有触发阈值和上下文判断。大小写与混淆测试尝试ScRiPt、script 多余空格。发现大小写变异通常能绕过基础检测但复杂的标签事件如onerror很容易触发拦截。通过这一系列探测我初步总结了该Cloudflare WAF策略的几个特点基于正则和语义它不仅仅匹配script字符串还会解析HTML标签结构识别常见的事件处理属性。有状态检测单个可疑参数可能放行但请求中多个参数同时存在恶意特征时触发拦截的概率大增。对某些上下文不敏感当Payload出现在特定的HTML标签属性内或者被某些字符分割时WAF的检测可能会失效。基于这些观察我的绕过策略从“硬碰硬”改为“迂回渗透”核心思路是寻找WAF规则集与浏览器HTML解析器之间的差异。3. 漏洞挖掘与绕过实战一场解析差异的博弈3.1 寻找脆弱的反射上下文反射型XSS的成功利用高度依赖于用户输入被嵌入到HTML文档的哪个位置即“上下文”。常见的上下文有HTML正文div用户输入/divHTML标签属性值未引号或引号闭合input value用户输入或input value用户输入JavaScript字符串内scriptvar a 用户输入;/scriptURL上下文a href用户输入链接/a通过仔细分析preview子域名的页面我确认用户控制的参数被直接插入到了一个div标签的内部即HTML正文上下文。这看起来是最容易利用的因为我可以直接注入HTML标签。但Cloudflare WAF正是针对这种直接注入做了强力防护。我的突破口来自于对响应内容的进一步审视。我注意到页面为了展示预览信息会动态生成一些包含数据的span标签。那么我的输入有没有可能被嵌入到某个标签的属性里呢我尝试了如下Payload onmouseoveralert(1)。如果输入点在一个属性值内并且属性没有正确用引号闭合这个Payload就能逃出属性范围创建一个新的onmouseover事件处理器。发送请求后WAF没有拦截。查看页面源码发现我的输入被放在了类似div>