
CVE-2024-29943, mais avec wasm
Une chaîne d'exploitation de bout en bout pour CVE-2024-29943 qui parvient à une
exécution de code natif arbitraire en introduisant clandestinement du shellcode dans la
page de code JIT WebAssembly de SpiderMonkey sous forme d'immédiats f64.const — pas de ROP, pas de VirtualProtect, pas de
chaîne d'outils externe.
Vérifié fonctionnel contre le shell SpiderMonkey du
nightly mozilla-central du 2024-03-20 (JavaScript-C126.0a1, linux x86-64,
pré-correctif) : la chaîne s'exécute jusqu'au bout et la charge utile s'exécute
(write(1, "PWNED by wasm!\n"); exit(0)).
CVE-2024-29943 est un bug d'analyse de plage d'IonMonkey critique pour la sécurité, utilisé à Pwn2Own 2024 par Manfred Paul, affectant Firefox < 124.0.1 (Bugzilla 1886849, CVSS 9.8).
MObjectKeysLength::computeRange renvoyait une plage entière incorrecte pour
Object.keys(x).length après que a été rendu élidable (régression introduite par
le bug 1845728). L'analyse de plage d'Ion a conclu qu'un compteur de boucle ne pouvait pas devenir
négatif et a éliminé des vérifications de limites qui étaient encore atteignables, produisant une
lecture/écriture hors limites sur un .
Object.keysUint8ArrayObject.keys range-analysis bug -> OOB r/w on Uint8Array
-> corrupt adjacent ArrayBuffer -> addrof / fakeobj / arbitrary R/W
-> instantiate hand-built WASM module (shellcode as f64.const immediates)
-> WasmInstanceObject -> wasm::Instance -> wasm::Code -> CodeTier
-> ModuleSegment.bytes_ (the JIT code page, RX)
-> scan page for marker constant
-> overwrite FuncExport.eagerInterpEntryOffset_ (plain heap)
with the shellcode's offset within the page
-> call the export through the interpreter -> payload runs
Deux détails nous ont coûté un segfault chacun pour être compris, alors ils sont consignés :
eagerInterpEntryOffset_ dans le
FuncExport résidant sur le tas à la place — l'interpréteur calcule
codeBase + offset et saute à cet endroit.La technique du shellcode dans la page WASM-JIT provient de WasmBlazeFox ; ce dépôt démontre que la technique se compose avec un bug moderne d'un navigateur en production à la place du bug d'entraînement original de 2018.
poc.js — déclencheur minimal pour le bug d'analyse de plage.exploit.js — chaîne complète : primitives + étage de shellcode WASM JIT.gen_wasm.py — assemble le module WASM intégrant le shellcode et vérifie
l'aller-retour des constantes. python3 gen_wasm.py mysc.bin pour utiliser une autre
charge utile. La charge utile par défaut est une preuve en pur syscall
write(1, "PWNED by wasm!\n"); exit(0) qui ne nécessite aucune résolution
de symboles (elle fonctionne donc aussi dans le jsshell nu). Pour la charge utile classique
system("gnome-calculator") basée sur libxul, voir WasmBlazeFox ex6.test.gdb — points d'arrêt et helpers ptype /o pour dériver les offsets du modèle
d'objet sur une build donnée.afbdf6822c9e9f9b6d44b9ea6904cb10878126b1 (Firefox ~124, pré-124.0.1),
Linux x86-64 — ou récupérez un jsshell nightly pré-correctif, par ex.
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 # trigger only (segfault)
LD_LIBRARY_PATH=<jsshell dir> ./js --no-threads --ion-offthread-compile=off \
--spectre-mitigations=off exploit.js # full chain ("PWNED by wasm!")
--spectre-mitigations=off est requis car l'élimination des vérifications de limites
repose sur la désactivation du masquage d'index (voir les commentaires Bugzilla).
f64.const sont émis en ligne
dans le segment de code. La compilation Ion pourrait les replier en constantes.WASM_INSTANCE_OFF_CODE = 0xa8, MetadataTier.funcExports + 448,
FuncExport + 8, etc.) ont été dérivés des en-têtes du commit vulnérable
et confirmés contre le jsshell nightly du 2024-03-20 ; re-dérivez-les avec
test.gdb pour d'autres builds.