
Un report su Dirty Frag, una catena di vulnerabilità di Linux Local Privilege Escalation (LPE) che consente a un utente non privilegiato di ottenere l'accesso root.
Laboratorio di riproduzione e rilevamento di exploit per una catena di escalation dei privilegi locale del kernel Linux.
Stato: VERIFICATO. Ho completato la riproduzione, la verifica fileless e il rilevamento a livello di syscall nel laboratorio (kernel 6.18.9+kali-amd64). Questo documento è un registro di laboratorio. Ogni affermazione di seguito è stata osservata durante l'esecuzione della riproduzione. Gli screenshot e gli artefatti sono acquisizioni reali dalla VM.
Dirty Frag combina due bug logici deterministici nel kernel Linux. Questi bug consentono a un utente locale non privilegiato di sovrascrivere la cache delle pagine di file di sola lettura (ad esempio /usr/bin/su) e ottenere una shell di root:
| Variante | CVE | Sink | Percorso di attivazione | Richiede userns non privilegiato |
|---|---|---|---|---|
| Scrittura Page-Cache xfrm‑ESP | CVE‑2026‑43284 | crypto_authenc_esn_decrypt() in esp_input() | socket(AF_INET) con UDP‑encap, poi xfrm_input() | Sì (CAP_NET_ADMIN) |
| Scrittura Page-Cache RxRPC | CVE‑2026‑43500 | rxkad_verify_packet_1() (pcbc(fcrypt)) | socket(AF_RXRPC) | No |
Entrambe le varianti utilizzano lo stesso schema di base di Dirty Pipe e Copy Fail. La syscall splice(2) inserisce un riferimento a una pagina della cache delle pagine di un file nello slot frag di uno sk_buff lato mittente. L'attaccante può solo leggere questo file. Il codice del kernel lato ricezione esegue quindi uno STORE crittografico in-place sopra quel frag. Questo modifica la cache delle pagine in RAM. Non avviene alcuna scrittura su disco, quindi il monitoraggio dell'integrità dei file (AIDE, Tripwire) non può rilevarlo. L'attacco è deterministico. Non ha finestra di race né panic del kernel in caso di fallimento.
cac2661c53f3 (2017‑01) a f4c50a4034e6 (corretta 2026‑05‑05)2dc334f1a63a (2023‑06) a aa54b1d27fe0 (corretta 2026‑05‑10)CVE-2026-43284 = 8.8 (Alta), CVE-2026-43500 = 7.8 (Alta)Dirty Frag è un LPE fileless. Corrompe la cache delle pagine in memoria, non il file su disco. Il monitoraggio tradizionale dell'integrità dei file non può rilevarlo. Il rilevamento deve avvenire a livello di syscall. La catena utilizza queste primitive di syscall: socket(AF_ALG)/socket(AF_RXRPC), splice e unshare(CLONE_NEWUSER|CLONE_NEWNET). Il percorso ESP crea anche socket UDP AF_INET e netlink. Questo livello è il fulcro dell'ingegneria del rilevamento in questo repository.
Entrambe le varianti utilizzano lo stesso sink: crittografia in-place che STORE byte su una pagina della cache delle pagine che l'attaccante posiziona con splice(2).
UDP_ENCAP_ESPINUDP.vmsplice, poi 16 byte da /usr/bin/su all'offset del file target con splice.splice spinge la pipe nel socket di invio. splice_to_socket() imposta MSG_SPLICE_PAGES. Questo inserisce la pagina della cache delle pagine di /usr/bin/su direttamente in skb->frags[0].xfrm4_udp_encap_rcv, poi xfrm_input, poi esp_input(). Il ramo vulnerabile skip_cow (!skb_cloned() && !skb_has_frag_list()) bypassa skb_cow_data(). Esegue decrittazione AEAD in-place con la pagina della cache delle pagine sia come sorgente che come destinazione.crypto_authenc_esn_decrypt() emette uno STORE dei 32 bit di ordine superiore dell'ESN. Quel valore è replay_esn->seq_hi. L'attaccante sceglie questo valore alla registrazione della SA con l'attributo netlink XFRMA_REPLAY_ESN_VAL.L'attaccante controlla sia la posizione (offset di splice) che il valore (4 byte). La verifica dell'autenticazione viene eseguita dopo lo store, quindi il livello crittografico non segnala mai la scrittura. Questa variante richiede CAP_NET_ADMIN e utilizza unshare(CLONE_NEWUSER|CLONE_NEWNET).
rxkad_verify_packet_1() esegue una decrittazione pcbc(fcrypt) a blocco singolo direttamente sul frag skb bloccato da splice. Non copia prima i dati. L'attaccante sceglie una chiave di sessione (add_key("rxrpc", …)) in modo che decrypt(ciphertext) sia uguale a desired_plaintext. Questo produce uno STORE di 8 byte. Questa variante prende di mira /etc/passwd. Non richiede namespace utente. Richiede il modulo rxrpc.ko (caricato per impostazione predefinita su Ubuntu).
Il PoC pubblico prende di mira /usr/bin/su. Scrive 48 store ESP di 4 byte ciascuno (192 byte all'offset del file 0). Sostituisce i primi byte della cache delle pagine con un ELF statico di shell di root. Il punto di ingresso dell'ELF esegue setgid(0); setuid(0); setgroups(0,NULL); execve("/bin/sh", …). Un singolo execve("/usr/bin/su") produce quindi una shell di root.
La patch ESP (mainline f4c50a4034e6) contrassegna i frag di pagina che arrivano tramite splice() con il flag SKBFL_SHARED_FRAG. Il ramo skip_cow in esp_input() ora controlla anche questo flag. Gli skb con frag condivisi passano attraverso skb_cow_data() prima della decrittazione AEAD in-place.
La patch RxRPC (mainline aa54b1d27fe0) aggiunge un controllo skb->data_len accanto al controllo skb_cloned() esistente. Il kernel copia uno skb non lineare con dati impaginati prima della decrittazione pcbc(fcrypt) in-place.
| Componente | Dettagli |
|---|---|
| Hypervisor | VirtualBox |
| VM target | Kali Linux 2026.1 (snapshot ripristinato a uno stato vulnerabile) |
| Kernel | 6.18.9+kali‑amd64 (più vecchio delle correzioni di maggio 2026) |
| PoC dell'exploit | V4bel/dirtyfrag (singolo file C) |
| Rilevamento | auditd (regole in detection/dirtyfrag.rules) |
Screenshot della configurazione del laboratorio VirtualBox:
