Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2026-15718-who-put-ptrs-in-my-wasm — Catena di exploit PoC per CVE-2026-15718: compilatore baseline wasm di SpiderMonkey, array.fill con sync mancante -> puntatore non valido -> addrOf/fakeobj -> R/W arbitraria -> RCE | Kitploit
Strumenti/GitHubGitHub/sneakynachos/cve-2026-15718-who-put-ptrs-in-my-wasm
Analisi delle VulnerabilitàExploitReverse EngineeringSicurezza WebSviluppo PayloadBinary Exploitation
GitHubsneakynachos/cve-2026-15718-who-put-ptrs-in-my-wasm

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

Catena di exploit PoC per CVE-2026-15718: compilatore baseline wasm di SpiderMonkey, array.fill con sync mancante -> puntatore non valido -> addrOf/fakeobj -> R/W arbitraria -> RCE

Vedi Repository
11 giorno faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

CVE-2026-15718 — chi ha messo puntatori nel mio wasm

Catena di exploit proof-of-concept per CVE-2026-15718, una miscompilazione per mancata sync() nel compilatore WebAssembly baseline di Mozilla SpiderMonkey (componente "JavaScript: WebAssembly"). Un singolo array.fill a zero iterazioni produce una primitiva fakeobj; la catena scala fino a lettura/scrittura arbitraria del processo host ed esecuzione arbitraria di codice nativo (posix_spawnp("/bin/sh", ...)).

  • CVE: CVE-2026-15718 (CWE-763, rilascio di un puntatore non valido)
  • Versioni interessate: Firefox < 152.0.6, Firefox ESR < 140.13, Thunderbird < 140.13
  • Corretto in: Firefox 152.0.6 / ESR 140.13 / Thunderbird 140.13, 2026-07-14
  • Bug upstream: Mozilla Bug 2045443 (MFSA-2026-67)
  • Commit di correzione: 4441102e62e8 ("Bug 2045443", una sola riga)

Causa principale

BaseCompiler::emitArrayFill() () genera il ciclo di riempimento di senza chiamare prima :

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() trasferisce lo stack dei valori del compilatore baseline (stk_) dai registri allo stack macchina. La post-barriera imprecisa per iterazione del ciclo di riempimento (emitPostBarrierEdgeImprecise) chiama sync() internamente — ma solo se il ciclo viene eseguito. L'etichetta di uscita del ciclo (done) è la confluenza di due percorsi:

  • il ciclo è stato eseguito almeno una volta (elementi di tipo reftype): stk_ è sincronizzato — ogni operando vive in uno slot dello stack macchina;
  • a zero iterazioni (numElements == 0): stk_ non viene toccato — gli operandi vivono ancora solo nei registri.

Il modello statico del compilatore dopo la confluenza riflette sempre il percorso sincronizzato, quindi il codice generato dopo array.fill legge gli operandi da slot dello stack che un'esecuzione a zero iterazioni non ha mai scritto. Un operando di tipo reftype riletto in questo modo è un puntatore non valido (obsoleto) (CWE-763).

Primitive: tecnica dello slot plant/read

La desincronizzazione è bidirezionale tra due funzioni wasm dal frame identico:

  • plant (n = 1, il ciclo viene eseguito): la sync() interna al ciclo scrive un valore nello slot — un ref reale (addrOf) o un i64 controllato (setup di fakeobj);
  • read (n = 0, a zero iterazioni): lo slot non viene mai scritto; la funzione gemella rilegge lo slot obsoleto — come i64 (leak) o come (ref $t) (fakeobj).

Catena di exploit (poc/)

FileFaseRisultato
poc-min.js (+ gen_trigger.py)demo della desincronizzazioneil percorso di controllo restituisce il valore corretto; il percorso a zero iterazioni restituisce un puntatore spazzatura letto dallo slot mai scritto
chain.js (+ gen_chain.py, chain.tpl.js, build.sh)catena completaaddrOf + fakeobj → WasmArrayObject fake → R/W arbitrario → leak della base di XUL → percorrimento runtime delle importazioni Mach-O → funcref contraffatto → posix_spawnp("/bin/sh", ["-c", "touch /tmp/CVE-2026-15718-PWNED"])

