Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
CVE-2026-15718-who-put-ptrs-in-my-wasm — Cadena de exploit PoC para CVE-2026-15718: array.fill sin sincronizar en el compilador baseline de wasm de SpiderMonkey -> puntero no válido -> addrOf/fakeobj -> R/W arbitrario -> RCE | Kitploit
Herramientas/GitHubGitHub/sneakynachos/cve-2026-15718-who-put-ptrs-in-my-wasm
Análisis de VulnerabilidadesExplotaciónIngeniería InversaSeguridad WebDesarrollo de PayloadsExplotación de Binarios
GitHubsneakynachos/cve-2026-15718-who-put-ptrs-in-my-wasm

CVE-2026-15718-who-put-ptrs-in-my-wasm

Cadena de exploit PoC para CVE-2026-15718: array.fill sin sincronizar en el compilador baseline de wasm de SpiderMonkey -> puntero no válido -> addrOf/fakeobj -> R/W arbitrario -> RCE

Ver Repositorio
1hace 1 díaAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

CVE-2026-15718 — quién metió punteros en mi wasm

Cadena de exploits de prueba de concepto para CVE-2026-15718, una mala compilación por falta de sync() en el compilador baseline de WebAssembly de Mozilla SpiderMonkey (componente «JavaScript: WebAssembly»). Un único array.fill de cero iteraciones produce una primitiva fakeobj; la cadena escala a lectura/escritura arbitraria del proceso anfitrión y ejecución arbitraria de código nativo (posix_spawnp("/bin/sh", ...)).

  • CVE: CVE-2026-15718 (CWE-763, liberación de un puntero no válido)
  • Afectados: Firefox < 152.0.6, Firefox ESR < 140.13, Thunderbird < 140.13
  • Corregido en: Firefox 152.0.6 / ESR 140.13 / Thunderbird 140.13, 2026-07-14
  • Bug upstream: Mozilla Bug 2045443 (MFSA-2026-67)
  • Commit de la corrección: 4441102e62e8 («Bug 2045443», una línea)

Causa raíz

BaseCompiler::emitArrayFill() () emite el bucle de relleno de sin llamar primero a :

js/src/wasm/WasmBaselineCompile.cpp
array.fill
sync()
root@kitploit:~
   if (elementType.isRefRepr()) {
     freePtr(RegPtr(PreBarrierReg));
   }

+  sync();
+
   // Perform the fill loop using `numElements` as the loop variable ...

sync() vacía la pila de valores (stk_) del compilador baseline, moviendo los registros a la pila de la máquina. La barrera posterior imprecisa de cada iteración del bucle de relleno (emitPostBarrierEdgeImprecise) llama a sync() internamente, pero solo si el bucle se ejecuta. La etiqueta de salida del bucle (done) es un punto de unión de dos caminos:

  • el bucle se ejecutó al menos una vez (elementos reftype): stk_ está sincronizado; cada operando vive en un slot de la pila de la máquina;
  • cero iteraciones (numElements == 0): stk_ no se toca; los operandos siguen viviendo solo en registros.

El modelo estático del compilador tras la unión siempre refleja el camino sincronizado, por lo que el código emitido después de array.fill lee operandos de slots de pila que una ejecución de cero iteraciones nunca escribió. Un operando reftype leído de esta forma es un puntero no válido (obsoleto) (CWE-763).

Primitiva: técnica del slot plant/read

La desincronización es bidireccional entre dos funciones wasm con marcos idénticos:

  • plant (n = 1, el bucle se ejecuta): el sync() interno escribe un valor en el slot — un ref real (addrOf) o un i64 controlado (montaje de fakeobj);
  • read (n = 0, cero iteraciones): el slot nunca se escribe; la función gemela lee el slot obsoleto — como i64 (fuga) o como (ref $t) (fakeobj).

Cadena del exploit (poc/)

FileStageResult
poc-min.js (+ gen_trigger.py)demo de desincronizaciónel camino de control devuelve el valor correcto; el camino de cero iteraciones devuelve un puntero basura leído del slot que nunca se escribió
chain.js (+ gen_chain.py, chain.tpl.js, build.sh)cadena completaaddrOf + fakeobj → WasmArrayObject falso → R/W arbitrario → fuga de la base de XUL → recorrido de importaciones Mach-O en tiempo de ejecución → funcref forjado → posix_spawnp("/bin/sh", ["-c", "touch /tmp/CVE-2026-15718-PWNED"])

