Script di rilevamento per CVE-2026-31431 (Copy Fail) che verifica la versione del kernel, la presenza di patch, le configurazioni del kernel, la disponibilità dei socket AF_ALG, i binari setuid e le mitigazioni per determinare lo stato di vulnerabilità sui sistemi Linux.
Solo rilevamento. Un PoC funzionante esiste già su copy.fail/#exploit. Questo script è pensato per sysadmin e team di sicurezza che devono determinare dove sono vulnerabili — o ancora vulnerabili dopo l'applicazione delle patch.
Il 29 aprile 2026, una vulnerabilità chiamata Copy Fail (CVE-2026-31431) è stata divulgata pubblicamente dal Xint Code Research Team. È un bug logico presente silenziosamente nel kernel Linux da circa 2017 — quasi un decennio — e consente a qualsiasi utente locale non privilegiato di ottenere root.
Non "ottenere root in condizioni specifiche con un po' di fortuna e un vento favorevole." Semplicemente... ottenere root. In modo affidabile. Praticamente su ogni principale distribuzione Linux.
Colpisce Ubuntu, Amazon Linux, RHEL, SUSE e qualsiasi altro sistema che esegue un kernel mainstream degli ultimi ~8 anni. Stesso script, nessuna ricompilazione, nessuna modifica per distribuzione richiesta.
Sì, è grave quanto sembra.
Il kernel Linux ha un sottosistema crittografico accessibile agli utenti non privilegiati tramite socket AF_ALG. Esiste un meccanismo chiamato splice() che può inoltrare dati di file direttamente in quel sottosistema senza copiarli — il che significa che la copia cache in memoria del kernel di un file (la "page cache") finisce all'interno di un'operazione crittografica.
Un algoritmo specifico — authencesn, usato per i numeri di sequenza estesi IPsec — ha una particolarità: usa il buffer di output come spazio di lavoro e scrive 4 byte leggermente oltre la posizione prevista. Normalmente innocuo. Ma quando le pagine della page cache di un binario setuid come /usr/bin/su finiscono concatenate in quel buffer di output (grazie a una "ottimizzazione" del 2017 in algif_aead.c), quei 4 byte finiscono direttamente nella copia cache del binario nel kernel.
L'operazione fallisce con un errore. Il kernel non marca mai quella pagina come sporca. Il file su disco è intatto. Gli strumenti di integrità dei file che verificano i checksum su disco non rilevano nulla di anomalo.
Ma la page cache è ciò che viene eseguito. E su è setuid root.
Il resoconto tecnico completo è su xint.io e merita davvero di essere letto.
Sette dalla versione originale più sei nuovi controlli aggiunti per colmare le lacune di rilevamento:
| # | Controllo | Cosa cerca |
|---|---|---|
| 1 | Versione del kernel | Questo kernel è nell'intervallo interessato (4.10–6.14)? |
| 2 | Presenza della patch | Il commit di correzione è effettivamente nel kernel in esecuzione? |
| 3 | Modulo algif_aead | Il modulo vulnerabile è caricato o caricabile? |
| 4 | CONFIG_CRYPTO_AUTHENC (nuovo) | CONFIG_CRYPTO_AUTHENC è integrato (=y) o un modulo (=m)? Questa singola opzione compila sia authenc che authencesn. Integrato significa che la mitigazione con blacklist di modprobe non serve a nulla. |
| 5 | CONFIG_CRYPTO_USER_API_AEAD (nuovo) | L'interfaccia utente AF_ALG AEAD è persino compilata? Se no, l'intero percorso di exploit è chiuso in fase di compilazione. |
| 6 | Socket AF_ALG | Un utente non privilegiato può aprirne uno adesso? |
| 7 | Python os.splice | Il percorso di exploit in puro Python è disponibile? |
| 8 | Binari setuid | Elenco esteso di target setuid-root leggibili presenti sul sistema. |
| 9 | Mitigazioni | AppArmor, SELinux, seccomp — cosa c'è in atto? |
| 10 | Namespace utente (nuovo) | I namespace utente non privilegiati sono abilitati? (Non blocca direttamente Copy Fail, ma influisce sulla più ampia superficie di privesc locale.) |
| 11 | Hugepage trasparenti (nuovo) | Stato THP — può influire sull'allineamento della page cache e sull'affidabilità dell'exploit. |
| 12 | Rilevamento ambiente (nuovo) | Contesto Docker/container/VM — i container condividono il kernel dell'host; è l'host che deve essere patchato. |
| 13 | Avviso utente root (nuovo) | Avvisa se si esegue come root, poiché diversi controlli danno falsi positivi per root indipendentemente dalle restrizioni per non privilegiati. |
Lo script Bash copre la stessa logica di rilevamento principale ma omette tre elementi specifici di Python:
| # | Controllo | Note |
|---|---|---|
| 1 | Versione del kernel | |
| 2 | Presenza della patch | |
| 3 | Modulo algif_aead | |
| 4 | Socket AF_ALG | Usa Python come helper se disponibile; altrimenti ripiega sull'inferenza dalla configurazione del kernel |
| 5 | Binari setuid | Elenco esteso, come nella versione Python |
| 6 | Mitigazioni | AppArmor, SELinux, seccomp |
| 7 | CONFIG_CRYPTO_AUTHENC | |
| 8 | Namespace utente | |
| 9 | Hugepage trasparenti | |
| 10 | Rilevamento ambiente |
Non presenti nello script shell (rispetto a Python):
| Controllo mancante | Motivo |
|---|---|
| CONFIG_CRYPTO_USER_API_AEAD | Non ancora implementato — pianificato |
| Disponibilità Python os.splice | Non applicabile a uno script shell |
| Avviso utente root | Non ancora implementato — pianificato |
Nessuno dei due script risolve o sfrutta nulla. Ti dicono la verità sul tuo sistema così puoi agire di conseguenza.
# Clona o scarica lo script, poi:
python3 cve-2026-31431-detect.py
Tutto qui. Report con codici colore e un riepilogo alla fine.
Lo script esce con un codice non zero in caso di risultati vulnerabili, rendendolo adatto all'uso in pipeline:
| Codice | Significato |
|---|---|
0 | Nessuna condizione vulnerabile trovata |
1 | Una o più condizioni vulnerabili trovate |
# Esempio: fai fallire uno step CI se l'host è vulnerabile
python3 cve-2026-31431-detect.py
rc=$?
if [ $rc -eq 1 ]; then
echo "VULNERABILE — blocca il deployment"
elif [ $rc -ne 0 ]; then
echo "ERRORE — lo script non è riuscito a completare (exit $rc)"
fi
CVE-2026-31431 'Copy Fail' — Rilevamento vulnerabilità
Corruzione page cache authencesn / escalation privilegi locale
Esecuzione come uid=1001, euid=1001
=== Versione del kernel ===
[VULNERABILE] Versione del kernel
Motivo : Il kernel è nell'intervallo vulnerabile (4.10 – 6.14)
Dettaglio : Release: 6.12.0-124.45.1.el10_1 — lo stato della patch deve essere confermato
=== CONFIG_CRYPTO_AUTHENC (Configurazione kernel) ===
[VULNERABILE] CONFIG_CRYPTO_AUTHENC
Motivo : Compilato come modulo (=m): si carica automaticamente su bind() AF_ALG; la blacklist di modprobe è la mitigazione corretta
=== CONFIG_CRYPTO_USER_API_AEAD (Configurazione kernel) ===
[VULNERABILE] CONFIG_CRYPTO_USER_API_AEAD
Motivo : L'interfaccia AEAD AF_ALG è un modulo caricabile — gli utenti non privilegiati possono accedere al sottosistema crittografico tramite socket AF_ALG
...
IL SISTEMA È PROBABILMENTE VULNERABILE A CVE-2026-31431
Azioni consigliate:
1. Applica l'aggiornamento del kernel della tua distribuzione per CVE-2026-31431
2. Fino alla patch, metti in blacklist il modulo:
echo 'install algif_aead /bin/false' > /etc/modprobe.d/disable-algif-aead.conf
rmmod algif_aead 2>/dev/null
NOTA: questo è efficace SOLO quando CONFIG_CRYPTO_AUTHENC=m (modulo).
Se CONFIG_CRYPTO_AUTHENC=y (integrato), la patch è l'unica soluzione.
Uno script Bash complementare (cve-2026-31431-detect.sh) è disponibile per ambienti in cui Python non è presente o dove si preferiscono strumenti nativi della shell. Esegue 10 dei 13 controlli — vedi la tabella di confronto dei controlli sopra per i dettagli sulle differenze.
# Esecuzione base
bash cve-2026-31431-detect.sh
# Output JSON — adatto per ingestione SIEM, fatti Ansible, aggregazione log
bash cve-2026-31431-detect.sh --json > scan-results.json
# Modalità silenziosa — stampa solo il riepilogo (utile nei log CI)
bash cve-2026-31431-detect.sh --quiet
# Disabilita colore ANSI (per file di log)
bash cve-2026-31431-detect.sh --no-colour
Lo script shell usa gli stessi codici di uscita (0 = OK, 1 = vulnerabile) e produce un output JSON equivalente per il consumo in pipeline. Dove Python 3 è disponibile sul sistema, lo script shell lo usa per eseguire il test live del socket AF_ALG; altrimenti ripiega sull'inferenza dalla configurazione del kernel.
La vera soluzione è applicare la patch al kernel. Controlla gli advisory di sicurezza della tua distribuzione.
| Distribuzione | Dove guardare |
|---|---|
| Ubuntu | ubuntu.com/security/CVE-2026-31431 |
| RHEL / Amazon Linux | dnf update kernel |
| SUSE | zypper update kernel-default |
| Debian | apt update && apt upgrade |
Se il controllo CONFIG_CRYPTO_AUTHENC riporta =m (compilato come modulo, non integrato), puoi metterlo in blacklist:
echo 'install algif_aead /bin/false' > /etc/modprobe.d/disable-algif-aead.conf
rmmod algif_aead 2>/dev/null
Importante: questa mitigazione non ha effetto se
CONFIG_CRYPTO_AUTHENC=y(integrato). In quel caso, la patch al kernel è l'unica soluzione. Il controllo CONFIG_CRYPTO_AUTHENC nello script ti dice in quale situazione ti trovi. Nota cheCONFIG_CRYPTO_AUTHENCè la chiave corretta della configurazione del kernel — compila sia i moduliauthenccheauthencesnda una singola opzione.
Questo potrebbe influire su IPsec se lo stai usando — verifica prima di distribuire su larga scala.
La correzione a monte è questo commit — annulla l'ottimizzazione AEAD in-place del 2017 in algif_aead.c, separando le scatterlist di origine e destinazione così che le pagine della page cache non possano più finire nella destinazione scrivibile.
Se stai eseguendo questo script all'interno di un container Docker, pod Kubernetes o altro ambiente containerizzato, lo script ti avviserà: i container condividono il kernel dell'host. La vulnerabilità risiede nel kernel, non nell'immagine del container. Devi valutare e patchare l'host.
# GitHub Actions
# Lo step fallirà naturalmente e bloccherà la pipeline quando lo script esce con 1.
# Nessuna configurazione extra necessaria — i codici di uscita non zero fanno fallire gli step di default.
- name: Controllo CVE-2026-31431
run: |
python3 cve-2026-31431-detect.py
rc=$?
if [ $rc -eq 1 ]; then
echo "VULNERABILE — pipeline bloccata"
exit 1
elif [ $rc -ne 0 ]; then
echo "ERRORE — lo script di rilevamento non è riuscito a completare (exit $rc)"
exit $rc
fi
# Ansible
# Usa playbook_dir per garantire che il percorso dello script si risolva correttamente.
# failed_when controlla qualsiasi uscita non zero (vulnerabilità O errore dello script).
- name: Controllo per CVE-2026-31431
script: "{{ playbook_dir }}/cve-2026-31431-detect.py"
register: cve_check
failed_when: cve_check.rc != 0
# Controllo Nagios / monitoraggio (script shell — supporta i codici di uscita nativamente)
bash cve-2026-31431-detect.sh --quiet
# exit 0 = OK, exit 1 = CRITICO (vulnerabile)
# Output JSON per SIEM / aggregazione log (script shell)
bash cve-2026-31431-detect.sh --json --quiet > /var/log/cve-2026-31431-$(hostname)-$(date +%Y%m%d).json
| Data | Evento |
|---|---|
| 2026-03-23 | Segnalato al team di sicurezza del kernel Linux |
| 2026-03-24 | Riconosciuto |
| 2026-03-25 | Patch proposte e revisionate |
| 2026-04-01 | Correzione committata nel kernel mainline |
| 2026-04-22 | Assegnato CVE-2026-31431 |
| 2026-04-29 | Divulgazione pubblica |
Crediti a Taeyang Lee di Theori per l'intuizione di ricerca originale, e al Xint Code Research Team per il resoconto completo della divulgazione.
Trovato un falso positivo? Una distribuzione che questo script non rileva? Una configurazione del kernel che dovrebbe essere controllata? Le PR sono benvenute. L'obiettivo è un segnale accurato, non solo testo rosso spaventoso.
Questo strumento è fornito così com'è per scopi di sicurezza difensiva. Puntalo su sistemi che sei autorizzato a valutare. Non fare cose strane.