Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-8389 | Kitploit
도구/GitHubGitHub/crixpwn/cve-2026-8389
Vulnerability AnalysisExploitationWeb Application ExploitationCTFLearning & EducationBinary Exploitation
GitHubcrixpwn/cve-2026-8389

CVE-2026-8389

저장소 보기
4072개월 전Kitploit 검토 완료

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2026-8389

이 취약점은 Pwn2Own 2026 Berlin에서 사용할 예정이었으나, 버전 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 메인 스레드 진입 경로입니다. 즉시 오프스레드 베이스라인 컴파일 경로는 해당 검사를 거치지 않으므로, 바이트코드가 256MB를 초과하는 스크립트는 pcOffset이 28비트 저장에 의해 조용히 잘리는(pcOffset & 0x0FFFFFFF) 상황에서도 베이스라인 컴파일을 통과할 수 있었습니다. 위의 두 정보 제공용 MOZ_ASSERT(pcOffset_ == pcOffset 및 pcOffset <= BaselineMaxScriptLength)는 릴리스 빌드에서 no-op이므로 잘림 현상은 감지되지 않았습니다.

영향받는 경로

즉시 오프스레드 베이스라인 컴파일 경로:

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은 RetAddrEntry::pc -> JSScript::offsetToPC를 거쳐 JSJitFrameIter::baselineScriptAndPc에서 바이트코드 포인터로 다시 변환됩니다.

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*가 아닌 슬롯이 그런 객체로 취급되어 vtable을 통해 디스패치될 수 있으며, 이는 추가 악용의 기반이 되는 타입 혼동을 발생시킵니다.

도구 다운로드