
Regole di rilevamento, firme YARA, regole auditd/Wazuh e modelli di eventi MISP per la vulnerabilità LPE CVE-2026-31431 del kernel Linux (Copy Fail). Include IoC, passaggi di mitigazione e analisi dell'exploit.
Pubblicato: 2026-04-30
CVSSv3: 7.8 (Alto)
Tipo: Escalation dei privilegi locale (LPE)
Sottosistema: template crittografico algif_aead / authencesn del kernel Linux
Versioni interessate: kernel Linux 4.14 – 6.18.21 (praticamente tutte le distribuzioni dal 2017)
Riferimenti:
CVE-2026-31431 è un difetto logico introdotto nel kernel 4.14 (2017) all'intersezione di tre modifiche indipendenti:
authencesn (aggiunto nel 2011 per il supporto ESN in IPsec) scrive 4 byte di dati scratch oltre il confine del suo buffer di output.AF_ALG ha ottenuto il supporto AEAD nel 2015, consentendo agli utenti dello spazio utente di inviare dati tramite splice() da file nella page cache.algif_aead.c è stato ottimizzato per operare in-place (req->src == req->dst), inserendo pagine vive della page cache in uno scatterlist scrivibile.Risultato: un utente non privilegiato può scrivere esattamente 4 byte controllati dall'attaccante nella copia nella page cache del kernel di qualsiasi file leggibile — inclusi binari setuid e /etc/passwd — senza toccare il file su disco. Il PoC funzionante è uno script Python di 732 byte. Nessuna race condition. Nessun offset per distribuzione. Affidabile su Ubuntu, RHEL, Amazon Linux e SUSE.
Attacker opens AF_ALG socket (family 38, type 5) └─ Binds to "authencesn(hmac(sha256),cbc(aes))" └─ Sets SOL_ALG (279) options including key and authsize └─ Accepts a connection socket
Attacker opens target file (e.g., /etc/passwd) read-only └─ Uses splice() to feed page-cache pages into the AEAD socket's RX buffer └─ Sends crafted AAD via sendmsg() — bytes 4–7 of AAD = attacker-controlled write value
authencesn performs in-place decryption: └─ scatterwalk_map_and_copy writes seqno_lo into the chained page-cache page └─ recvmsg() returns an error (HMAC fails — expected), but the write already happened
Page-cache now contains attacker-modified copy of the file └─ Kernel executes from page-cache, not disk └─ On-disk file is UNCHANGED — file integrity tools see nothing
Il PoC prende di mira `/etc/passwd`: trova l'offset del campo UID dell'utente in esecuzione e lo sovrascrive con `0000`, quindi invoca `su` per ottenere una shell di root.
---
## Limitazioni del rilevamento
> **Leggi questa sezione prima di implementare qualsiasi regola riportata di seguito.**
Questo exploit ha due proprietà che limitano significativamente la copertura del rilevamento:
**1. La scrittura avviene nella page cache, non nel filesystem.**
Qualsiasi strumento di rilevamento che monitora gli eventi del filesystem — `inotify`, `fanotify`, AIDE, Tripwire, auditd path watches — **non** osserverà la modifica. Il file su disco non viene mai scritto. Ciò significa che i flag `-p w` (write) nei path watch di auditd per `/usr/bin/su` o `/etc/passwd` non rileveranno la scrittura effettiva dello sfruttamento.
**2. Il meccanismo utilizza interfacce kernel legittime.**
I socket `AF_ALG`, `splice()` e `authencesn` hanno tutti usi legittimi (IPsec, self-test del kernel, I/O in stile sendfile). Il rilevamento deve concentrarsi sulla *combinazione* di queste primitive piuttosto che su una sola in isolamento; ci si devono aspettare falsi positivi su sistemi che eseguono IPsec o test crittografici del kernel.
**Cosa il rilevamento PUÒ individuare:**
- La syscall `socket(AF_ALG, SOCK_SEQPACKET, 0)`
- La syscall `splice()` correlata alla precedente, soprattutto in prossimità dell'accesso a binari setuid
- Lo script PoC stesso (tramite YARA)
- La stringa dell'algoritmo specifica `authencesn(hmac(sha256),cbc(aes))` nella memoria di processo o nei file di script
**Cosa il rilevamento NON PUÒ individuare:**
- La scrittura effettiva nella page cache (in memoria, nessun evento del filesystem)
- L'uso post-exploitation della voce modificata nella page cache (sembra una normale chiamata a `su` o `passwd`)
- Varianti che evitano Python o la stringa dell'algoritmo specifica
---
## Mitigazione immediata
Prima di implementare le regole di rilevamento, applica questa mitigazione su qualsiasi host non patchato:```bash
# Disable algif_aead kernel module — blocks the exploit primitive entirely
echo "install algif_aead /bin/false" | sudo tee /etc/modprobe.d/disable-algif-aead.conf
sudo rmmod algif_aead 2>/dev/null || true
Verifica che la mitigazione sia attiva utilizzando il rilevatore ufficiale:```bash
python3 test_cve_2026_31431.py
> **Nota:** Il comando `rmmod` fallirà se il modulo non è attualmente caricato; questo è accettabile. La configurazione `modprobe.d` previene caricamenti futuri. Questa mitigazione non ha alcun impatto su TLS standard, SSH o carichi di lavoro di crittografia del filesystem — influisce solo su IPsec con Extended Sequence Numbers che utilizzano il template `authencesn`, il quale è insolito al di fuori di gateway VPN dedicati.
---
## Regola YARA
Salva come `cve_2026_31431.yar`
> **Ambito di scansione:** Questa regola è progettata per scansionare file script Python su disco o estratti da dump di memoria. Corrisponderà al PoC noto e a varianti simili. NON rileverà l'attività di sfruttamento a livello di syscall — utilizza le regole auditd/Wazuh per quello.```yara
rule CVE_2026_31431_CopyFail_PoC_HighConfidence {
meta:
description = "High-confidence match: CVE-2026-31431 Copy Fail PoC or close variant"
author = "Detection Engineering"
reference = "https://xint.io/blog/copy-fail-linux-distributions"
cve = "CVE-2026-31431"
date = "2026-04-30"
severity = "High"
cvss = "7.8"
strings:
// Algorithm string unique to this exploit path — very high fidelity
$alg_full = "authencesn(hmac(sha256),cbc(aes))" ascii
// Specific socket call signature from PoC: AF_ALG=38, SOCK_SEQPACKET=5
$socket_call = "socket(38,5,0)" ascii
// SOL_ALG socket option (decimal 279)
$solalg = "setsockopt(279" ascii
// Hex key/iv payload written via setsockopt in PoC
$key_payload = "0800010000000010" ascii
// splice() usage in context of AEAD operations
$splice = "splice(" ascii
// Target indicators from PoC (page-cache corruption targets)
$target_passwd = "/etc/passwd" ascii
$target_su = "/usr/bin/su" ascii
// AF_ALG aead bind strings
$aead_bind = "\"aead\"" ascii