
Chaîne d'exploitation Firefox complète : CVE-2026-2796 confusion de types wasm -> RCE dans le processus de contenu, plus CVE-2026-2768 analyse d'évasion du processus parent (tous deux corrigés dans Firefox 148)
Recherche d'exploitation Firefox en chaîne complète : une confusion de type WebAssembly pour l'exécution de code dans le processus de rendu, enchaînée vers un bug du processus parent pour une évasion du sandbox. Les deux bogues ont été corrigés dans Firefox 148 (MFSA-2026-13) ; la cible ici est un arbre Firefox 148-nightly @ 2fbc0748c4 (2026-01-14), qui précède les deux correctifs.
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
| Démo | Où | Résultat |
|---|---|---|
poc/shell/poc-crash.js | js shell | 0xDEADBEEF déréférencé comme funcref → SIGSEGV à 0xdeadbf2f |
poc/shell/poc-addrof.js | js shell | lecture/écriture arbitraire — auto-tests OK |
poc/shell/poc-forge.js | js shell | contrôle du PC : crash sur le canary placé |
poc/shell/poc-rce.js | js shell | system("id > /tmp/CVE-2026-2796-PWNED; open -a Calculator") — le fichier contient uid=501(sid) ..., Calculator s'ouvre |
poc/browser/stage1-browser.html | Nightly (contenu sbLevel 3) | lecture/écriture arbitraire dans l'onglet sandboxé ; un funcref forgé saute à 0x4141414141414141 → l'onglet plante, le parent survit |
poc/browser/stage1-browser-cmd.html | Nightly (contenu sbLevel 3) | fuite de la base XUL, résout posix_spawnp (0x187xxxxx), l'appelle avec /bin/sh -c "touch /tmp/PWNED-FROM-CONTENT" → le sandbox macOS refuse l'exécution : fichier non créé, page intacte — preuve que la RCE du contenu seule ≠ exécution de commande |
poc/browser/sandbox-proof.html | Nightly (contenu sbLevel 3) | exécution native dans les règles du sandbox : getpid() renvoie le vrai PID de l'onglet (correspond à ps), et un write(1, ...) brut de libc atterrit dans le journal du terminal du navigateur — pas de fork/exec, pas d'ouverture de fichier |
poc/browser/fd3-proof.html | Nightly (contenu sbLevel 3) | écrit 32 octets bruts sur fd 3 (la socket IPDL du parent) : le parseur IPC du parent consomme des octets de l'attaquant (Message needs unreceived descriptors ... num_handles:33), abandonne le message et tue l'onglet (« Exiting due to channel error ») — la primitive de transport que l'étape 2 transforme en arme avec des messages IndexedDB bien formés mais malveillants |
poc/browser/stage2-trigger.html | Nightly | atteignabilité en pur JS du chemin du bug parent (clés d'index auto-incrémentées ) |
Voir docs/full-escape.md pour l'analyse de la cause racine de l'étape 2 (diffs de correctifs, sérialisation IPC, stratégie d'exploitation).
# 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)
Exécutez les PoC navigateur : lancez obj-browser/dist/Nightly.app avec un profil qui définit browser.dom.window.dump.enabled=true, ouvrez les fichiers HTML via file://, surveillez stdout pour la sortie de dump(). Le crash de l'onglet apparaît comme process <pid> exited on signal 10 dans le journal du parent.
WasmArrayObject : numElements @+16, pointeur de données @+24, données inline @+40. WasmFuncRef : pointeur typeDef @+0x40, cible d'appel @+0x38. Pointeur natif JSFunction @+0x20. js shell : os_system @ base+0x1a9f8, GOT de system @ base+0x11d47b0. Navigateur : base XUL trouvée en remontant depuis un pointeur de code natif WebIDL (console.log JSFunction +0x20) jusqu'à la magie Mach-O 0xfeedfacf ; GOT de _posix_spawnp @ XUL+0x9bb7d30, GOT de _getpid @ XUL+0x9bb7600, GOT de _write @ XUL+0x9bb87e0. Les fenêtres de faux tableaux doivent vivre dans un tableau hors-ligne (alloué par malloc) — les objets inline/pépinière sont déplacés par le GC pendant les longues analyses.
L'exécution de code dans le processus de rendu via CVE-2026-2796 est entièrement démontrée (shell et navigateur). L'analyse de l'évasion du sandbox de CVE-2026-2768 est vérifiée au niveau du code source par rapport au diff du correctif ; le déclencheur dynamique de corruption du parent de bout en bout est un travail en cours (voir docs). Cette recherche est destinée à un usage défensif/pédagogique ; les vulnérabilités sont corrigées dans les versions actuelles.
e2acef67 de mozilla-firefox/firefoxc5dea6ec de mozilla-firefox/firefoxPour la recherche en sécurité, l'éducation et les tests défensifs uniquement. Ne pas utiliser contre des systèmes que vous ne possédez pas ou pour lesquels vous n'avez pas d'autorisation explicite de tester.
[1,2,3,4]