
Toolkit di ricerca e rilevamento per la LPE del kernel Linux CVE-2026-31431, che include analisi degli exploit, regole YARA, rilevamento auditd/Falco, guida alla patch e ambiente di laboratorio.
algif_aeadCISA KEV | CVSS 7.8 ALTO | Interessa i kernel Linux 4.14 – inizio 2026 (~9 anni)
CVE-2026-31431, soprannominata "Copy Fail", è una vulnerabilità di escalation dei privilegi locali (LPE) ad alta gravità nel sottosistema crittografico del kernel Linux. Un utente locale con privilegi bassi può ottenere root in pochi secondi su qualsiasi sistema non patchato.
| Attributo | Valore |
|---|---|
| CVE | CVE-2026-31431 |
| Soprannome | Copy Fail |
| CVSS v3.1 | 7.8 ALTO |
| Vettore di Attacco | Locale |
| Privilegi Richiesti | Bassi |
| Interazione Utente | Nessuna |
| Componente | crypto/algif_aead.c — template authencesn |
| Introdotta | 2017 (commit 72548b093ee3) |
| Divulgata | 2026 |
| Anni di Silenzio | ~9 anni |
| CISA KEV | Sì |
| PoC Pubblico | Sì (script Python autonomo da 732 byte) |
detection/check_vulnerable.sh prima e dopo la correzione.CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
| Metrica | Valore | Motivazione |
|--------|-------|-----------|
| Vettore di attacco | **Locale** | Richiede accesso alla shell (SSH, exec in container, fisico) |
| Complessità dell'attacco | **Bassa** | Affidabile, completamente automatizzato — nessuna race condition richiesta |
| Privilegi richiesti | **Bassi** | Qualsiasi account utente non privilegiato |
| Interazione utente | **Nessuna** | Nessuna interazione con la vittima richiesta |
| Riservatezza | **Alta** | Compromissione completa del sistema |
| Integrità | **Alta** | Compromissione completa del sistema |
| Disponibilità | **Alta** | Compromissione completa del sistema |
### Panorama delle minacce
| Fattore | Valutazione |
|--------|-----------|
| Disponibilità del PoC | Pubblico, armato, Python standalone da 732 byte |
| Affidabilità dell'exploit | Alta — funziona sulle distro testate senza modifiche |
| Difficoltà di rilevamento | Alta — nessuna scrittura su disco, nessuna dirty page |
| Competenza richiesta all'attaccante | Bassa — script kiddie con PoC pubblico |
| CISA KEV | Aggiunto nel 2026 — monitorato attivamente |
| Microsoft Defender | Segnalato come sotto indagine attiva |
### Ambienti interessati
| Ambiente | Rischio |
|-------------|------|
| Server Linux bare-metal | Critico |
| VM Linux (cloud o on-premise) | Critico |
| Nodi Kubernetes | Critico (consente anche la fuga dal container) |
| Host Docker | Critico |
| Hosting condiviso / multi-tenant | Critico |
| WSL2 / Linux su Windows | Valutare in base alla versione del kernel |
---
## 3. Approfondimento tecnico
### 3.1 Contesto: AF_ALG e AEAD
Il kernel Linux espone le operazioni crittografiche agli utenti tramite **socket AF_ALG** (`AF_ALG = 38`). Questa interfaccia (`algif_aead`) consente alle applicazioni non privilegiate di invocare gli acceleratori hardware crittografici del kernel senza necessitare di codice in modalità kernel.
Gli algoritmi **AEAD** (Authenticated Encryption with Associated Data) come AES-GCM e ChaCha20-Poly1305 sono ampiamente utilizzati per TLS, crittografia del disco e protocolli VPN. Il template vulnerabile è `authencesn` — una composizione AEAD che utilizza `hmac(sha256)` + `cbc(aes)` con supporto Extended Sequence Number (ESN), comunemente usato in IPsec.
### 3.2 Causa principale
Nel 2017, il commit `72548b093ee3` ha introdotto l'**operazione AEAD in-place** in `algif_aead` come ottimizzazione delle prestazioni — consentendo al motore crittografico di leggere e scrivere lo stesso buffer. Questo era difettoso:```
The bug chain:
1. Caller binds AF_ALG socket to:
authencesn(hmac(sha256),cbc(aes))
2. Caller sends a decryption request via sendmsg() with specific flags
3. Caller uses splice() to feed PAGE CACHE PAGES from an open file
descriptor directly into the socket's scatterlist
4. The authencesn template, during ESN header processing, uses the
OUTPUT BUFFER as scratch space — writing 4 bytes past the
expected output boundary
5. Because the scatterlist contains page cache pages (not private
copies), this scratch write lands DIRECTLY IN THE PAGE CACHE
6. Page cache is shared kernel-wide — all processes reading the
same file now see the modified bytes
Key insight: splice() is zero-copy — it hands page cache references
to the socket. The in-place "optimization" then writes INTO those
pages. No dirty bit is set because the write goes through the crypto
engine, not the normal write path.
La vulnerabilità fornisce una scrittura controllata di 4 byte nella cache delle pagine di qualsiasi file che l'attaccante può aprire in lettura:
La scrittura è ripetibile — l'exploit esegue in loop la scrittura di 4 byte per applicare patch a sequenze di codice più lunghe.
[1] Open /usr/bin/su (or any setuid-root binary) for reading ↓ [2] Map a copy to find target instruction bytes (e.g., UID check, execve path, security gate) ↓ [3] Compute exact page cache offset of target bytes ↓ [4] Set up AF_ALG socket → authencesn(hmac(sha256),cbc(aes)) ↓ [5] splice() the target binary's page cache into the socket ↓ [6] Trigger decryption → authencesn scratch write patches the target bytes in page cache (4 bytes per iteration) ↓ [7] Repeat for each 4-byte patch needed ↓ [8] Execute /usr/bin/su → runs root-owned setuid binary but now with attacker-controlled code in page cache ↓ [9] Root shell
### 3.5 Perché le Difese Standard Falliscono
| Difesa | Bypassata? | Motivo |
|---------|-----------|--------|
| Monitoraggio dell'Integrità dei File (Tripwire/AIDE) | **Sì** | Nessuna modifica su disco |
| Controlli hash dei file IDS | **Sì** | I byte su disco rimangono invariati |
| Watch sui file `inotify` | **Sì** | Nessun evento di scrittura VFS |
| SELinux / AppArmor | **Parziale** | Controlla il processo, non la scrittura nella page cache tramite il motore crittografico |
| Montaggi read-only | **Sì** | La page cache viene modificata in memoria, non tramite il mount |
| `watch` di auditd sul binario | **Sì** | Audit osserva le scritture VFS — questo bypassa la VFS |
### 3.6 Versioni del Kernel Interessate
| Branch | Vulnerabile Fino a | Corretto Da |
|--------|-------------------|------------|
| 4.14.x | Tutte (origine della vulnerabilità) | Nessun fix upstream (EOL) |
| 5.4.x (LTS) | Tutte | Richiesto backport della distribuzione |
| 5.10.x (LTS) | Tutte | Richiesto backport della distribuzione |
| 5.15.x (LTS) | Tutte | Richiesto backport della distribuzione |
| 6.1.x (LTS) | ≤ 6.1.129 | **6.1.130+** |
| 6.6.x (LTS) | ≤ 6.6.86 | **6.6.87+** |
| 6.12.x (LTS) | ≤ 6.12.22 | **6.12.23+** |
| 6.15-rc | Corretto in rc | **6.15-rc+** |
> I kernel delle distribuzioni potrebbero aver applicato il backport del fix con numeri di versione diversi. Controlla sempre l'advisory di sicurezza della tua distribuzione.
---
## 4. Metodologia di Attacco — Red Team
> **Autorizzazione Richiesta.** Questa sezione esiste per aiutare i difensori a comprendere la prospettiva dell'attaccante. Esegui solo su sistemi di tua proprietà o per cui hai esplicita autorizzazione scritta per i test.
### 4.1 Prerequisiti
- Shell a bassi privilegi sul target (SSH, container exec, catena RCE)
- Python 3.10+ **oppure** binario C compilato
- Kernel non patchato con `algif_aead` disponibile
### 4.2 Ricognizione```bash
# Check if vulnerable
uname -r
cat /proc/crypto | grep -A10 "authencesn"
lsmod | grep algif_aead
# Verify setuid target exists
ls -la /usr/bin/su /usr/bin/sudo /usr/bin/passwd
I ricercatori originali (Theori) hanno rilasciato un PoC Python autonomo completamente funzionante di 732 byte:
python3 copy_fail_exp.py
python3 copy_fail_exp.py /usr/bin/passwd
Una copia locale è disponibile in `exploit/poc.py`. Consulta `exploit/README.md` per l'analisi tecnica.
### 4.4 Scenario di fuga dal container
Poiché la cache delle pagine Linux è condivisa tra tutti i processi sullo stesso host (inclusi host e container):```
Attacker in container → patches /usr/bin/su in HOST page cache
Host user runs su → executes attacker code as root on host
Questo funziona anche da container non privilegiati, purché il kernel dell'host sia vulnerabile.
Questo è il focus principale di questo repository.
Esegui lo script di rilevamento su qualsiasi sistema Linux:```bash chmod +x detection/check_vulnerable.sh sudo ./detection/check_vulnerable.sh
**Cosa controlla:**
- Versione del kernel rispetto agli intervalli noti come vulnerabili
- Stato di caricamento del modulo `algif_aead` e stato della blacklist
- Disponibilità di `authencesn` in `/proc/crypto`
- Integrità della cache delle pagine dei binari setuid (richiede root)
- Stato delle patch specifiche per distribuzione
- Processi in esecuzione per indicatori di sfruttamento attivo
Un report con timestamp viene salvato in `/tmp/cve-2026-31431-report-*.txt`.
### 5.2 Rilevamento YARA
Due regole YARA sono fornite in `detection/yara/`:
| File della regola | Scopo |
|-----------|---------|
| `cve_2026_31431_base.yar` | Corrisponde esattamente al PoC pubblico noto |
| `cve_2026_31431_enhanced.yar` | Rileva exploit offuscati, compilati e varianti |```bash
# Install YARA
apt-get install yara # Debian/Ubuntu
dnf install yara # RHEL/Fedora
apk add yara # Alpine
# Scan running process executables
sudo yara -r detection/yara/cve_2026_31431_enhanced.yar /proc/*/exe 2>/dev/null
# Scan common dropper locations
sudo yara -r detection/yara/cve_2026_31431_enhanced.yar /home /tmp /var/tmp /dev/shm
# Scan uploaded files / quarantine
yara detection/yara/cve_2026_31431_base.yar <suspect_file>
Perché le regole avanzate sono importanti: gli attaccanti possono offuscare il PoC Python pubblico (codificare stringhe in base64, XOR-encodare il nome dell'algoritmo, compilare in un binario C, rimuovere i simboli). La regola avanzata rileva queste varianti prendendo di mira gli invarianti che non possono essere rimossi senza rompere l'exploit:
authencesn come nome dell'algoritmosplice() per ottenere accesso zero-copy alla page cache38)Distribuire in /etc/audit/rules.d/cve-2026-31431.rules:```bash
-a always,exit -F arch=b64 -S socket -F a0=38 -k cve_2026_31431_afalg
-a always,exit -F arch=b64 -S splice -k cve_2026_31431_splice
-a always,exit -F arch=b64 -S init_module -S finit_module -k cve_2026_31431_modload
-a always,exit -F arch=b64 -S execve -F euid=0 -F auid>=1000 -k cve_2026_31431_suid_exec
Reload:```bash
augenrules --load && service auditd restart
Query per tentativi di sfruttamento:```bash
ausearch -k cve_2026_31431_afalg --start today
ausearch -k cve_2026_31431_afalg -k cve_2026_31431_splice --start today
### 5.4 Rilevamento Falco / eBPF
Aggiungi a `/etc/falco/rules.d/cve-2026-31431.yaml`:```yaml
- rule: CVE-2026-31431 AF_ALG Socket Creation
desc: Detects unprivileged process creating AF_ALG socket (family 38) — required step for Copy Fail exploit
condition: >
syscall.type = socket and
evt.arg.domain = 38 and
not user.uid = 0 and
not proc.name in (known_crypto_daemons)
output: >
CVE-2026-31431 exploitation attempt - AF_ALG socket (user=%user.name
uid=%user.uid pid=%proc.pid cmd=%proc.cmdline)
priority: CRITICAL
tags: [cve-2026-31431, lpe, kernel, crypto]
- list: known_crypto_daemons
items: [strongswan, charon, pluto, openssl]
- rule: CVE-2026-31431 Splice After AF_ALG
desc: Detects splice() syscall shortly after AF_ALG socket creation — exploitation sequence
condition: >
syscall.type = splice and
not user.uid = 0 and
evt.elapsed < 5000000000
output: >
CVE-2026-31431 splice after AF_ALG socket (user=%user.name pid=%proc.pid)
priority: CRITICAL
tags: [cve-2026-31431, lpe]
Poiché l'exploit modifica la cache di pagina senza scrivere su disco, i tool FIM standard non la rilevano. Questa verifica individua lo sfruttamento attivo:```bash #!/bin/bash
SETUID_BINS=("/usr/bin/su" "/usr/bin/sudo" "/usr/bin/passwd")
for binary in "${SETUID_BINS[@]}"; do [[ -f "$binary" ]] || continue LIVE_HASH=$(sha256sum "$binary" | awk '{print $1}') echo 3 | sudo tee /proc/sys/vm/drop_caches > /dev/null # flush page cache DISK_HASH=$(sha256sum "$binary" | awk '{print $1}') if [[ "$LIVE_HASH" != "$DISK_HASH" ]]; then echo "CRITICAL: Page cache tampering detected on $binary" echo " Pre-flush: $LIVE_HASH" echo " Post-flush: $DISK_HASH" else echo "OK: $binary page cache matches disk" fi done
> **Nota di produzione:** `drop_caches` comporta un calo delle prestazioni. Eseguire durante le finestre di manutenzione o prima su sistemi non critici.
### 5.6 Indicatori di Compromissione (IoC)
| Tipo di IoC | Indicatore | Confidenza |
|----------|-----------|-----------|
| Stringa (binario/script) | `authencesn(hmac(sha256),cbc(aes))` | Alta |
| Byte esadecimali | `78 DA AB 77 F5 71 63 62 64 64` (header payload zlib) | Alta |
| Sequenza di syscall | `socket(38,5,0)` → `bind()` → `splice()` | Alta |
| Rete | Nessuno — puramente locale | N/D |
| File | Nessuna scrittura su disco (stealth) | — |
| Processo | Processo Python/C di breve durata con socket AF_ALG | Media |
| Cache di pagina | Cache di pagina del binario setuid ≠ hash su disco | Critica |
### 5.7 Query di Rilevamento SIEM
**Splunk (sorgente auditd):**```spl
index=linux_audit sourcetype=auditd action=SYSCALL syscall=socket a0="0x26"
| join pid [
search index=linux_audit sourcetype=auditd action=SYSCALL syscall=splice
]
| where (_time - join_time) < 30
| table _time host user pid cmd a0
| eval severity="CRITICAL"
Elastic KQL:```kql event.action: "SYSCALL" AND process.args: "socket" AND auditd.data.a0: "0x26" AND NOT user.id: "0"
**Microsoft Sentinel (KQL):**```kql
Syslog
| where Facility == "kern" or ProcessName == "audit"
| where SyslogMessage contains "socket" and SyslogMessage contains "a0=0x26"
| extend UserName = extract("uid=([0-9]+)", 1, SyslogMessage)
| where UserName != "0"
| project TimeGenerated, Computer, UserName, SyslogMessage
| order by TimeGenerated desc
Esegui lo script di patch automatico:```bash chmod +x patch/patch.sh sudo ./patch/patch.sh
### 6.1 Mitigazione Immediata (Nessun Riavvio Richiesto*)```bash
# Blacklist the module permanently
echo "install algif_aead /bin/false" | sudo tee /etc/modprobe.d/disable-algif-aead.conf
echo "install authencesn /bin/false" | sudo tee -a /etc/modprobe.d/disable-algif-aead.conf
# Unload if currently loaded
sudo rmmod algif_aead 2>/dev/null || echo "Not loaded — mitigation active after config"
# Verify
lsmod | grep algif_aead && echo "WARNING: still loaded — reboot needed" || echo "OK: not loaded"
*Se algif_aead è già caricato, è necessario un riavvio affinché la blacklist abbia pieno effetto.
Effetti collaterali: Le applicazioni che utilizzano l'interfaccia AEAD del kernel tramite AF_ALG (poco comune — la maggior parte usa OpenSSL in userspace) potrebbero fallire. TLS standard, crittografia dei dischi e strumenti VPN generalmente non sono interessati.
kubectl get nodes -o wide
kubectl drain --ignore-daemonsets --delete-emptydir-data
kubectl uncordon
Usa auto-upgrader di nodi (Karpenter, Managed Node Groups) o la rotazione del pool di nodi del cluster dove disponibile.
### 6.4 Verifica post-patch```bash
# Re-run detection script
sudo ./detection/check_vulnerable.sh
# Quick manual verification
uname -r # confirm new kernel version
lsmod | grep algif_aead # should be empty
cat /proc/crypto | grep authencesn # should return nothing (or still listed but module blacklisted)
È fornito un laboratorio Docker minimale basato su Alpine per testare in sicurezza gli strumenti di rilevamento.```bash cd lab/ docker compose up -d docker exec -it cve-2026-31431-lab /bin/sh
/cve-2026-31431/detection/check_vulnerable.sh
> **Importante:** I container Docker condividono il kernel dell'host. Il laboratorio testa lo stato di vulnerabilità **del kernel del tuo host**. I risultati delle vulnerabilità riflettono il sistema host effettivo — questo è intenzionale per una valutazione realistica.
Per test isolati con una versione specifica del kernel vulnerabile, utilizza una VM dedicata con un kernel fissato. Consulta `lab/README.md` per le indicazioni sulla configurazione della VM.
---
## 8. Riferimenti
| Risorsa | Link |
|----------|------|
| Advisory NVD | https://nvd.nist.gov/vuln/detail/CVE-2026-31431 |
| Ricerca originale | https://copy.fail |
| Approfondimento tecnico | https://xint.io/blog/copy-fail-linux-distributions |
| PoC pubblico | https://github.com/theori-io/copy-fail-CVE-2026-31431 |
| Catalogo KEV CISA | https://www.cisa.gov/known-exploited-vulnerabilities-catalog |
| Fix del kernel — Commit di revert | `a664bf3d603d` / `fafe0fa2995a` |
| Commit vulnerabile | `72548b093ee3` |
| Advisory Microsoft Defender | Blog Microsoft Defender Threat Intelligence |
---
## Struttura del repository```
cve-2026-31431/
├── README.md ← This document
├── exploit/
│ ├── README.md ← Technical exploit breakdown
│ └── poc.py ← Public PoC (theori-io, for reference)
├── detection/
│ ├── README.md ← Detection guide
│ ├── check_vulnerable.sh ← Vulnerability & IoC detection script
│ └── yara/
│ ├── cve_2026_31431_base.yar ← Detects known public PoC
│ └── cve_2026_31431_enhanced.yar ← Detects obfuscated/compiled variants
├── patch/
│ ├── README.md ← Remediation guide
│ └── patch.sh ← Automated patch/mitigation script
└── lab/
├── README.md ← Lab setup guide
├── Dockerfile ← Alpine-based lab container
└── docker-compose.yml ← Lab orchestration
Questa ricerca è fornita esclusivamente a scopo educativo e di sicurezza difensiva. Tutti gli strumenti sono progettati per aiutare i difensori a rilevare e correggere la CVE-2026-31431 sui sistemi che sono autorizzati a proteggere.
Repository mantenuto da rippsec
| Proprietà | Valore |
|---|
| Dimensione della scrittura | 4 byte |
| Controllo dell'offset | Sì — controllato dall'attaccante tramite l'offset di splice |
| Destinazione | Cache delle pagine di qualsiasi file leggibile |
| Marcatura della pagina sporca | Nessuna |
| Modifica su disco | Nessuna |
| Aggiornamento del timestamp | Nessuno |
| Voce nel log del kernel | Nessuna (a meno che auditd non sia configurato) |
| Tecnica | ID | Note |
|---|
| Sfruttamento per l'Elevazione dei Privilegi | T1068 | Tecnica principale |
| Abuso del Meccanismo di Controllo dell'Elevazione: Setuid/Setgid | T1548.001 | Hijack del binario Setuid |
| Hijack del Flusso di Esecuzione | T1574 | Patch binaria in memoria |
| Rimozione degli Indicatori: Timestomp | T1070.006 | Nessun timestamp aggiornato |
| Esecuzione di Comandi Indiretta | T1202 | Il binario patchato esegue la shell |
| Distribuzione | Comando di aggiornamento |
|---|
| Ubuntu / Debian | apt-get update && apt-get upgrade linux-image-generic && reboot |
| RHEL / CentOS / Rocky | dnf update kernel && reboot |
| Amazon Linux 2 | yum update kernel && reboot |
| Amazon Linux 2023 | dnf update kernel && reboot |
| SUSE / SLES | zypper update kernel-default && reboot |
| Arch Linux | pacman -Syu linux && reboot |
| Alpine Linux | apk update && apk upgrade linux-lts && reboot |
| Debian | apt-get update && apt-get upgrade linux-image-amd64 && reboot |