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
wasm2c-tableflip — Evasione dalla sandbox di wasm2c. Un modulo WebAssembly non attendibile fuoriesce dalla sandbox C generata ed esegue un comando shell arbitrario sull'host. | Kitploit
Strumenti/GitHubGitHub/trustsig-eu/wasm2c-tableflip
Analisi delle VulnerabilitàExploitVirtualizzazione per la SicurezzaBinary Exploitation
GitHubtrustsig-eu/wasm2c-tableflip

wasm2c-tableflip

Evasione dalla sandbox di wasm2c. Un modulo WebAssembly non attendibile fuoriesce dalla sandbox C generata ed esegue un comando shell arbitrario sull'host.

Vedi Repository
4141 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

wasm2c sandbox escape: il modulo guest esegue un comando shell sull'host

Leggi il blog: trustsig.eu/blog

wasm_rt_allocate_funcref_table() in wasm2c/wasm-rt-impl-tableops.inc imposta table->size dal numero di elementi dichiarati dal modulo e poi ignora il risultato di calloc(). Quando l'allocazione fallisce, la tabella rimane con data == NULL e la dimensione size completa dichiarata, quindi ogni controllo dei limiti passa comunque e table->data[i] diventa l'indirizzo assoluto i * sizeof(wasm_rt_funcref_t).

Il conteggio degli elementi proviene dal guest, quindi il guest sceglie la dimensione dell'allocazione e può forzare il fallimento.

Riproduzione

root@kitploit:~
git clone https://github.com/trustsig-eu/wasm2c-tableflip.git
cd wasm2c-tableflip
root@kitploit:~
docker build -t wabt-w2c-poc .
docker run --rm wabt-w2c-poc

L'immagine clona wabt al tag 1.0.41 da upstream, compila wat2wasm e wasm2c, compila il modulo guest e un embedder semplice, e lo esegue.

Output previsto:

root@kitploit:~
running guest
guest returned 0
--- file on host ---
goodbye sandbox

L'ultima riga è il contenuto di /tmp/pwned.txt, un file che non esisteva prima che il modulo in sandbox fosse eseguito.

Verificato su linux/arm64 e linux/amd64. Niente nel modulo è specifico dell'architettura: l'indirizzo dell'istanza, lo slot GOT e l'offset di libc vengono tutti risolti in fase di build a partire dal binario appena compilato e dalla libc di quell'immagine.

Senza Docker

Su Linux, con clang, cmake, ninja e binutils installati:

root@kitploit:~
git clone --depth 1 --branch 1.0.41 --recurse-submodules --shallow-submodules \
  https://github.com/WebAssembly/wabt ~/wabt
cmake -S ~/wabt -B ~/wabt/out -G Ninja -DCMAKE_BUILD_TYPE=Release \
  -DBUILD_TESTS=OFF -DBUILD_LIBWASM=OFF -DWITH_WASI=OFF
ninja -C ~/wabt/out wat2wasm wasm2c

python3 tableflip_poc.py --wabt-src ~/wabt --wat2wasm ~/wabt/out/wat2wasm \
  --wasm2c ~/wabt/out/wasm2c --run
cat /tmp/pwned.txt

macOS non è una piattaforma supportata per questo PoC. Darwin non applica RLIMIT_AS, quindi la calloc sovradimensionata riesce e il bug non si attiva mai; le build arm64 di macOS sono sempre indipendenti dalla posizione, e Mach-O non ha un GOT ELF per il passaggio di leak. Il difetto in sé è indipendente dalla piattaforma; solo questa catena di exploit è specifica di Linux.

Altre versioni e comandi:

root@kitploit:~
docker build --build-arg WABT_REF=main -t wabt-w2c-poc .
docker run --rm wabt-w2c-poc bash -c \
  "python3 tableflip_poc.py --run --command 'id > /tmp/pwned.txt' && cat /tmp/pwned.txt"

Cosa fa il guest

  1. Dichiara (table $t 2147483648 funcref). La calloc da 68 GB fallisce, data è NULL, size resta 2147483648 e gli indici della tabella diventano indirizzi assoluti.
  2. table.get all'indirizzo got_slot/32 legge il GOT dell'embedder attraverso la tabella corrotta e table.set memorizza il risultato nei globali del modulo, dove il codice wasm può leggerlo come intero. Questo rivela l'indirizzo di malloc della libc, e system si ricava a distanza fissa nella libc del target.
  3. Crea una wasm_rt_funcref_t in quattro globali consecutivi: func_type che punta a una copia dell'hash di tipo del call site (func_types_eq_slowpath lo confronta con , quindi i byte controllati dal guest superano il controllo), = , e = la stringa di comando, anch'essa contenuta nei globali.

L'unico dato di layout incorporato nel modulo è l'indirizzo dell'istanza del modulo, che è un globale e quindi fisso in un embedder non PIE. ASLR rimane attivo; l'indirizzo della libc viene leakato a runtime.

Condizione di attivazione

L'allocazione della tabella deve fallire. Il PoC usa ulimit -v 1000000, un limite di spazio degli indirizzi del tipo che un host che esegue codice non fidato imposterebbe. Fallisce anche su host a 32 bit, dove l'allocazione non può essere soddisfatta affatto, con vm.overcommit_memory=2, o sotto una pressione di memoria sufficiente.

Su Linux 64-bit standard con l'euristica di overcommit predefinita l'allocazione riesce e non viene mai toccata, ed è per questo che il bug sopravvive ai test normali.

Versioni interessate

Ogni release che include le tabelle di wasm2c. La calloc senza controllo risale al commit ab9e0b55 (#813). Verificato contro la release 1.0.41 e l'attuale main.

L'allocatore di memoria nello stesso runtime gestisce questo caso:

root@kitploit:~
  memory->data = (MEMORY_CELL_TYPE)calloc(byte_length, 1);
  if (byte_length != 0 && !memory->data) {
    abort();
  }

L'allocatore di tabelle necessita dello stesso controllo.

File

  • Dockerfile compila wabt ed esegue il PoC.
  • tableflip_poc.py genera il modulo guest, compila l'embedder, risolve le tre costanti dal binario compilato e dalla libc del target con nm e readelf, e lo esegue. L'embedder che emette non contiene alcun codice di supporto all'exploit.
Scarica lo strumento
memcmp
func
system
module_instance
  • call_indirect all'indirizzo globals_addr/32. wasm2c emette ((t)entry.func)(entry.module_instance, ...), quindi questo chiama system(command).