
Toolkit de investigación y detección para LPE CVE-2026-31431 del kernel de Linux, que incluye análisis de exploits, reglas YARA, detección con auditd/Falco, guía de parcheo y entorno de laboratorio.
algif_aeadCISA KEV | CVSS 7.8 ALTO | Afecta a kernels de Linux 4.14 – principios de 2026 (~9 años)
CVE-2026-31431, apodado «Copy Fail», es una vulnerabilidad de escalada de privilegios local (LPE) de alta severidad en el subsistema criptográfico del kernel de Linux. Un usuario local con privilegios bajos puede escalar a root en segundos en cualquier sistema sin parchear.
detection/check_vulnerable.sh antes y después de la remediación.CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
| Métrica | Valor | Justificación |
|--------|-------|-----------|
| Vector de ataque | **Local** | Requiere acceso a shell (SSH, exec de contenedor, físico) |
| Complejidad del ataque | **Baja** | Fiable, totalmente automatizado — no requiere condición de carrera |
| Privilegios requeridos | **Bajos** | Cualquier cuenta de usuario sin privilegios |
| Interacción del usuario | **Ninguna** | No se necesita interacción de la víctima |
| Confidencialidad | **Alta** | Compromiso total del sistema |
| Integridad | **Alta** | Compromiso total del sistema |
| Disponibilidad | **Alta** | Compromiso total del sistema |
### Panorama de amenazas
| Factor | Evaluación |
|--------|-----------|
| Disponibilidad de PoC | Pública, armada, Python independiente de 732 bytes |
| Fiabilidad del exploit | Alta — funciona en las distros probadas sin modificación |
| Dificultad de detección | Alta — sin escrituras en disco, sin páginas sucias |
| Habilidad requerida del atacante | Baja — script kiddie con PoC público |
| CISA KEV | Añadido en 2026 — monitorizado activamente |
| Microsoft Defender | Marcado como bajo investigación activa |
### Entornos afectados
| Entorno | Riesgo |
|-------------|------|
| Servidores Linux en bare-metal | Crítico |
| VMs Linux (nube o locales) | Crítico |
| Nodos Kubernetes | Crítico (también permite escape de contenedor) |
| Hosts Docker | Crítico |
| Hosting compartido / multiinquilino | Crítico |
| WSL2 / Linux en Windows | Evaluar según la versión del kernel |
---
## 3. Inmersión técnica profunda
### 3.1 Antecedentes: AF_ALG y AEAD
El kernel de Linux expone operaciones criptográficas al espacio de usuario mediante **sockets AF_ALG** (`AF_ALG = 38`). Esta interfaz (`algif_aead`) permite que aplicaciones sin privilegios invoquen aceleradores criptográficos de hardware del kernel sin necesidad de código en modo kernel.
Los algoritmos **AEAD** (Cifrado autenticado con datos asociados) como AES-GCM y ChaCha20-Poly1305 se usan ampliamente para TLS, cifrado de disco y protocolos VPN. La plantilla vulnerable es `authencesn` — una composición AEAD que usa `hmac(sha256)` + `cbc(aes)` con soporte de Número de secuencia extendido (ESN), comúnmente utilizada en IPsec.
### 3.2 Causa raíz
En 2017, el commit `72548b093ee3` introdujo la **operación AEAD in-place** en `algif_aead` como una optimización de rendimiento — permitiendo que el motor criptográfico leyera y escribiera en el mismo búfer. Esto era defectuoso:```
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 vulnerabilidad proporciona una escritura controlada de 4 bytes en la caché de páginas de cualquier archivo que el atacante pueda abrir para lectura:
La escritura es repetible: el exploit itera la escritura de 4 bytes para parchear secuencias de código más grandes.
[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 Por qué fallan las defensas estándar
| Defensa | ¿Evadida? | Motivo |
|---------|-----------|--------|
| Monitoreo de integridad de archivos (Tripwire/AIDE) | **Sí** | Sin cambio en disco |
| Comprobaciones de hash de archivos del IDS | **Sí** | Los bytes del disco no cambian |
| Vigilancia de archivos `inotify` | **Sí** | Sin evento de escritura en VFS |
| SELinux / AppArmor | **Parcial** | Controla el proceso, no la escritura en page cache mediante el motor criptográfico |
| Montajes de solo lectura | **Sí** | La page cache se modifica en memoria, no a través del montaje |
| `watch` de auditd sobre el binario | **Sí** | Audit vigila escrituras VFS — esto evita VFS |
### 3.6 Versiones de kernel afectadas
| Rama | Vulnerable hasta | Corregido desde |
|--------|-------------------|------------|
| 4.14.x | Todas (origen de la vulnerabilidad) | Sin corrección upstream (EOL) |
| 5.4.x (LTS) | Todas | Requiere backport de la distribución |
| 5.10.x (LTS) | Todas | Requiere backport de la distribución |
| 5.15.x (LTS) | Todas | Requiere backport de la distribución |
| 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 | Corregido en rc | **6.15-rc+** |
> Los kernels de las distribuciones pueden haber aplicado el backport de la corrección en números de versión diferentes. Consulta siempre el aviso de seguridad de tu distribución.
---
## 4. Metodología de ataque — Red Team
> **Autorización requerida.** Esta sección existe para ayudar a los defensores a comprender la perspectiva del atacante. Ejecuta únicamente en sistemas que poseas o para los que tengas autorización escrita explícita para realizar pruebas.
### 4.1 Requisitos previos
- Shell con privilegios bajos en el objetivo (SSH, exec de contenedor, cadena RCE)
- Python 3.10+ **o** binario C compilado
- Kernel sin parchear con `algif_aead` disponible
### 4.2 Reconocimiento```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
Los investigadores originales (Theori) publicaron un PoC independiente de Python de 732 bytes totalmente funcional:
python3 copy_fail_exp.py
python3 copy_fail_exp.py /usr/bin/passwd
Una copia local está disponible en `exploit/poc.py`. Consulta `exploit/README.md` para el desglose técnico.
### 4.4 Escenario de escape de contenedor
Debido a que la caché de páginas de Linux se comparte entre todos los procesos del mismo host (incluidos el host y los contenedores):```
Attacker in container → patches /usr/bin/su in HOST page cache
Host user runs su → executes attacker code as root on host
Esto funciona incluso desde contenedores sin privilegios, siempre que el kernel del host sea vulnerable.
Este es el enfoque principal de este repositorio.
Ejecute el script de detección en cualquier sistema Linux:```bash chmod +x detection/check_vulnerable.sh sudo ./detection/check_vulnerable.sh
**Lo que comprueba:**
- Versión del kernel frente a rangos conocidos de vulnerabilidad
- Estado de carga del módulo `algif_aead` y estado de bloqueo en lista negra
- Disponibilidad de `authencesn` en `/proc/crypto`
- Integridad de la caché de páginas de binarios setuid (requiere root)
- Estado de parche específico de la distribución
- Procesos en ejecución para indicadores de explotación activa
Se guarda un informe con marca de tiempo en `/tmp/cve-2026-31431-report-*.txt`.
### 5.2 Detección YARA
Se proporcionan dos reglas YARA en `detection/yara/`:
| Archivo de regla | Propósito |
|-----------|---------|
| `cve_2026_31431_base.yar` | Coincide exactamente con el PoC público conocido |
| `cve_2026_31431_enhanced.yar` | Detecta exploits ofuscados, compilados y variantes |```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>
Por qué importan las reglas mejoradas: Los atacantes pueden ofuscar el PoC público de Python (codificar cadenas en base64, codificar el nombre del algoritmo con XOR, compilar a un binario C, eliminar símbolos). La regla mejorada detecta estas variantes al apuntar a invariantes que no se pueden eliminar sin romper el exploit:
authesn como nombre del algoritmosplice() para lograr acceso de copia cero a la caché de páginas38)Desplegar en /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
Consulta de intentos de explotación:```bash
ausearch -k cve_2026_31431_afalg --start today
ausearch -k cve_2026_31431_afalg -k cve_2026_31431_splice --start today
### 5.4 Detección con Falco / eBPF
Añade 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]
Dado que el exploit modifica la caché de páginas sin escribir en el disco, las herramientas estándar de FIM no lo detectan. Esta comprobación detecta la explotación activa:```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 de producción:** `drop_caches` provoca una pérdida de rendimiento. Ejecútalo durante ventanas de mantenimiento o primero en sistemas no críticos.
### 5.6 Indicadores de compromiso (IoCs)
| Tipo de IoC | Indicador | Confianza |
|----------|-----------|-----------|
| Cadena (binario/script) | `authencesn(hmac(sha256),cbc(aes))` | Alta |
| Bytes hexadecimales | `78 DA AB 77 F5 71 63 62 64 64` (cabecera de carga útil zlib) | Alta |
| Secuencia de syscalls | `socket(38,5,0)` → `bind()` → `splice()` | Alta |
| Red | Ninguno — puramente local | N/D |
| Archivo | Sin escrituras en disco (sigiloso) | — |
| Proceso | Proceso Python/C de corta duración con socket AF_ALG | Media |
| Caché de páginas | Caché de páginas del binario setuid ≠ hash en disco | Crítica |
### 5.7 Consultas de detección SIEM
**Splunk (fuente 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
Ejecute el script de parcheo automatizado:```bash chmod +x patch/patch.sh sudo ./patch/patch.sh
### 6.1 Mitigación Inmediata (Sin Reinicio Requerido*)```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"
*Si algif_aead ya está cargado, se requiere un reinicio para que la lista negra surta efecto por completo.
Efectos secundarios: Las aplicaciones que usan la interfaz AEAD del kernel a través de AF_ALG (poco común — la mayoría usa OpenSSL en espacio de usuario) pueden fallar. TLS estándar, cifrado de discos y herramientas VPN generalmente no se ven afectados.
kubectl get nodes -o wide
kubectl drain --ignore-daemonsets --delete-emptydir-data
kubectl uncordon
Utilice auto-actualizadores de nodos (Karpenter, Managed Node Groups) o la rotación del grupo de nodos del clúster cuando esté disponible.
### 6.4 Verificación posterior al parche```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)
Se proporciona un laboratorio mínimo en Docker con Alpine para probar herramientas de detección de forma segura.```bash cd lab/ docker compose up -d docker exec -it cve-2026-31431-lab /bin/sh
/cve-2026-31431/detection/check_vulnerable.sh
> **Importante:** Los contenedores Docker comparten el kernel del host. El laboratorio prueba el estado de vulnerabilidad **del kernel de tu host**. Los resultados de vulnerabilidad reflejan el sistema host real — esto es intencional para una evaluación realista.
Para pruebas aisladas con una versión específica de kernel vulnerable, usa una VM dedicada con un kernel fijado. Consulta `lab/README.md` para obtener orientación sobre la configuración de la VM.
---
## 8. Referencias
| Recurso | Enlace |
|----------|------|
| Aviso NVD | https://nvd.nist.gov/vuln/detail/CVE-2026-31431 |
| Investigación original | https://copy.fail |
| Informe técnico | https://xint.io/blog/copy-fail-linux-distributions |
| PoC público | https://github.com/theori-io/copy-fail-CVE-2026-31431 |
| Catálogo KEV de CISA | https://www.cisa.gov/known-exploited-vulnerabilities-catalog |
| Corrección del kernel — Commit revertido | `a664bf3d603d` / `fafe0fa2995a` |
| Commit vulnerable | `72548b093ee3` |
| Aviso de Microsoft Defender | Blog de Microsoft Defender Threat Intelligence |
---
## Estructura del repositorio```
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
Esta investigación se proporciona únicamente con fines educativos y de seguridad defensiva. Todas las herramientas están diseñadas para ayudar a los defensores a detectar y remediar CVE-2026-31431 en sistemas que están autorizados a proteger.
Repositorio mantenido por rippsec
| Atributo | Valor |
|---|
| CVE | CVE-2026-31431 |
| Apodo | Copy Fail |
| CVSS v3.1 | 7.8 ALTO |
| Vector de Ataque | Local |
| Privilegios Requeridos | Bajos |
| Interacción del Usuario | Ninguna |
| Componente | crypto/algif_aead.c — plantilla authencesn |
| Introducido | 2017 (commit 72548b093ee3) |
| Divulgado | 2026 |
| Años en Silencio | ~9 años |
| CISA KEV | Sí |
| PoC Público | Sí (script Python independiente de 732 bytes) |
| Propiedad | Valor |
|---|
| Tamaño de escritura | 4 bytes |
| Control de desplazamiento | Sí — controlado por el atacante mediante el desplazamiento de splice |
| Objetivo | Caché de páginas de cualquier archivo legible |
| Marcado de página sucia | Ninguno |
| Modificación en disco | Ninguna |
| Actualización de marca de tiempo | Ninguna |
| Entrada en el registro del kernel | Ninguna (a menos que auditd esté configurado) |
| Técnica | ID | Notas |
|---|
| Explotación para escalada de privilegios | T1068 | Técnica principal |
| Abuso del mecanismo de control de elevación: Setuid/Setgid | T1548.001 | Secuestro de binario setuid |
| Secuestro del flujo de ejecución | T1574 | Parcheo de binario en memoria |
| Eliminación de indicadores: Timestomp | T1070.006 | No se actualizan marcas de tiempo |
| Ejecución indirecta de comandos | T1202 | El binario parcheado ejecuta la shell |
| Distribución | Comando de actualización |
|---|
| 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 |