Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2026-15718-who-put-ptrs-in-my-wasm — Chaîne d'exploitation PoC pour CVE-2026-15718 : compilateur baseline wasm de SpiderMonkey, array.fill sans synchronisation -> pointeur invalide -> addrOf/fakeobj -> R/W arbitraire -> RCE | Kitploit
Outils/GitHubGitHub/sneakynachos/cve-2026-15718-who-put-ptrs-in-my-wasm
Analyse des VulnérabilitésExploitationRétro-ingénierieSécurité WebDéveloppement de Charges UtilesExploitation de Binaires
GitHubsneakynachos/cve-2026-15718-who-put-ptrs-in-my-wasm

CVE-2026-15718-who-put-ptrs-in-my-wasm

Chaîne d'exploitation PoC pour CVE-2026-15718 : compilateur baseline wasm de SpiderMonkey, array.fill sans synchronisation -> pointeur invalide -> addrOf/fakeobj -> R/W arbitraire -> RCE

Voir le dépôt
1il y a 1 jourPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

CVE-2026-15718 — qui a mis des pointeurs dans mon wasm

Chaîne d'exploitation proof-of-concept pour CVE-2026-15718, une erreur de compilation par absence de sync() dans le compilateur baseline WebAssembly de Mozilla SpiderMonkey (composant « JavaScript: WebAssembly »). Un unique array.fill sans itération fournit une primitive fakeobj ; la chaîne escalade vers la lecture/écriture arbitraire du processus hôte et l'exécution arbitraire de code natif (posix_spawnp("/bin/sh", ...)).

  • CVE : CVE-2026-15718 (CWE-763, libération de pointeur invalide)
  • Affecté : Firefox < 152.0.6, Firefox ESR < 140.13, Thunderbird < 140.13
  • Corrigé dans : Firefox 152.0.6 / ESR 140.13 / Thunderbird 140.13, 2026-07-14
  • Bug en amont : Mozilla Bug 2045443 (MFSA-2026-67)
  • Commit de correctif : 4441102e62e8 (« Bug 2045443 », une ligne)

Cause racine

BaseCompiler::emitArrayFill() () émet la boucle de remplissage de sans appeler au préalable :

js/src/wasm/WasmBaselineCompile.cpp
array.fill
sync()
root@kitploit:~
   if (elementType.isRefRepr()) {
     freePtr(RegPtr(PreBarrierReg));
   }

+  sync();
+
   // Perform the fill loop using `numElements` as the loop variable ...

sync() vide la pile de valeurs du compilateur baseline (stk_) des registres vers la pile machine. La barrière postérieure imprécise par itération de la boucle de remplissage (emitPostBarrierEdgeImprecise) appelle sync() en interne — mais seulement si la boucle s'exécute. L'étiquette de sortie de la boucle (done) est une jonction de deux chemins :

  • la boucle s'est exécutée au moins une fois (éléments reftype) : stk_ est synchronisé — chaque opérande vit dans un emplacement de pile machine ;
  • zéro itération (numElements == 0) : stk_ n'est pas touché — les opérandes vivent encore uniquement dans des registres.

Le modèle statique du compilateur après la jonction reflète toujours le chemin synchronisé, donc le code émis après array.fill lit les opérandes depuis des emplacements de pile qu'une exécution sans itération n'a jamais écrits. Un opérande reftype relu de cette façon est un pointeur invalide (périmé) (CWE-763).

Primitive : technique d'emplacement plant/lecture

