hacktricks/pentesting-web/postmessage-vulnerabilities/blocking-main-page-to-steal-postmessage.md

3.4 KiB

Bloquear la página principal para robar postmessage

Aprende hacking en AWS desde cero hasta experto con htARTE (HackTricks AWS Red Team Expert)!

Ganando RCs con Iframes

Según este informe de Terjanq los blobs creados desde orígenes nulos están aislados por razones de seguridad, lo que significa que si mantienes ocupada la página principal, la página del iframe se ejecutará.

Básicamente, en ese desafío se ejecuta un iframe aislado y justo después de que se cargue, la página padre va a enviar un mensaje post con la bandera.
Sin embargo, esa comunicación postmessage es vulnerable a XSS (el iframe puede ejecutar código JS).

Por lo tanto, el objetivo del atacante es permitir que el padre cree el iframe, pero antes de que la página padre envíe los datos sensibles (bandera) mantenerla ocupada y enviar el payload al iframe. Mientras el padre está ocupado, el iframe ejecuta el payload que será algún JS que escuchará el mensaje postmessage del padre y filtrará la bandera.
Finalmente, el iframe ha ejecutado el payload y la página padre deja de estar ocupada, por lo que envía la bandera y el payload la filtra.

Pero, ¿cómo podrías hacer que el padre esté ocupado justo después de generar el iframe y solo mientras espera a que el iframe esté listo para enviar los datos sensibles? Básicamente, necesitas encontrar una acción asincrónica que puedas hacer que el padre ejecute. Por ejemplo, en ese desafío, el padre estaba escuchando los postmessages de esta manera:

window.addEventListener('message', (e) => {
if (e.data == 'blob loaded') {
$("#previewModal").modal();
}
});

Entonces era posible enviar un número entero grande en un postmessage que será convertido a cadena en esa comparación, lo cual tomará algo de tiempo:

const buffer = new Uint8Array(1e7);
win?.postMessage(buffer, '*', [buffer.buffer]);

Y para ser preciso y enviar ese postmessage justo después de que se cree el iframe pero antes de que esté listo para recibir los datos del padre, necesitarás jugar con los milisegundos de un setTimeout.