Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2026-8389 — Análise técnica e exploit de prova de conceito para CVE-2026-8389, uma vulnerabilidade de confusão de tipos no BaselineJIT do SpiderMonkey no Firefox, demonstrada com truncamento de bytecode e manipulação de desenrolamento de exceções. | Kitploit
Ferramentas/GitHubGitHub/crixpwn/cve-2026-8389
Análise de VulnerabilidadesExploraçãoExploração de Aplicações WebCTFAprendizado e EducaçãoExploração de Binários
GitHubcrixpwn/cve-2026-8389

CVE-2026-8389

Análise técnica e exploit de prova de conceito para CVE-2026-8389, uma vulnerabilidade de confusão de tipos no BaselineJIT do SpiderMonkey no Firefox, demonstrada com truncamento de bytecode e manipulação de desenrolamento de exceções.

Ver Repositório
4072há 3 mesesRevisado pelo Kitploit

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

CVE-2026-8389

Esta vulnerabilidade foi projetada para ser usada no Pwn2Own 2026 Berlin, mas foi corrigida na versão 150.0.3.

Truncamento do bitfield pcOffset do BaselineJIT do SpiderMonkey no caminho de compilação baseline ansiosa fora da thread, levando a um pc de bytecode incorreto, mas dentro dos limites, durante o unwind de exceções e a uma subsequente confusão de tipos.

Resumo

RetAddrEntry armazena o offset de bytecode pcOffset_ como um campo de bits de 28 bits. A constante BaselineMaxScriptLength = 0x0fffffff, definida no mesmo cabeçalho, tem tamanho exato para corresponder a esse intervalo do 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 da correção, esse limite superior era aplicado em builds de release apenas dentro de CanEnterBaselineJIT (js/src/jit/BaselineJIT.cpp), que é o caminho de entrada da thread principal para warmup/OSR. O caminho de compilação baseline ansiosa fora da thread não passava por essa verificação, portanto, um script cujo bytecode excedesse 256 MB podia concluir a compilação baseline enquanto seu pcOffset era silenciosamente truncado pelo armazenamento de 28 bits (pcOffset & 0x0FFFFFFF). As duas MOZ_ASSERTs informativas acima (pcOffset_ == pcOffset e pcOffset <= BaselineMaxScriptLength) não têm efeito em builds de release, então o truncamento passou despercebido.

Caminho afetado

O caminho de compilação baseline ansiosa fora da thread:

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 do patch, MaybeDoEagerBaselineCompilations só verificava script->baselineDisabled() e jit::CanBaselineInterpretScript(script). Nenhuma das duas validava o comprimento do script, portanto, um script longo demais chegava à compilação baseline por esse caminho.

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

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

Em contraste, o caminho da thread principal aplicava o limite (esse bloco foi posteriormente movido para o CanBaselineCompileScript compartilhado):

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

Consequência

O pcOffset truncado é convertido de volta em um ponteiro de bytecode em JSJitFrameIter::baselineScriptAndPc, por meio 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_);
}

Esse pc é passado para o manipulador de exceções HandleExceptionBaseline. Como o offset truncado é menor que o comprimento real do script, offsetToPC retorna um pc dentro dos limites, porém incorreto, portanto, a falha é silenciosa em vez de um crash óbvio fora dos limites.

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);

Esse pc incorreto leva a uma correspondência incorreta de try-notes durante o unwind de exceções (HandleExceptionBaseline usa script->trynotes() como chave), resultando em uma leitura incorreta de slot da pilha. Um slot que não é um JSObject* pode então ser tratado como tal e despachado por meio de sua vtable, produzindo uma confusão de tipos que serve de base para exploração adicional.

Baixar ferramenta