
Un'implementazione Bash di copyfail (CVE-2026-31431)
Nessuna race. Nessun offset. Nessun binario precompilato di cui fidarsi alla cieca.
Un'implementazione in bash di CVE-2026-31431 (Copy Fail). Lo script compila un helper C minimale inline in fase di esecuzione. Il livello bash gestisce il rilevamento dell'architettura, la decompressione del payload e la selezione del target; il livello C esegue l'effettiva interazione con il kernel (socket AF_ALG, splice, sendmsg) a cui bash non può accedere da sola.
Vedi copy.fail per l'analisi tecnica completa.
Il bug si trova in algif_aead, l'interfaccia socket AF_ALG AEAD del kernel. Un'ottimizzazione in-place del 2017 consente alle pagine della page cache di finire nello scatterlist di destinazione scrivibile di un'operazione di decrittazione authencesn. Fornisci l'input giusto tramite splice() e ottieni una scrittura deterministica di 4 byte nella page cache di qualsiasi file leggibile, inclusi i binari setuid che non possiedi.
Sovrascrivi /usr/bin/su con shellcode 4 byte alla volta, eseguilo, ottieni una shell di root. Nessuna finestra di race, nessun simbolo specifico del kernel, nessun tentativo.
chmod +x copyfail.sh
# Check if the system is vulnerable before doing anything
./copyfail.sh -c
# Run the exploit (must be non-root)
./copyfail.sh
# Specify a different setuid target
./copyfail.sh -t /usr/bin/passwd
# List all setuid-root candidates on the system
./copyfail.sh -s
L'exploit sovrascrive solo la page cache in memoria, il file su disco non viene toccato. Un riavvio ripristina tutto. Se vuoi pulire immediatamente:
# Inside your root shell
/usr/bin/su --version # still works from disk if page cache is evicted
# Or just reboot
Se hai usato -t con qualcosa di diverso da su, vale lo stesso. Solo page cache, il disco è pulito.
gcc per compilare l'helper C inlinepython3 per decomprimere il payload dello shellcode (one-liner, nessun pacchetto richiesto)algif_aead, authencesn, hmac, cbcSe l'algo non è disponibile:
sudo modprobe algif_aead authencesn hmac cbc
Alcune distribuzioni includono un blocco in /etc/modprobe.d/ come workaround temporaneo. Rimuovilo se presente:
sudo rm /etc/modprobe.d/disable-algif{_,-}aead.conf 2>/dev/null
floor: torvalds/linux 72548b093ee3 August 2017, v4.14
(AF_ALG iov_iter rework that introduced
the file-page write primitive via splice
into the AEAD scatterlist)
ceiling: torvalds/linux a664bf3d603d April 2026, mainline
(reverts the 2017 in-place optimization;
source and destination scatterlists are
now separate, page-cache pages can no
longer end up as writable crypto output)
Tra questi due commit: ogni distribuzione importante che non ha backportato la correzione. Ubuntu, RHEL, SUSE, Amazon Linux e Debian sono risultati tutti vulnerabili al momento della divulgazione. I backport delle distribuzioni hanno iniziato ad arrivare intorno al 2026-04-29. Per verificare un kernel specifico, cerca a664bf3d603d (o il suo backport per la distribuzione) nel changelog.
| Architettura | Stato |
|---|---|
| x86_64 | ✓ |
| aarch64 | ✓ |
| i386 / i686 | ✓ |
| armv7l | ✓ |
Permanente: aggiorna il kernel.
Workaround (blocca il socket AF_ALG; non influisce su IPsec/XFRM che utilizza direttamente l'API crittografica del kernel):
echo "install algif_aead /bin/false" | sudo tee /etc/modprobe.d/disable-algif-aead.conf
sudo rmmod algif_aead 2>/dev/null
Contenitori: aggiungi un profilo seccomp che blocchi la creazione di socket AF_ALG e imposta allowPrivilegeEscalation: false nel security context del pod. Questo abilita no_new_privs, impedendo al kernel di onorare i bit setuid su execve().
La versione bash non vincerà sulle dipendenze, ma è un singolo script che puoi leggere dall'inizio alla fine prima di eseguirlo. L'helper C viene generato e compilato in fase di esecuzione da un heredoc, nessun blob binario da controllare separatamente.
Solo per test di sicurezza e ricerca autorizzati. Non eseguirlo su sistemi che non possiedi o per i quali non hai un'esplicita autorizzazione scritta a testarli.
| Python | Go | Bash |
|---|
| Dipendenze | python3 | nessuno (binario statico) | gcc + python3 |
| Binario precompilato | no | sì | no |
| File singolo | sì | no | sì |
| Fase di compilazione | no | no | sì (inline, auto) |