Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2026-8389 — 针对CVE-2026-8389的技术分析和概念验证漏洞利用,该漏洞是Firefox中SpiderMonkey BaselineJIT的类型混淆漏洞,通过字节码截断和异常展开操控进行演示。 | Kitploit
工具/GitHubGitHub/crixpwn/cve-2026-8389
漏洞分析漏洞利用Web应用程序漏洞利用CTF学习与教育二进制利用
GitHubcrixpwn/cve-2026-8389

CVE-2026-8389

针对CVE-2026-8389的技术分析和概念验证漏洞利用,该漏洞是Firefox中SpiderMonkey BaselineJIT的类型混淆漏洞,通过字节码截断和异常展开操控进行演示。

查看仓库
40723个月前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CVE-2026-8389

此漏洞原计划在 Pwn2Own 2026 柏林上使用,但在 150.0.3 版本中已被修补。

SpiderMonkey BaselineJIT 在急切的离线程基线编译路径上发生了 pcOffset 位字段截断,导致异常展开期间出现错误但在边界内的字节码 pc,进而引发类型混淆。

摘要

RetAddrEntry 将字节码偏移量 pcOffset_ 存储为 28 位位字段。同头文件中定义的常量 BaselineMaxScriptLength = 0x0fffffff 大小正好匹配该位字段的范围。

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

在修复之前,这个上界只在发布版本中的 CanEnterBaselineJIT (js/src/jit/BaselineJIT.cpp) 内强制执行,这是预热/OSR 主线程入口路径。急切的离线程基线编译路径没有经过这个检查,因此字节码超过 256 MB 的脚本可以清除基线编译,而其 pcOffset 被 28 位存储 (pcOffset & 0x0FFFFFFF) 静默截断。上述两个信息性 MOZ_ASSERT(pcOffset_ == pcOffset 和 pcOffset <= BaselineMaxScriptLength)在发布版本中是空操作,所以截断未被检测到。

受影响路径

急切的离线程基线编译路径:

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

补丁前,MaybeDoEagerBaselineCompilations 仅以 script->baselineDisabled() 和 jit::CanBaselineInterpretScript(script) 作为门控条件。两者均未验证脚本长度,因此超长脚本可通过此路径进入基线编译。

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

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

相比之下,主线程路径强制执行了该界限(此代码块后来被移入共享函数 CanBaselineCompileScript):

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

后果

被截断的 pcOffset 通过 JSScript::offsetToPC 在 JSJitFrameIter::baselineScriptAndPc 中转换回字节码指针,经由 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_);
}

该 pc 被传递给异常处理器 HandleExceptionBaseline。由于截断后的偏移量小于实际脚本长度,offsetToPC 返回一个在边界内但错误的 pc,因此该失败是静默的,而非明显的越界崩溃。

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

错误的 pc 会导致异常展开过程中 try-note 匹配错误(HandleExceptionBaseline 依赖于 script->trynotes()),进而引发错误的栈槽读取。一个本不是 JSObject* 的槽位可能被视为 JSObject*,并通过其虚函数表进行分发,从而产生类型混淆,为后续利用奠定基础。

下载工具