
CVE-2024-29943, 하지만 wasm 사용
CVE-2024-29943에 대한 엔드투엔드 익스플로잇 체인으로, 셸코드를
SpiderMonkey의 WebAssembly JIT 코드 페이지에 f64.const 즉시값으로
밀반입하여 임의 네이티브 코드 실행을 달성합니다 — ROP도, VirtualProtect도,
외부 툴체인도 필요 없습니다.
2024-03-20 mozilla-central nightly의 SpiderMonkey 셸(JavaScript-C126.0a1,
linux x86-64, 패치 이전)에 대해 동작 검증 완료: 체인이 끝까지 실행되고
페이로드가 실행됩니다
(write(1, "PWNED by wasm!\n"); exit(0)).
CVE-2024-29943은 Manfred Paul이 Pwn2Own 2024에서 사용한 sec-critical IonMonkey 범위 분석 버그로, Firefox < 124.0.1에 영향을 줍니다 (Bugzilla 1886849, CVSS 9.8).
Object.keys가 제거 가능(elidable)해진 이후(버그 1845728로 인한 회귀),
MObjectKeysLength::computeRange가 Object.keys(x).length에 대해 잘못된
정수 범위를 반환했습니다. Ion 범위 분석은 루프 카운터가 음수가 될 수 없다고
결론지어 여전히 도달 가능한 경계 검사를 제거했고, 그 결과 Uint8Array에
대한 범위 밖 읽기/쓰기가 발생했습니다.
Object.keys 범위 분석 버그 -> Uint8Array에 대한 OOB r/w
-> 인접한 ArrayBuffer 손상 -> addrof / fakeobj / 임의 R/W
-> 직접 구성한 WASM 모듈 인스턴스화 (셸코드를 f64.const 즉시값으로)
-> WasmInstanceObject -> wasm::Instance -> wasm::Code -> CodeTier
-> ModuleSegment.bytes_ (JIT 코드 페이지, RX)
-> 페이지에서 마커 상수 스캔
-> FuncExport.eagerInterpEntryOffset_ (일반 힙)을
페이지 내 셸코드의 오프셋으로 덮어쓰기
-> 인터프리터를 통해 export 호출 -> 페이로드 실행
두 가지 세부 사항은 각각 세그폴트를 한 번씩 겪고 나서 알게 되었으므로 기록해 둡니다:
FuncExport의
eagerInterpEntryOffset_을 덮어써서 수행합니다 — 인터프리터가
codeBase + offset을 계산하여 그곳으로 점프합니다.WASM-JIT-페이지 셸코드 기법은 WasmBlazeFox에서 가져왔습니다; 이 저장소는 그 기법이 원래의 2018년 훈련 버그 대신 현대의 실제 배포되는 브라우저 버그와 결합될 수 있음을 보여줍니다.
poc.js — 범위 분석 버그에 대한 최소 트리거.exploit.js — 전체 체인: 프리미티브 + WASM JIT 셸코드 단계.gen_wasm.py — 셸코드를 내장한 WASM 모듈을 어셈블하고 상수 왕복을
검증합니다. 다른 페이로드를 사용하려면 python3 gen_wasm.py mysc.bin.
기본 페이로드는 심볼 해석이 필요 없는 순수 시스템 콜
write(1, "PWNED by wasm!\n"); exit(0) 증명입니다(따라서 베어 jsshell에서도
동작합니다). 고전적인 libxul 기반 system("gnome-calculator") 페이로드는
WasmBlazeFox ex6을 참조하세요.test.gdb — 주어진 빌드에서 객체 모델 오프셋을 도출하기 위한 브레이크포인트와
ptype /o 헬퍼.afbdf6822c9e9f9b6d44b9ea6904cb10878126b1 (Firefox ~124, 124.0.1 이전),
Linux x86-64를 빌드하거나 — 패치 이전 nightly jsshell을 받으세요, 예:
archive.mozilla.org/pub/firefox/nightly/2024/03/2024-03-20-21-16-35-mozilla-central/jsshell-linux-x86_64.zip.LD_LIBRARY_PATH=<jsshell dir> ./js --no-threads --ion-offthread-compile=off \
--spectre-mitigations=off poc.js # 트리거만 (세그폴트)
LD_LIBRARY_PATH=<jsshell dir> ./js --no-threads --ion-offthread-compile=off \
--spectre-mitigations=off exploit.js # 전체 체인 ("PWNED by wasm!")
--spectre-mitigations=off가 필요한 이유는 경계 검사 제거가 인덱스 마스킹이
비활성화되어 있는 것에 의존하기 때문입니다(Bugzilla 코멘트 참조).
f64.const 즉시값이 코드 세그먼트에 인라인으로
방출됩니다. Ion 컴파일은 이들을 상수 폴딩할 수 있습니다.WASM_INSTANCE_OFF_CODE = 0xa8, MetadataTier.funcExports + 448,
FuncExport + 8 등)은 취약한 커밋의 헤더에서 도출되었고 2024-03-20 nightly
jsshell에 대해 확인되었습니다; 다른 빌드의 경우 test.gdb로 다시
도출하세요.