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

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

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

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

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-84118-who-labeled-the-crit-as-a-high — CVE-2026-84118에 대한 개념 증명(PoC)으로, SpiderMonkey GC의 use-after-free 취약점으로 인해 경계를 벗어난 읽기/쓰기가 발생하고 잠재적으로 코드 실행이 가능합니다. 결정적 SEGV 트리거와 임의 읽기 및 ASLR 우회로의 권한 상승에 대한 연구를 포함합니다. | Kitploit
도구/GitHubGitHub/sneakynachos/cve-2026-84118-who-labeled-the-crit-as-a-high
Memory ForensicsVulnerability AnalysisExploitationWeb SecurityBinary Exploitation
GitHubsneakynachos/cve-2026-84118-who-labeled-the-crit-as-a-high

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

CVE-2026-84118에 대한 개념 증명(PoC)으로, SpiderMonkey GC의 use-after-free 취약점으로 인해 경계를 벗어난 읽기/쓰기가 발생하고 잠재적으로 코드 실행이 가능합니다. 결정적 SEGV 트리거와 임의 읽기 및 ASLR 우회로의 권한 상승에 대한 연구를 포함합니다.

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유
저장소 보기
111시간 전아직 검토되지 않음

CVE-2026-84118 — SpiderMonkey GC use-after-free (Bug 2057457)

이것은 Mozilla가 Critical을 High로 분류한 사례 중 하나입니다. 그렇다면 누군가 Firefox에 가서 원래 버그 헌터들의 보상을 업데이트하도록 요청하고 싶을 수도 있습니다.

요약: 제어된 포인터에 대해 OOB R 프리미티브를 수행한 다음 해당 포인터를 기준으로 위아래로 이동할 수 있습니다. 제어된 포인터를 배열에 지정하면 재미있는 일을 할 수 있습니다.

PoC에는 SEGV 부분만 있으므로 나머지는 배열을 가리키고 원하는 WASM으로 점프하는 재미있는 모험이 됩니다.

Firefox/SpiderMonkey 154.0.1용 결정적 릴리스 빌드 SEGV 개념 증명. 155에서 수정됨(AtomMarking 재작업). Mozilla 심각도: HIGH.

PoC 실행

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

154.0.1에서 재현: 일반 최적화 셸에서 3/3(SIGSEGV, exit 139), 릴리스+gczeal 셸에서 5/5, 매 실행마다 동일한 오류:

root@kitploit:~
SEGV on address 0x000000000014 (READ)
JS::shadow::Zone::gcState()  <- zone == nullptr, +0x14 offset

근본 원인

154는 영역별 원자 표시 비트맵과 참조 추적을 혼동합니다. 약하게만 유지되는 Symbol — 여기서는 Baseline CacheIR IC 스텁 내부의 약한 Value 필드로 캡처됨 — 이 수집되지 않은 영역에서 참조되는 경우, 영역 범위 GC에서 원자 영역이 수집될 때 다시 표시되지 않습니다. 결과적으로 스윕/재배치된 셀에 대한 오래된 엣지가 남습니다.

릴리스 빌드의 결정적 킬 샷은 두 번째 정적 버그입니다: MightBeForwarded<JS::Symbol>이 false로 하드코딩되어 있어 IsForwarded가 확인 없이 false를 반환하고(gc/Marking-inl.h:92-97), 이를 기반으로 하는 모든 포인터 수정 경로가 엣지를 조용히 건너뜁니다. 원자 영역이 압축되면 강한 엣지는 올바르게 업데이트되지만, 이 약한 CacheIR 엣지는 피해 Symbol의 이전 주소에 영구적으로 매달린 채 남습니다. (디버그 빌드는 Assertion failure: !t->isForwarded(), gc/Marking-inl.h:94로 이를 포착합니다.)

PoC가 매달린 엣지를 SEGV로 바꾸는 방법

