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
Herramientas/GitHubGitHub/sneakynachos/cve-2026-84118-who-labeled-the-crit-as-a-high
Forensia de MemoriaAnálisis de VulnerabilidadesExplotaciónSeguridad WebExplotación de Binarios
GitHubsneakynachos/cve-2026-84118-who-labeled-the-crit-as-a-high

CVE-2026-84118-who-labeled-the-crit-as-a-high

Ver Repositorio

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 →

Acerca de

Prueba de concepto para CVE-2026-84118, un use-after-free en el GC de SpiderMonkey que conduce a una lectura/escritura fuera de límites y a una posible ejecución de código. Incluye un desencadenante determinista de SEGV e investigación sobre la escalada a lectura arbitraria y la anulación de ASLR.

1hace 11 horasAún no revisado
Compartir

CVE-2026-84118 — Use-after-free en el GC de SpiderMonkey (Bug 2057457)

Este es uno de esos casos en los que Mozilla etiquetó una Critical como High. Así que alguien podría querer que Firefox actualice el pago a los cazadores de bugs originales si ese es el caso.

EL TLDR: Puedes hacer una primitiva R OOB sobre un puntero controlado y luego empezar a subir y bajar desde ese puntero. Así que si apuntas el puntero controlado a un array, enhorabuena, puedes hacer cosas divertidas.

El POC solo tiene la parte del SEGV, así que el resto es una aventura divertida de apuntar a un array y saltar al WASM que elijas.

Prueba de concepto determinista de SEGV en build de release para Firefox/SpiderMonkey 154.0.1. Corregido en 155 (rework de AtomMarking). Severidad Mozilla: HIGH.

Ejecutando el PoC

root@kitploit:~
/path/to/release/js poc.js

Reproducido en 154.0.1: 3/3 en un shell optimizado simple (SIGSEGV, exit 139), 5/5 en un shell de release+gczeal, fallo idéntico en cada ejecución:

root@kitploit:~
SEGV en la dirección 0x000000000014 (READ)
JS::shadow::Zone::gcState()  <- zone == nullptr, offset +0x14

Causa raíz

154 confunde los bitmaps de marcado de átomos por zona con el seguimiento de referencias. Un Symbol mantenido solo débilmente — aquí, capturado como un campo Value débil dentro de un stub IC CacheIR de Baseline — y referenciado desde una zona no recolectada nunca se vuelve a marcar cuando la zona de átomos se recolecta en un GC con ámbito de zona. El resultado es un borde obsoleto hacia una celda barrida/desplazada.

El golpe letal en build de release es un segundo bug estático: MightBeForwarded<JS::Symbol> está hardcodeado como false, así que IsForwarded devuelve false sin comprobar (gc/Marking-inl.h:92-97) y cada ruta de corrección de punteros que depende de ello omite silenciosamente el borde. Cuando la zona de átomos se compacta, los bordes fuertes se actualizan correctamente, pero este borde CacheIR débil queda permanentemente colgando en la dirección antigua del Symbol víctima. (Los builds de debug lo detectan como Assertion failure: !t->isForwarded(), gc/Marking-inl.h:94.)

Cómo el PoC convierte el borde colgante en un SEGV

El PoC no solo deja un puntero obsoleto a heap reutilizable — consigue que la página subyacente sea desmapeada (munmapped), de modo que la siguiente desreferencia falla.

  1. Aislamiento de chunks por zona. Los pools de chunks del GC son por zona (Zone::availableChunks/fullChunks), así que los chunks de la zona de átomos contienen solo arenas de la zona de átomos. El destino de un chunk puede controlarse puramente por las vidas de átomos/symbols.
  2. Grooming del heap. 300 Symbols "imán" (mantenidos vivos) ocupan un chunk temprano y sirven como destino de la compactación. 150.000 Symbols desechables llenan entonces ~4 chunks nuevos de 1 MB, de modo que el Symbol víctima aterriza en medio del spray en un chunk que contiene solo symbols de spray condenados.
  3. El baile del symbol mantenido débilmente (líneas 21-31, frágil a nivel de bytecode — debe permanecer verbatim): c.eval(b) hace que el IC de llamada de nivel superior capture el Symbol en un campo de stub débil; b = undefined suelta la última raíz fuerte; el spray se suelta; dos GCs con ámbito de zona (gc("zone"), schedulezone(c) + schedulezone("") + gc("zone") — la cadena vacía programa la zona de átomos) barren el spray muerto, compactan la víctima en la arena de imanes, omiten la corrección del borde débil, y liberan la arena de la víctima. Su chunk ahora está completamente vacío.
  4. munmap. gcparam("minEmptyChunkCount", 0) hace que cada chunk vacío sea expirable; durante sleep(0.5) la BackgroundDecommitTask ejecuta -> -> — un munmap real del chunk víctima. (El decommit a nivel de arena es solo — ceros legibles — la liberación de chunks completos es la única ruta de munmap, por eso el aislamiento de chunks del paso 1 importa.)

Más allá del crash de página nula

Esto no es solo un DoS. Escaladas demostradas (PoCs y logs en los directorios de investigación GC-NDAY/ y CHAIN/):

  • Dirección de fallo elegida por el atacante (segv9): después del munmap, un cambio de semiespacio de minorgc() hace que la nursery reclame la VA liberada; un spray crudo de dobles densos escribe un qword del atacante sobre el campo zone del header de la arena obsoleta. El barrido entonces desreferencia attacker_ptr + 0x14 — determinista 3/3 en 0x424242424256.
  • Control del veredicto + lecturas repetibles: el valor cargado selecciona el veredicto de liveness del borde débil; un veredicto "LIVE" mantiene el borde colgante y lo vuelve a desreferenciar en cada GC mayor posterior (lecturas elegidas por el atacante
    • un oráculo observable por script de 1 bit). Un veredicto "DEAD" se auto-cura.
  • Cadena de dos bugs: un js::Zone* real filtrado a través de un canal lateral especulativo separado fue plantado mediante este relleno; el recolector consumió los metadatos de arena falsificados sin fallar (una planta de control perturbada en 1 bit crashea), demostrando la composición derrota-de-ASLR -> planta-de-UAF.
  • Negativo acotado: el fakeobj directo a través de esta familia de stubs está bloqueado arquitectónicamente — la compactación corrige los bordes fuertes correctamente, solo los bordes débiles quedan colgando, y sus consumidores de barrido son solo de ramas.
Descargar herramienta
expireEmptyChunkPool
FreeChunkPool
UnmapPages
madvise(MADV_DONTNEED)
  • La desreferencia que falla. El gc() final barre datos JIT: sweepJitDataOnMainThread -> ICEntry::traceWeak -> TraceWeakCacheIRStub lee el puntero Symbol obsoleto, y luego SweepingTracer::onEdge (gc/Marking.cpp:3195) realiza aritmética de chunks sobre la dirección obsoleta para cargar el campo zone del header de la arena. La página ha desaparecido/está a ceros, así que zone == nullptr, y zone->isGCSweeping() lee nullptr + 0x14 (shadow::Zone::gcState) -> SIGSEGV. En el fallo, rcx contiene el puntero Symbol obsoleto y rdx la base del chunk desmapeado.