VirtualBox Slirp NAT Packet Heap Exploitation
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
TL;DR
- VirtualBox include un fork fortemente modificato di Slirp i cui packet buffers (mbufs) risiedono in un custom zone allocator con metadata inline e callback tramite puntatori a funzione (
pfFini,pfDtor). - Una guest può riscrivere il valore
m->m_lenconsiderato trusted con una lunghezza dell’header IP controllata dall’attaccante, il che annulla tutti i successivi controlli di bounds e fornisce sia primitive di infoleak che di overwrite. - Abusando di pacchetti UDP con checksum
0eip_lensovradimensionato, la guest può esfiltrare le tail degli mbuf e i metadata dei chunk adiacenti per apprendere gli indirizzi dell’heap e del zone allocator. - Fornendo IP options appositamente costruite si costringe
ip_stripoptions()a farememcpy()di troppi dati in-place, così l’attaccante può sovrascrivere l’headerstruct itemdel mbuf successivo e puntare il suo campozoneverso dati completamente controllati. - Il free dell’mbuf corrotto attiva
zone->pfFini()con argomenti forniti dall’attaccante; puntandolo sumemcpy@pltsi ottiene una primitiva di copy/write arbitraria che può essere diretta verso GOT entry o altri dati di controllo all’interno del binario VirtualBox non-PIE.
Packet allocator anatomy
VirtualBox allocates every ingress Ethernet frame from a per-interface zone named zone_clust. Each 0x800-byte data chunk is preceded by an inline header:
struct item {
uint32_t magic; // 0xdead0001
void *zone; // uma_zone_t pointer with callbacks
uint32_t ref_count;
LIST_ENTRY(item) list; // freelist / used list links
};
Quando un mbuf viene liberato lo stack di chiamate m_freem -> ... -> slirp_uma_free() si fida dell’header inline:
uma_zfree_arg()ricalcolaitem = (struct item *)mem - 1e dovrebbe validareitem->zone, maAssert()è compilato fuori nelle build di release.slirp_uma_free()caricazone = item->zoneed esegue incondizionatamentezone->pfFini(zone->pData, data_ptr, zone->size)seguito dazone->pfDtor(...).
Pertanto, qualsiasi write-what-where nell’header dell’mbuf si traduce in una chiamata indiretta controllata durante free().
Infoleak via m->m_len override
All’inizio di ip_input() VirtualBox ha aggiunto:
if (m->m_len != RT_N2H_U16(ip->ip_len))
m->m_len = RT_N2H_U16(ip->ip_len);
Perché l’assegnazione avviene prima di verificare l’intestazione IP, un guest può dichiarare qualsiasi lunghezza fino a 0xffff. Il resto dello stack (ICMP, UDP, gestori di frammentazione, ecc.) assume che m->m_len sia affidabile e lo usa per decidere quanti byte copiare dall’mbuf.
Usare pacchetti UDP con checksum 0 (significa “no checksum”). Il fast-path del NAT inoltra m->m_len byte senza ispezionare l’integrità del payload, quindi gonfiare ip_len fa sì che Slirp legga oltre il buffer reale e restituisca residui di heap al guest o a un helper esterno cooperante oltre il NAT. Poiché la dimensione dei chunk è 2048 byte, il leak può includere:
- L’
struct iteminline dell’mbuf successivo, rivelando l’ordine della freelist e il puntatorezonereale. - Heap cookies come i campi
magic, utili per costruire header dall’aspetto valido quando si eseguono corruzioni successivamente.
Overwriting neighbouring chunk headers with IP options
Lo stesso valore di lunghezza fasullo può essere trasformato in una primitive di overwrite forzando il pacchetto attraverso ip_stripoptions() (scatenato quando l’header IP ha options e il payload è UDP/TCP). L’helper calcola una lunghezza di copia da m->m_len e poi chiama memcpy() per spostare l’header di trasporto sopra le options rimosse:
- Fornire un lungo
ip_lencosì che la lunghezza di move calcolata si estenda oltre l’attuale mbuf. - Includere un piccolo numero di IP options in modo che Slirp entri nel percorso di stripping.
- Quando
memcpy()viene eseguito, legge dall’mbuf successivo e scrive sul payload dell’mbuf corrente e sull’header inline, corrompendomagic,zone,ref_count, ecc.
Poiché l’allocator mantiene i pacchetti della stessa interfaccia contigui sulla freelist, questo overflow colpisce deterministically il chunk successivo dopo un moderato heap grooming.
Forging uma_zone_t to hijack pfFini
Una volta che il struct item adiacente è corrompibile, l’exploit procede come segue:
- Usare indirizzi heap leakati per costruire una struttura
uma_zonefasulla dentro un mbuf completamente controllato dal guest. Popolare:pfFinicon la voce PLT dimemcpy().pDatacon il puntatore di destinazione desiderato (es. voce GOT, slot di vtable, array di puntatori a funzione).sizecon il numero di byte da copiare.- Opzionale:
pfDtorcome chiamata di secondo stadio (es. per invocare il puntatore a funzione appena scritto).
- Sovrascrivere il campo
zonedell’mbuf target con il puntatore alla struttura fasulla; adattare i puntatorilistin modo che la bookkeeping della freelist rimanga sufficientemente consistente per evitare crash. - Freeare l’mbuf.
slirp_uma_free()ora eseguememcpy(dest=pData, src=item_data, n=size)mentre l’mbuf contiene ancora dati controllati dal guest, ottenendo un arbitrary write.
Poiché il binario VirtualBox su Linux non è PIE, gli indirizzi PLT per memcpy e system sono fissi e possono essere usati direttamente. Il guest può anche nascondere stringhe come /bin/sh dentro un altro mbuf che rimane referenziato quando la chiamata hijackata viene eseguita.
Heap grooming via fragmentation
La zona per-interfaccia di Slirp è profonda 3072 chunk ed inizialmente ricavata come un array contiguo la cui freelist viene percorsa da indirizzi alti verso il basso. Si può ottenere adjacency deterministica tramite:
- Inondare il NAT con molti frammenti
IP_MFdi dimensione costante in modo che il codice di riassemblaggio allochi sequenze di mbuf prevedibili. - Riciclare chunk specifici inviando frammenti che scadono, forzando le free a rientrare nella freelist in ordine LIFO.
- Usare la conoscenza del cammino della freelist per posizionare l’mbuf futuro vittima subito dopo l’mbuf che conterrà l’overflow delle opzioni IP.
Questo grooming assicura che l’overflow colpisca il struct item target e che la uma_zone fasulla rimanga entro i confini della primitive di leak.
From arbitrary write to host code execution
Con la primitive memcpy-on-free:
- Copiare una stringa
/bin/shcontrollata dall’attacker e il buffer dei comandi in un mbuf stabile. - Usare la primitive per sovrascrivere una voce GOT o un callsite indiretto (es. un puntatore a funzione nello stato del dispositivo NAT) con la voce PLT di
system(). - Scatenare la chiamata sovrascritta. Poiché VirtualBox esegue il dispositivo NAT all’interno del processo host, il payload viene eseguito con i privilegi dell’utente che esegue VirtualBox, permettendo una guest-to-host escape.
Payload alternativi includono il piazzare una mini ROP chain nella memoria heap e copiarne l’indirizzo in una callback frequentemente invocata, oppure ripuntare pfFini/pfDtor stessi su gadget concatenati per scritture ripetute.
References
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.