PoC는 재사용 가능한 힙에 대한 오래된 포인터만 남기는 것이 아니라 백킹 페이지를 munmap하여 다음 역참조에서 바로 오류가 발생하게 합니다.

  1. 영역별 청크 격리. GC 청크 풀은 영역별로 존재하므로(Zone::availableChunks/fullChunks), 원자 영역 청크에는 원자 영역 아레나만 포함됩니다. 청크의 운명은 순전히 원자/Symbol 수명으로 제어할 수 있습니다.
  2. 힙 정리. 300개의 "자석" Symbol(유지됨)이 초기 청크를 차지하고 압축 대상 역할을 합니다. 그런 다음 150,000개의 폐기 가능한 Symbol이 ~4개의 새로운 1MB 청크를 채워 피해 Symbol이 운명이 정해진 스프레이 Symbol만 포함된 청크의 중간에 위치하게 합니다.
  3. 약하게 유지된 Symbol 댄스(21-31행, 바이트코드에 민감 — 그대로 유지해야 함): c.eval(b)는 최상위 호출 IC가 약한 스텁 필드에 Symbol을 캡처하게 합니다; b = undefined는 마지막 강한 루트를 제거합니다; 스프레이는 제거됩니다; 두 번의 영역 범위 GC(gc("zone"), schedulezone(c) + schedulezone("") + gc("zone") — 빈 문자열은 원자 영역을 예약함)가 죽은 스프레이를 스윕하고, 피해자를 자석 아레나로 압축하며, 약한 엣지 수정을 건너뛰고, 피해자의 아레나를 해제합니다. 이제 해당 청크는 완전히 비어 있습니다.
  4. munmap. gcparam("minEmptyChunkCount", 0)은 모든 빈 청크를 만료 가능하게 만듭니다; sleep(0.5) 동안 BackgroundDecommitTask가 expireEmptyChunkPool -> FreeChunkPool -> 를 실행합니다 — 피해 청크의 진정한 munmap입니다. (아레나 수준의 decommit은 — 읽기 가능한 0 — 일 뿐이며, 전체 청크 해제만이 유일한 munmap 경로이므로 1단계의 청크 격리가 중요한 이유입니다.)

널 페이지 크래시 너머

이것은 단순한 DoS가 아닙니다. 입증된 에스컬레이션(GC-NDAY/ 및 CHAIN/ 연구 디렉토리의 PoC 및 로그):

  • 공격자가 선택한 오류 주소(segv9): munmap 후 minorgc() 세미스페이스 플립으로 nursery가 해제된 VA를 차지합니다; 원시 밀집 더블 스프레이가 오래된 아레나 헤더의 zone 필드 위에 공격자 qword를 씁니다. 그런 다음 스윕이 attacker_ptr + 0x14를 역참조합니다 — 0x424242424256에서 결정적 3/3.
  • 판정 제어 + 반복 가능한 읽기: 로드된 값이 약한 엣지 활성 판정을 선택합니다; "LIVE" 판정은 매달린 엣지를 유지하고 이후 모든 주요 GC에서 이를 다시 역참조합니다(공격자가 선택한 읽기 + 1비트 스크립트 관찰 가능 오라클). "DEAD" 판정은 자가 치유됩니다.
  • 두 버그 체인: 별도의 투기적 사이드 채널을 통해 유출된 실제 js::Zone*가 이 리필을 통해 심어졌습니다; 수집기는 오류 없이 위조된 아레나 메타데이터를 소비했습니다(1비트 교란된 제어 심기는 크래시 발생), ASLR 무력화 -> UAF 심기 구성을 입증합니다.
  • 제한된 네거티브: 이 스텁 계열을 통한 직접 fakeobj는 아키텍처적으로 차단됩니다 — 압축은 강한 엣지를 올바르게 수정하고, 약한 엣지만 매달리며, 해당 스윕 소비자는 분기 전용입니다.
도구 다운로드
UnmapPages
madvise(MADV_DONTNEED)
  • 오류를 일으키는 역참조. 마지막 gc()가 JIT 데이터를 스윕합니다: sweepJitDataOnMainThread -> ICEntry::traceWeak -> TraceWeakCacheIRStub가 오래된 Symbol 포인터를 읽은 다음, SweepingTracer::onEdge(gc/Marking.cpp:3195)가 오래된 주소에 대해 청크 산술을 수행하여 아레나 헤더의 zone 필드를 로드합니다. 페이지가 사라졌거나 0으로 채워졌으므로 zone == nullptr이고, zone->isGCSweeping()이 nullptr + 0x14(shadow::Zone::gcState)를 읽습니다 -> SIGSEGV. 오류 시점에 rcx는 오래된 Symbol 포인터를, rdx는 munmap된 청크 베이스를 보유합니다.