声明: 文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由用户承担全部法律及连带责任,文章作者不承担任何法律及连带责任。
在漏洞众测的世界里,耐心往往是最关键的胜负手。一个看似毫无价值的初步发现,经过深度挖掘,完全可能演变为一个危害巨大的严重漏洞。今天分享的案例,就讲述了一位国外白帽黑客如何将一个超出项目接收范围的简单发现,通过持续学习和精巧的WAF绕过技术,最终升级为CVSS评分9.3的高危反射型XSS漏洞的完整过程。
第一章:起点——一个超出范围的漏洞与严苛的WAF
故事的起点在去年12月中旬。这位白帽小哥正在参与一个政府部门的漏洞披露项目(我们姑且称之为 target.com)。在对某个接口进行测试时,他发现 q.LIKE 这个参数存在有趣的特性:用户的输入内容会直接、未经过滤地回显在网页上。
经过简单测试,他确认这里可以实现HTML注入。但紧接着就遇到了第一个障碍:该项目的规则白纸黑字地写明,单纯的HTML注入属于超出漏洞接收范围的发现,不会被受理。这意味着,如果他想成功提交报告并获得认可,就必须将这个注入点升级为能够执行任意代码的跨站脚本(XSS)漏洞。
于是,他尝试输入最简单的测试载荷:<script>alert(1)</script>。结果毫不意外——被拦截了。目标站点部署了防护规则极其严密的AWS WAF。更棘手的是,这套WAF配备了严格的惩罚机制:一旦检测到恶意载荷,就会将发起请求的IP地址封禁整整5分钟。当时,小哥还没有掌握IP轮换的技巧,在这种“手动测试五分钟,封禁等待五分钟”的循环下,有效测试根本无法开展。
研究似乎走进了死胡同。但这位小哥并没有沮丧地关掉页面,而是选择了一个聪明的做法:他保留了这个浏览器标签页,转身投入了新技能的学习。
第二章:沉淀——两个半月的学习与提升
在接下来的两个半月里,那个承载着希望与障碍的标签页一直静静地躺在浏览器中,保持着打开状态。这段时间,小哥集中精力钻研高阶的XSS利用技巧与绕过方法。更重要的是,他系统学习了如何在Burp Suite中配置和使用IP轮换(IP Rotation)功能。
掌握了这项技能后,WAF那烦人的5分钟封禁机制终于不再是不可逾越的障碍。小哥摩拳擦掌,准备以全新的姿态,重新对那个“老对手”发起挑战。
第三章:测试——从PortSwigger学来的方法论
带着新学的知识,小哥按照从PortSwigger Web安全学院汲取的思路,开始对目标WAF进行系统性的探测。这个过程就像是在和WAF玩一场“猜猜我允许什么”的游戏。
步骤1:HTML标签模糊测试
首先需要探明WAF的“白名单”——它究竟允许哪些HTML标签通过?小哥将请求发送到Burp Suite的Intruder模块,使用一个包含 <svg>、<body>、<a>、<video> 等常见标签的列表进行模糊测试。WAF的规则果然严密,绝大多数标签都被无情拦截。然而,测试结果显示,唯独 <video> 标签被放行了。这是第一个突破口。
步骤2:事件处理器模糊测试
光有标签还不够,我们需要让这个标签“动”起来,执行JavaScript。小哥再次祭出Burp Intruder,这次的目标是<video>标签内部可能存在的各种JavaScript事件处理器,例如 onload、onerror、onplay 等。

几乎所有的常规事件处理器都触发了WAF的拦截规则(返回403状态码)。但列表中有一个“异类”返回了 200 OK:onwebkitpresentationmodechanged。WAF的开发者显然仔细过滤了那些标准事件,却遗漏了这个WebKit浏览器内核(主要为Safari浏览器使用)独有的、用于处理画中画模式变化的事件。第二个关键拼图找到了。
第四章:绕过——终极Payload的构造
现在,小哥手上有可用的标签(<video>)和可触发的事件(onwebkitpresentationmodechanged),接下来就需要构造能够成功执行的JavaScript代码了。
但WAF的检测并未结束,它依然在监控代码内容。直接写入 window.location 或 javascript:alert(1) 这样的语句会立刻被识别并拦截。为了绕过这种基于关键词的检测,小哥使用了经典的字符串拼接技巧:将被拦截的关键词拆分成无害的片段,让WAF的规则引擎无法匹配。
例如,不直接写 window.location,而是写成:window['loca' + 'tion']。
为了让整个攻击链更加隐蔽和强大,小哥还运用了 window.name 属性传递Payload的技巧。攻击者可以先创建一个恶意页面,将真正的恶意代码(如 javascript:alert(document.domain))赋值给 window.name,然后诱导受害者从该页面跳转到存在漏洞的URL。
最终的绕过方案和攻击链如下:
- 攻击者准备:创建一个恶意页面,执行
window.name = “javascript:alert(document.domain)”。
- 诱导跳转:该页面将受害者重定向到存在漏洞的目标URL,携带精心构造的参数。
- 注入载荷:成功注入的Payload结构大致如下:
...<video/controls/src="..."/onwebkitpresentationmodechanged="window['loca'+'tion']=window['na'+'me']"></video>...
- 触发执行:当受害者使用Safari浏览器访问该页面,视频开始播放或触发画中画模式变化时,
onwebkitpresentationmodechanged 事件被触发。
- 代码执行:事件处理器中的代码
window['loca'+'tion']=window['na'+'me'] 被执行。这等同于 window.location = window.name,从而跳转并执行隐藏在 window.name 中的恶意JavaScript代码。

结论与思考
小哥将包含完整绕过细节和复现步骤的报告提交到了漏洞平台。平台的研判团队经过验证,确认该WAF绕过手法有效,并将此漏洞评定为高危(Critical)级别,给出了CVSS 9.3的高分,最终予以收录并奖励。
经验总结:
这个故事给我们上了生动的一课:
- 永不放弃边缘发现:如果一个漏洞初步看来“超出范围”或“低危”,不要轻易放弃。思考它是否可能成为更严重漏洞的跳板。
- 对抗WAF需要耐心与技巧:遇到强大的WAF拦截时,硬碰硬往往无效。适时暂停,学习新的绕过技术和工具(如IP轮换),会让你在回来时更具优势。
- 保持探索状态:就像那位小哥一样,永远不要轻易关掉那个可能蕴藏机会的浏览器标签页。持续学习和积累,是安全研究员最宝贵的财富。
这个案例也启示我们,Web安全的攻防是一场持续的动态博弈。防御方需要不断更新规则以覆盖小众特性和新型绕过手法,而攻击方则在不断寻找规则盲区。对于开发者而言,除了依赖WAF,实施严格的输出编码和内容安全策略(CSP)才是根本的解决之道。
原文参考:https://medium.com/@housien.a.khalek19/escalating-an-out-of-scope-html-injection-to-a-critical-9-3-xss-waf-bypass-12b194d6a1df