Detalles de las etapas en chain.js:

  1. plantSpray/plantCmd/plantFun/plantExt + leak — addrOf para arrays wasm, funcrefs y objetos JS (externref).
  2. sprayV + fakeRd/fakeWr — fakeobj; WasmArrayObject falso (numElements_ @+16, data_ @+24, elementos inline @+40) con la ventana falsa mantenida en un array fuera de línea (asignado con malloc) para que el GC no pueda moverlo a mitad del escaneo.
  3. Filtrar la entrada nativa de una JSFunction (+0x20), escanear hacia atrás página a página buscando la magia Mach-O (0xfeedfacf) → base de XUL.
  4. Resolución de símbolos totalmente dinámica: recorrer los comandos de carga Mach-O de XUL mediante la lectura arbitraria (LC_SEGMENT_64/LC_SYMTAB/LC_DYSYMTAB + tabla de símbolos indirectos) para localizar la entrada __stubs de _posix_spawnp. Sin offsets hardcodeados; el stub realiza el lazy binding en la primera llamada.
  5. Forjar un funcref (typeDef @+0x40 copiado de un ref.func real, destino de llamada @+0x38 = dirección del stub) e invocarlo mediante call_ref con posix_spawnp(pid, "/bin/sh", 0, 0, [sh, -c, cmd], 0).

Ejecución

Probado con un xpcshell (o el shell js / navegador) compilado a partir de un árbol anterior a 152.0.6 (la build de referencia aquí es Firefox 149.0a1, 2026-01-14):

root@kitploit:~
# minimal desync demo
xpcshell poc/poc-min.js

# full chain (regenerates chain.js from the template + generator)
(cd poc && sh build.sh)
rm -f /tmp/CVE-2026-15718-PWNED
xpcshell poc/chain.js    # creates /tmp/CVE-2026-15718-PWNED
ls -l /tmp/CVE-2026-15718-PWNED

El harness establece javascript.options.wasm_optimizingjit=false para fijar el nivel baseline durante el largo escaneo Mach-O (el bug es solo del baseline; en el navegador el trigger se ejecuta muy por debajo del umbral de tier-up, por lo que no es necesario allí). tools/xul_slots.py es un validador offline que lista los slots stub/GOT con nombre de XUL (se utiliza para contrastar el recorrido en tiempo de ejecución).

Notas de portabilidad

Los offsets corresponden a macOS arm64, este árbol/build exacto (WasmArrayObject { +16 numElements, +24 data_, +40 inline }, JSFunction nativa @ +0x20, WasmFuncRef { +0x38/+0x48 destino de llamada, +0x40 typeDef }). Todos se re-derivan en tiempo de ejecución mediante los auto-tests de la cadena; solo se asumen los diseños de las estructuras. No hay preocupaciones de PAC (XUL es un binario arm64, no arm64e); el stub de lazy binding resuelve el destino en la primera llamada, por lo que no se necesitan offsets de la caché compartida de dyld.

Alcance / limitaciones honestas

Este PoC se ejecuta en un proceso de shell sin sandbox. En un ataque real a Firefox, la cadena aterriza dentro del proceso de contenido, donde la sandbox de macOS deniega posix_spawnp; se necesita un bug independiente de escape de la sandbox del SO para un compromiso completo (véase, p. ej., el análisis de la etapa 2 en CVE-2026-2796-and-CVE-2026-2768-escape-the-wasm-box).

Mitigaciones

  • Actualizar a Firefox / Thunderbird ≥ 152.0.6 (ESR ≥ 140.13).
  • Defensa en profundidad: javascript.options.wasm=false bloquea el vector del trigger.

Referencias

  • MFSA-2026-67
  • NVD: CVE-2026-15718
  • Corrección: https://github.com/mozilla-firefox/firefox/commit/4441102e62e8

Descargo de responsabilidad

Solo para investigación de seguridad, educación y pruebas defensivas. La vulnerabilidad está parcheada en las versiones actuales de Firefox/Thunderbird. No lo utilices contra sistemas que no poseas o para los que no tengas autorización explícita de prueba.

Descargar herramienta