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-8389 | Kitploit
Herramientas/GitHubGitHub/crixpwn/cve-2026-8389
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebCTFAprendizaje y EducaciónExplotación de Binarios
GitHubcrixpwn/cve-2026-8389

CVE-2026-8389

Ver Repositorio
407hace 2 mesesRevisado por Kitploit

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-8389

Esta vulnerabilidad estaba prevista para ser utilizada en Pwn2Own 2026 Berlín, pero fue parcheada en la versión 150.0.3.

Truncamiento del campo de bits pcOffset de SpiderMonkey BaselineJIT en la ruta de compilación baseline anticipada fuera del hilo principal, lo que produce un pc de bytecode incorrecto pero dentro de los límites durante el desenrollado de excepciones y una confusión de tipos posterior.

Resumen

RetAddrEntry almacena el desplazamiento de bytecode pcOffset_ como un campo de bits de 28 bits. La constante BaselineMaxScriptLength = 0x0fffffff, definida en el mismo encabezado, tiene un tamaño que coincide exactamente con el rango de ese campo de bits.

root@kitploit:~
// js/src/jit/BaselineJIT.h:73
static constexpr uint32_t BaselineMaxScriptLength = 0x0fffffffu;

// js/src/jit/BaselineJIT.h:100-105
class RetAddrEntry {
  // Offset from the start of the JIT code where call instruction is.
  uint32_t returnOffset_;

  // The offset of this bytecode op within the JSScript.
  uint32_t pcOffset_ : 28;
root@kitploit:~
// js/src/jit/BaselineJIT.h:141-156 (RetAddrEntry constructor)
RetAddrEntry(uint32_t pcOffset, Kind kind, CodeOffset retOffset)
    : returnOffset_(uint32_t(retOffset.offset())),
      pcOffset_(pcOffset),
      kind_(uint32_t(kind)) {
  MOZ_ASSERT(returnOffset_ == retOffset.offset(),
             "retOffset must fit in returnOffset_");

  // The pc offset must fit in at least 28 bits, since we shave off 4 for
  // the Kind enum.
  MOZ_ASSERT(pcOffset_ == pcOffset);
  static_assert(BaselineMaxScriptLength <= (1u << 28) - 1);
  MOZ_ASSERT(pcOffset <= BaselineMaxScriptLength);

  MOZ_ASSERT(kind < Kind::Invalid);
  MOZ_ASSERT(this->kind() == kind, "kind must fit in kind_ bit field");
}

Antes del parche, este límite superior solo se aplicaba en las compilaciones de lanzamiento dentro de CanEnterBaselineJIT (js/src/jit/BaselineJIT.cpp), que es la ruta de entrada del hilo principal para warmup / OSR. La ruta de compilación baseline anticipada fuera del hilo principal no pasaba por esa comprobación, por lo que un script cuyo bytecode superara los 256 MB podía completar la compilación baseline mientras su pcOffset se truncaba silenciosamente en el almacenamiento de 28 bits (pcOffset & 0x0FFFFFFF). Los dos MOZ_ASSERTs informativos anteriores (pcOffset_ == pcOffset y pcOffset <= BaselineMaxScriptLength) son no-ops en las compilaciones de lanzamiento, por lo que el truncamiento pasaba desapercibido.

Ruta afectada

La ruta de compilación baseline anticipada fuera del hilo principal:

root@kitploit:~
CompilationStencil::instantiateStencils
  -> MaybeDoEagerBaselineCompilations        (js/src/frontend/Stencil.cpp:2720)
    -> DispatchOffThreadBaselineBatchEager    (js/src/jit/BaselineJIT.cpp:386)
      -> BaselineCompileTask::runTask         (js/src/jit/BaselineCompileTask.cpp:69)
        -> BaselineCompile

Antes del parche, MaybeDoEagerBaselineCompilations solo dependía de script->baselineDisabled() y de jit::CanBaselineInterpretScript(script). Ninguna de las dos valida la longitud del script, por lo que un script demasiado largo podía llegar a la compilación baseline a través de esta ruta.

root@kitploit:~
// js/src/frontend/Stencil.cpp, MaybeDoEagerBaselineCompilations (pre-patch)
    if (script->baselineDisabled()) {
      continue;
    }

    if (!jit::CanBaselineInterpretScript(script)) {
      continue;
    }

En cambio, la ruta del hilo principal sí aplicaba el límite (este bloque se movió después a la función compartida CanBaselineCompileScript):

root@kitploit:~
// js/src/jit/BaselineJIT.cpp, CanEnterBaselineJIT (pre-patch)
  if (script->length() > BaselineMaxScriptLength) {
    script->disableBaselineCompile();
    return Method_CantCompile;
  }

Consecuencia

El pcOffset truncado se vuelve a convertir en un puntero de bytecode en JSJitFrameIter::baselineScriptAndPc, a través de RetAddrEntry::pc -> JSScript::offsetToPC.

root@kitploit:~
// js/src/jit/JSJitFrameIter.cpp:155-160
  // address.
  uint8_t* retAddr = resumePCinCurrentFrame();
  const RetAddrEntry& entry =
      script->baselineScript()->retAddrEntryFromReturnAddress(retAddr);
  *pcRes = entry.pc(script);
}
root@kitploit:~
// js/src/jit/BaselineJIT.h:162-164 (RetAddrEntry::pc)
jsbytecode* pc(JSScript* script) const {
  return script->offsetToPC(pcOffset_);
}

Ese pc se entrega al manejador de excepciones HandleExceptionBaseline. Como el desplazamiento truncado es menor que la longitud real del script, offsetToPC devuelve un pc dentro de los límites pero incorrecto, por lo que el fallo es silencioso en lugar de un crash evidente por fuera de rango.

root@kitploit:~
// js/src/jit/JitFrames.cpp:584-591
static void HandleExceptionBaseline(JSContext* cx, JSJitFrameIter& frame,
                                    CommonFrameLayout* prevFrame,
                                    ResumeFromException* rfe) {
  MOZ_ASSERT(frame.isBaselineJS());
  MOZ_ASSERT(prevFrame);

  jsbytecode* pc;
  frame.baselineScriptAndPc(nullptr, &pc);

Ese pc incorrecto provoca una coincidencia errónea de las try-notes durante el desenrollado de excepciones (HandleExceptionBaseline se basa en script->trynotes()), lo que conduce a una lectura incorrecta de una ranura de la pila. Una ranura que no es un JSObject* puede entonces tratarse como tal y despacharse a través de su vtable, produciendo una confusión de tipos que sirve de base para una explotación posterior.

Descargar herramienta