
Cadena completa de Firefox: CVE-2026-2796 confusión de tipos de wasm -> RCE en el proceso de contenido, más análisis de escape del proceso padre CVE-2026-2768 (ambos corregidos en Firefox 148)
Investigación sobre explotación de Firefox de cadena completa: una confusión de tipos en WebAssembly para ejecución de código en el renderer, encadenada hacia un bug del proceso padre para un escape del sandbox. Ambos bugs se corrigieron en Firefox 148 (MFSA-2026-13); el objetivo aquí es un árbol nightly de Firefox 148 @ 2fbc0748c4 (2026-01-14), anterior a ambas correcciones.
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 | Dónde | Resultado |
|---|---|---|
poc/shell/poc-crash.js | js shell | 0xDEADBEEF desreferenciado como funcref → SIGSEGV en 0xdeadbf2f |
poc/shell/poc-addrof.js | js shell | las autopruebas de R/W arbitrario pasan |
poc/shell/poc-forge.js | js shell | control del PC: crash en el canario plantado |
poc/shell/poc-rce.js | js shell | system("id > /tmp/CVE-2026-2796-PWNED; open -a Calculator") — el archivo contiene uid=501(sid) ..., se abre Calculator |
poc/browser/stage1-browser.html | Nightly (contenido sbLevel 3) | R/W arbitrario en la pestaña con sandbox; el funcref falsificado salta a 0x4141414141414141 → la pestaña crashea, el padre sobrevive |
poc/browser/stage1-browser-cmd.html | Nightly (contenido sbLevel 3) | filtra la base de XUL, resuelve posix_spawnp (0x187xxxxx), la invoca con /bin/sh -c "touch /tmp/PWNED-FROM-CONTENT" → el sandbox de macOS deniega el exec: el archivo no se crea, la página no sufre daños — prueba de que la RCE en el contenido por sí sola ≠ ejecución de comandos |
poc/browser/sandbox-proof.html | Nightly (contenido sbLevel 3) | exec nativo dentro de las reglas del sandbox: getpid() devuelve el PID real de la pestaña (coincide con ps), y la write(1, ...) cruda de libc llega al log de terminal del navegador — sin fork/exec, sin aperturas de archivos |
poc/browser/fd3-proof.html | Nightly (contenido sbLevel 3) | escribe 32 bytes crudos en el fd 3 (el socket IPDL del padre): el parser IPC del padre consume bytes del atacante (Message needs unreceived descriptors ... num_handles:33), descarta el mensaje y mata la pestaña ("Exiting due to channel error") — la primitiva de transporte que la etapa 2 aprovecha con mensajes IndexedDB bien formados pero maliciosos |
poc/browser/stage2-trigger.html | Nightly | verificación de que el camino del bug del padre es alcanzable solo con JS (claves de índice de autoincremento ) |
Consulta docs/full-escape.md para el análisis de causa raíz de la etapa 2 (diffs de corrección, serialización IPC, estrategia de explotación).
# 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)
Ejecuta los PoCs del navegador: lanza obj-browser/dist/Nightly.app con un perfil que establezca browser.dom.window.dump.enabled=true, abre los archivos HTML mediante file://, y observa stdout en busca de la salida de dump(). El crash de la pestaña aparece como process <pid> exited on signal 10 en el log del padre.
WasmArrayObject: numElements @+16, data ptr @+24, inline data @+40.
WasmFuncRef: typeDef ptr @+0x40, call target @+0x38. JSFunction native ptr @+0x20. js shell: os_system @ base+0x1a9f8, system GOT @ base+0x11d47b0. Navegador: la base de XUL se encuentra escaneando hacia atrás desde un puntero de código nativo WebIDL (console.log JSFunction +0x20) hasta la magia Mach-O 0xfeedfacf; GOT de _posix_spawnp @ XUL+0x9bb7d30, GOT de _getpid @ XUL+0x9bb7600, GOT de _write @ XUL+0x9bb87e0. Las ventanas de arrays falsos deben vivir en un array fuera de línea (malloc'd) — los objetos inline/nursery son movidos por el GC durante escaneos largos.
La ejecución de código en el renderer mediante CVE-2026-2796 está completamente demostrada (shell y navegador). El análisis del escape del sandbox de CVE-2026-2768 está verificado contra el diff de la corrección a nivel de código fuente; el disparador en vivo de corrupción del padre de extremo a extremo es un trabajo en curso (ver docs). Esta investigación es para uso defensivo/educativo; las vulnerabilidades están parcheadas en las versiones actuales.
e2acef67 de mozilla-firefox/firefoxc5dea6ec de mozilla-firefox/firefoxSolo para investigación de seguridad, educación y pruebas defensivas. No lo uses contra sistemas que no poseas o para los que no tengas autorización explícita de prueba.
[1,2,3,4]