
Rilevatore e proof-of-concept per una vulnerabilità di scrittura nella page-cache del kernel Linux (CVE-2026-31431) in algif_aead, inclusi uno scanner non distruttivo e un exploit per l'escalation dei privilegi locale.
Questo repository contiene il rilevatore e il PoC per la vulnerabilità scratch-write della page cache algif_aead / authencesn di Linux, CVE-2026-31431.
Articolo di divulgazione: https://xint.io/blog/copy-fail-linux-distributions
Utilizzare solo su host di tua proprietà o per i quali hai ricevuto esplicita autorizzazione. Il rilevatore è non distruttivo e opera solo su file sentinella in directory temporanee; il PoC e l'LPE modificano lo stato della page cache in memoria e rappresentano una vera tecnica di escalation dei privilegi locale: l'esecuzione non autorizzata è generalmente illegale.
algif_aead esegue le operazioni AEAD in-place, ovvero req->src == req->dst. Quando i dati di input vengono forniti tramite splice() da un file normale, lo scatterlist di destinazione contiene riferimenti alle pagine della page cache del file, consentendo al kernel di scrivere nella copia della page cache del file.
authencesn(hmac(sha256),cbc(aes)) esegue una scratch write di 4 byte sul campo seqno_lo dell'AAD (byte 4-7 dell'AAD). Combinando l'AEAD in-place con il percorso splice(), un attaccante può far ricadere questi 4 byte nella pagina della page cache di un file leggibile.
La modifica non viene riscritta su disco, influenzando solo la page cache corrente del kernel. Pertanto il contenuto del file su disco rimane invariato, ma i lettori che condividono quella page cache vedranno il contenuto alterato. File leggibili da tutti come /etc/passwd e /usr/bin/su possono essere bersagli.
È necessario che la toolchain Rust e Cargo siano installati sulla macchina.
Compila tutti i binary Rust:
cargo build --release --bins
Al termine della compilazione verranno generati:
target/release/cve_2026_31431_detector
target/release/cve_2026_31431_poc
Se nel repository devono essere inclusi file precompilati, posizionarli in:
dist/linux-x86_64/cve_2026_31431_detector
dist/linux-x86_64/cve_2026_31431_poc
dist/linux-x86_64/SHA256SUMS
Non committare l'intera directory target/; essa contiene artefatti intermedi di Cargo e cache locale.
Compila solo il rilevatore non distruttivo:
cargo build --release --bin cve_2026_31431_detector
Compila solo la versione Rust di poc.py:
cargo build --release --bin cve_2026_31431_poc
Si consiglia il rilevatore Rust non distruttivo:
./target/release/cve_2026_31431_detector
echo $?
È anche possibile eseguirlo direttamente tramite Cargo:
cargo run --release --bin cve_2026_31431_detector
echo $?
Utilizzo del rilevatore Python:
python3 test_cve_2026_31431.py
echo $?
Significato dei codici di uscita:
| Codice di uscita | Significato |
|---|---|
0 | Nessuna vulnerabilità rilevata, oppure prerequisiti non soddisfatti, ad esempio AF_ALG / non disponibili. |
Interpretazione comune dell'output:
Operazioni eseguite dal rilevatore:
AF_ALG e authencesn(hmac(sha256),cbc(aes)).sendmsg, impostando seqno_lo dell'AAD al marker PWND.splice(), invia la pagina della page cache del file sentinella alla op socket AF_ALG.recv() per guidare l'esecuzione dell'algoritmo.Il rilevatore non modifica /usr/bin/su, /etc/passwd o altri file di sistema. Il file sentinella temporaneo viene eliminato all'uscita.
Versione Rust di poc.py:
./target/release/cve_2026_31431_poc
oppure:
cargo run --release --bin cve_2026_31431_poc
Nota: questo PoC, seguendo la logica di poc.py, apre /usr/bin/su, contamina la sua copia nella page cache tramite la primitiva della vulnerabilità, quindi esegue su. Non fa parte del flusso di rilevamento non distruttivo e deve essere eseguito solo in ambienti di test autorizzati.
python3 exploit_cve_2026_31431.py
python3 exploit_cve_2026_31431.py --shell
Lo script individua il campo UID dell'utente corrente in /etc/passwd e tenta di modificare l'UID nella page cache in 0000. Il file /etc/passwd su disco non viene modificato, ma i processi di sistema che leggono la page cache potrebbero vedere il contenuto alterato.
Limitazioni:
1000 a 9999.nscd, sssd, systemd-userdbd, potrebbero mascherare le modifiche alla page cache di /etc/passwd./etc/passwd deve rimanere presente tra la patch e l'esecuzione di su.Pulizia della page cache:
python3 -c "import os; fd=os.open('/etc/passwd', os.O_RDONLY); os.posix_fadvise(fd, 0, 0, os.POSIX_FADV_DONTNEED); os.close(fd)"
Se si è già ottenuta una shell root, si può anche eseguire:
echo 3 > /proc/sys/vm/drop_caches
Anche un riavvio cancella lo stato della page cache.
In attesa della correzione del kernel della distribuzione, è possibile disabilitare algif_aead:
sudo tee /etc/modprobe.d/disable-algif-aead.conf <<<'install algif_aead /bin/false'
sudo rmmod algif_aead 2>/dev/null
Dopo aver applicato la mitigazione, il rilevatore dovrebbe normalmente produrre 检测结论:未发现漏洞, indicando che i prerequisiti di attivazione non sono soddisfatti, con codice di uscita 0.
L'idea della correzione a monte è ripristinare le operazioni AEAD da in-place a non in-place, evitando che le pagine della page cache finiscano in uno scatterlist di destinazione scrivibile.
| File | Descrizione |
|---|
test_cve_2026_31431.py | Rilevatore Python non distruttivo. Opera solo su file sentinella temporanei, non tocca i file di sistema. |
src/main.rs | Rilevatore Rust non distruttivo. Logica di rilevamento e codici di uscita identici al rilevatore Python. |
src/bin/poc.rs | Versione Rust di poc.py. Contamina la page cache di /usr/bin/su ed esegue su. |
poc.py | PoC Python. |
exploit_cve_2026_31431.py | LPE Python. Tenta di ottenere una shell root contaminando la page cache di /etc/passwd. |
authencesn2 | Rilevata suscettibilità a CVE-2026-31431. |
1 | Errore durante il test; il risultato non può essere usato come giudizio sulla vulnerabilità. |
| Output | Conclusione |
|---|
检测结论:未发现漏洞 | Nessuna vulnerabilità rilevata, oppure prerequisiti di attivazione non soddisfatti. |
检测结论:存在 CVE-2026-31431 漏洞 | Il marker PWND è finito correttamente nella pagina della page cache spliced; la vulnerabilità è presente. |
检测结论:存在疑似 CVE-2026-31431 漏洞 | La page cache è stata modificata; anche se il marker non è finito nella posizione prevista, il sistema deve essere considerato affetto. |
测试过程出错,无法判断是否存在漏洞 | Rilevamento fallito, codice di uscita 1; è necessario indagare in base al messaggio di errore e rieseguire. |