
Vollständige Firefox-Kette: CVE-2026-2796 wasm-Typverwechslung -> RCE im Content-Prozess, plus CVE-2026-2768 Analyse des Parent-Prozess-Escapes (beide in Firefox 148 behoben)
Firefox-Exploitation-Forschung zur vollständigen Angriffskette: eine WebAssembly-Typverwechslung für Codeausführung im Renderer, verkettet mit einem Bug im Parent-Prozess für einen Sandbox-Escape. Beide Bugs wurden in Firefox 148 (MFSA-2026-13) behoben; das Ziel hier ist ein Firefox-148-Nightly-Tree @ 2fbc0748c4 (2026-01-14), der aus der Zeit vor beiden Fixes stammt.
page loads crafted wasm module
│
CVE-2026-2796: Function.prototype.call.bind unwrap skips signature check
│ → i64 ↔ (ref $t) confusion → addrOf/fakeobj
│ → fake WasmArrayObject → arbitrary R/W in the CONTENT process
│ → forged WasmFuncRef → hijack call target ([funcref+0x38])
▼
native code exec INSIDE the sandboxed content process (sbLevel 3)
│ (sandbox blocks exec/fork — need a parent bug)
▼
CVE-2026-2768: forge IndexedDB add/put IPC with out-of-range
mAutoIncrementKeyOffsets (ParamTraits<Key> validates nothing)
│ → parent writes 8 bytes at attacker-controlled offset
▼
memory corruption in the UNSANDBOXED parent process = full escape
| Demo | Wo | Ergebnis |
|---|---|---|
poc/shell/poc-crash.js | js shell | 0xDEADBEEF als Funcref dereferenziert → SIGSEGV bei 0xdeadbf2f |
poc/shell/poc-addrof.js | js shell | Selbsttests für beliebiges R/W bestehen |
poc/shell/poc-forge.js | js shell | PC-Kontrolle: Absturz an platzierter Canary |
poc/shell/poc-rce.js | js shell | system("id > /tmp/CVE-2026-2796-PWNED; open -a Calculator") — Datei enthält uid=501(sid) ..., Calculator öffnet sich |
poc/browser/stage1-browser.html | Nightly (sbLevel 3 content) | beliebiges R/W im sandboxierten Tab; gefälschter Funcref springt zu 0x4141414141414141 → Tab stürzt ab, Parent überlebt |
poc/browser/stage1-browser-cmd.html | Nightly (sbLevel 3 content) | leakt die XUL-Basis, löst posix_spawnp auf (0x187xxxxx) und ruft posix_spawnp mit /bin/sh -c "touch /tmp/PWNED-FROM-CONTENT" auf → macOS-Sandbox verweigert den Exec: Datei wird nicht erstellt, Seite unbeschädigt — Beweis, dass Content-RCE allein ≠ Befehlsausführung ist |
poc/browser/sandbox-proof.html | Nightly (sbLevel 3 content) | nativer Exec innerhalb der Sandbox-Regeln: getpid() liefert die echte PID des Tabs (stimmt mit ps überein), und rohes libc-write(1, ...) landet im Terminal-Log des Browsers — kein Fork/Exec, keine Dateiöffnungen |
poc/browser/fd3-proof.html | Nightly (sbLevel 3 content) | schreibt 32 rohe Bytes auf fd 3 (den IPDL-Socket des Parents): der IPC-Parser des Parents verarbeitet Angreifer-Bytes (Message needs unreceived descriptors ... num_handles:33), verwirft die Nachricht und killt den Tab ("Exiting due to channel error") — die Transport-Primitive, die Stufe 2 mit wohlgeformten, aber bösartigen IndexedDB-Nachrichten als Waffe einsetzt |
poc/browser/stage2-trigger.html | Nightly |
Siehe docs/full-escape.md für die Root-Cause-Analyse von Stufe 2 (Fix-Diffs, IPC-Serialisierung, Exploitation-Strategie).
# Tree: mozilla-firefox/firefox @ 2fbc0748c4 (2026-01-14, pre-FF148)
# 1) js shell (stage-1 development, unsandboxed):
cd js/src && ../../configure --enable-debug --enable-optimize \
--without-intl-api --enable-project=js && cd _obj && make -j8
# 2) full browser (stage 2). mozconfig:
# export CC=/usr/bin/clang ; export CXX=/usr/bin/clang++
# ac_add_options --enable-application=browser
# ac_add_options --disable-debug --enable-optimize
# ac_add_options --disable-crashreporter --disable-updater --disable-tests
# ac_add_options --enable-sandbox
# ac_add_options --without-wasm-sandboxed-libraries
# requires: node, cbindgen, rustc >= 1.87, macOS CLT SDK
# local build notes:
# - private header sys/fileport.h shim added to objdir dist/include/sys/
# - one compile guard added: NSGlassEffectView (macOS 26 SDK symbol) wrapped
# in #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 260000 in widget/cocoa/
# nsCocoaWindow.mm (build-environment fix, no security impact)
Browser-PoCs ausführen: obj-browser/dist/Nightly.app mit einem Profil
starten, das browser.dom.window.dump.enabled=true setzt, die HTML-Dateien
über file:// öffnen und stdout nach dump()-Ausgabe beobachten. Ein
Tab-Absturz erscheint als process <pid> exited on signal 10 im Parent-Log.
WasmArrayObject: numElements @+16, data ptr @+24, inline data @+40.
WasmFuncRef: typeDef ptr @+0x40, call target @+0x38. JSFunction-Native-
Pointer @+0x20. js shell: os_system @ base+0x1a9f8, system GOT @
base+0x11d47b0. Browser: XUL-Basis, gefunden durch Zurückscannen von einem
nativen WebIDL-Code-Pointer (console.log-JSFunction +0x20) bis zur
0xfeedfacf-Mach-O-Magic; _posix_spawnp GOT @ XUL+0x9bb7d30, _getpid
GOT @ XUL+0x9bb7600, _write GOT @ XUL+0x9bb87e0. Fake-Array-Fenster müssen
in einem Out-of-Line-Array (malloc'd) leben — Inline-/Nursery-Objekte werden
bei langen Scans vom GC verschoben.
Die Codeausführung im Renderer über CVE-2026-2796 ist vollständig demonstriert (Shell und Browser). Die Sandbox-Escape-Analyse von CVE-2026-2768 ist quellcode-verifiziert gegen den Fix-Diff; der Live-End-to-End-Trigger für die Parent-Korruption ist noch in Arbeit (siehe Doku). Diese Forschung ist für defensive/lehrreiche Zwecke gedacht; die Schwachstellen sind in aktuellen Versionen gepatcht.
e2acef67c5dea6ecNur für Sicherheitsforschung, Ausbildung und defensive Tests. Nicht gegen Systeme verwenden, die man nicht besitzt oder für die man keine ausdrückliche Genehmigung zum Testen hat.
Erreichbarkeit des Parent-Bug-Pfads in reinem JS (Auto-Increment-Index-Keys [1,2,3,4]) |