La désynchronisation est bidirectionnelle entre deux fonctions wasm identiques au niveau du frame :

  • plant (n = 1, la boucle s'exécute) : le sync() dans la boucle écrit une valeur dans l'emplacement — une vraie ref (addrOf) ou un i64 contrôlé (mise en place de fakeobj) ;
  • read (n = 0, zéro itération) : l'emplacement n'est jamais écrit ; la fonction jumelle relit l'emplacement périmé — comme i64 (fuite) ou comme (ref $t) (fakeobj).

Chaîne d'exploitation (poc/)

FichierÉtapeRésultat
poc-min.js (+ gen_trigger.py)démo de désynchronisationle chemin contrôlé renvoie la valeur correcte ; le chemin zéro itération renvoie un pointeur poubelle lu depuis l'emplacement jamais écrit
chain.js (+ gen_chain.py, chain.tpl.js, build.sh)chaîne complèteaddrOf + fakeobj → faux WasmArrayObject → R/W arbitraire → fuite de la base XUL → parcours des imports Mach-O du runtime → funcref forgée → posix_spawnp("/bin/sh", ["-c", "touch /tmp/CVE-2026-15718-PWNED"])

Détails des étapes dans chain.js :

  1. plantSpray/plantCmd/plantFun/plantExt + leak — addrOf pour les tableaux wasm, les funcrefs et les objets JS (externref).
  2. sprayV + fakeRd/fakeWr — fakeobj ; faux WasmArrayObject (numElements_ @+16, data_ @+24, éléments inline @+40) avec la fenêtre factice conservée dans un tableau hors ligne (alloué par malloc) afin que le GC ne puisse pas la déplacer en cours de balayage.
  3. Fuite de l'entrée native d'une JSFunction (+0x20), balayage arrière page par page pour le magic Mach-O (0xfeedfacf) → base XUL.
  4. Résolution de symboles entièrement dynamique : parcours des commandes de chargement Mach-O de XUL via la lecture arbitraire (LC_SEGMENT_64/LC_SYMTAB/LC_DYSYMTAB + table des symboles indirects) pour localiser l'entrée __stubs de _posix_spawnp. Aucun offset codé en dur ; le stub effectue la liaison paresseuse au premier appel.
  5. Forge d'une funcref (typeDef @+0x40 copié depuis une vraie ref.func, cible d'appel @+0x38 = adresse du stub) puis invocation via call_ref avec posix_spawnp(pid, "/bin/sh", 0, 0, [sh, -c, cmd], 0).

Exécution

Testé avec un xpcshell (ou le shell js / le navigateur) compilé depuis un arbre antérieur à 152.0.6 (la build de référence ici est Firefox 149.0a1, 2026-01-14) :

root@kitploit:~
# démo minimale de désynchronisation
xpcshell poc/poc-min.js

# chaîne complète (régénère chain.js depuis le template + le générateur)
(cd poc && sh build.sh)
rm -f /tmp/CVE-2026-15718-PWNED
xpcshell poc/chain.js    # crée /tmp/CVE-2026-15718-PWNED
ls -l /tmp/CVE-2026-15718-PWNED

Le harnais définit javascript.options.wasm_optimizingjit=false pour épingler le niveau baseline pendant le long balayage Mach-O (le bug ne concerne que le baseline ; dans le navigateur, le déclencheur s'exécute bien sous le seuil de montée de niveau, donc cela n'est pas nécessaire là-bas). tools/xul_slots.py est un validateur hors ligne qui liste les emplacements nommés stub/GOT de XUL (utilisé pour recouper le parcoureur du runtime).

Notes de portabilité

Les offsets concernent macOS arm64, cet arbre/build exact (WasmArrayObject { +16 numElements, +24 data_, +40 inline }, JSFunction native @ +0x20, WasmFuncRef { +0x38/+0x48 cible d'appel, +0x40 typeDef }). Tous sont redérivés au runtime par les auto-tests de la chaîne ; seuls les agencements de structures sont supposés. Aucun souci de PAC (XUL est un binaire arm64, non arm64e) ; le stub de liaison paresseuse résout la cible au premier appel, donc aucun offset de cache partagé dyld n'est nécessaire.

Périmètre / limites honnêtes

Ce PoC s'exécute dans un processus shell non sandboxé. Dans une véritable attaque Firefox, la chaîne atterrit dans le processus de contenu, où la sandbox macOS refuse posix_spawnp — un bug distinct d'évasion de la sandbox OS est nécessaire pour une compromission complète (voir par exemple l'analyse de l'étape 2 dans CVE-2026-2796-and-CVE-2026-2768-escape-the-wasm-box).

Atténuations

  • Mettre à jour vers Firefox / Thunderbird ≥ 152.0.6 (ESR ≥ 140.13).
  • Défense en profondeur : javascript.options.wasm=false bloque le vecteur de déclenchement.

Références

  • MFSA-2026-67
  • NVD : CVE-2026-15718
  • Correctif : https://github.com/mozilla-firefox/firefox/commit/4441102e62e8

Avertissement

Pour la recherche en sécurité, l'éducation et les tests défensifs uniquement. La vulnérabilité est corrigée dans les versions actuelles de Firefox/Thunderbird. Ne pas utiliser contre des systèmes que vous ne possédez pas ou pour lesquels vous n'avez pas d'autorisation explicite de test.

Télécharger l’outil