Dettagli delle fasi in chain.js:

  1. plantSpray/plantCmd/plantFun/plantExt + leak — addrOf per gli array wasm, i funcref e gli oggetti JS (externref).
  2. sprayV + fakeRd/fakeWr — fakeobj; WasmArrayObject fake (numElements_ @+16, data_ @+24, elementi inline @+40) con la finestra dei fake mantenuta in un array out-of-line (allocato con malloc()) così che il GC non possa spostarla durante la scansione.
  3. Leak dell'entry nativa di una JSFunction (+0x20), scansione all'indietro pagina per pagina alla ricerca del magic Mach-O (0xfeedfacf) → base di XUL.
  4. Risoluzione simbolica completamente dinamica: percorre i load command Mach-O di XUL tramite la lettura arbitraria (LC_SEGMENT_64/LC_SYMTAB/LC_DYSYMTAB + tabella dei simboli indiretta) per individuare la entry __stubs di _posix_spawnp. Nessun offset hardcoded; lo stub esegue il lazy binding alla prima chiamata.
  5. Funcref contraffatto (typeDef @+0x40 copiato da un ref.func reale, call target @+0x38 = indirizzo dello stub), invocato tramite call_ref con posix_spawnp(pid, "/bin/sh", 0, 0, [sh, -c, cmd], 0).

Esecuzione

Testato con uno xpcshell (o la shell js / il browser) compilato da un albero pre-152.0.6 (la build di riferimento qui è Firefox 149.0a1, 2026-01-14):

root@kitploit:~
# minimal desync demo
xpcshell poc/poc-min.js

# full chain (regenerates chain.js from the template + generator)
(cd poc && sh build.sh)
rm -f /tmp/CVE-2026-15718-PWNED
xpcshell poc/chain.js    # creates /tmp/CVE-2026-15718-PWNED
ls -l /tmp/CVE-2026-15718-PWNED

L'harness imposta javascript.options.wasm_optimizingjit=false per fissare il tier baseline durante la lunga scansione Mach-O (il bug riguarda solo il baseline; nel browser il trigger gira ben al di sotto della soglia di tier-up, quindi non serve lì). tools/xul_slots.py è un validatore offline che elenca gli slot stub/GOT con nome di XUL (usato per la verifica incrociata del walker a runtime).

Note sulla portabilità

Gli offset valgono per macOS arm64, questo esatto albero/build (WasmArrayObject { +16 numElements, +24 data_, +40 inline }, JSFunction native @ +0x20, WasmFuncRef { +0x38/+0x48 call target, +0x40 typeDef }). Tutti vengono ricalcolati a runtime dai self-test della catena; si assume solo il layout delle strutture. Nessun problema di PAC (XUL è un binario arm64, non arm64e); lo stub di lazy binding risolve la destinazione alla prima chiamata, quindi non servono offset della dyld shared cache.

Ambito / limitazioni oneste

Questo PoC viene eseguito in un processo shell senza sandbox. In un attacco Firefox reale la catena finisce nel content process, dove la sandbox di macOS blocca posix_spawnp — serve un bug separato di fuga dalla sandbox del sistema operativo per una compromissione completa (vedi ad es. l'analisi dello stage 2 in CVE-2026-2796-and-CVE-2026-2768-escape-the-wasm-box).

Mitigazioni

  • Aggiornare a Firefox / Thunderbird ≥ 152.0.6 (ESR ≥ 140.13).
  • Difesa in profondità: javascript.options.wasm=false blocca il vettore del trigger.

Riferimenti

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

Dichiarazione di non responsabilità

Solo per ricerca sulla sicurezza, formazione e test difensivi. La vulnerabilità è corretta nelle versioni attuali di Firefox/Thunderbird. Non utilizzare contro sistemi che non possiedi o per i quali non hai un'autorizzazione esplicita al test.

Scarica lo strumento