Copy Fail y Dirty Frag
El Kernel de Linux Bajo Fuego — 732 Bytes Bastan para ser Root
Juan David Rosas Salas
Categorías:
HackingSeguridadInvestigación2026-05-08
Dos vulnerabilidades críticas descubiertas con semanas de diferencia acaban de sacudir el mundo de la seguridad en Linux. No son bugs teóricos ni exploits que requieren alinear planetas. Son fallos de lógica deterministas, portables, que funcionan con el mismo script en Ubuntu, RHEL, Amazon Linux y SUSE, y que entregan una shell de root sin carreras de condición, sin offsets por distribución y sin crashes del kernel. Bienvenidos a la era post-Dirty Cow: Copy Fail (CVE-2026-31431) y Dirty Frag, dos hallazgos que redefinirán cómo se auditan los subsistemas criptográficos del kernel de Linux.
Copy Fail (CVE-2026-31431): 732 Bytes para Root en Toda Distro Desde 2017
¿Qué es Copy Fail?
Copy Fail es un fallo de lógica en línea recta que no necesita ventana de carrera ni offsets específicos por kernel. El mismo script Python de 732 bytes hace root en todas las distribuciones Linux desde 2017.
Un único bug de lógica en el template criptográfico authencesn, encadenado a través de AF_ALG y splice(), produce una escritura de 4 bytes en el page cache, explotable sigilosamente durante casi una década.
Lo que hace diferente a Copy Fail de sus predecesores
Los veteranos de seguridad Linux recordarán Dirty Cow (CVE-2016-5195) y Dirty Pipe (CVE-2022-0847). Dirty Cow requería ganar una condición de carrera en el subsistema de copia-en-escritura de la VM, con múltiples intentos y riesgo de crash. Dirty Pipe era específico a versiones y requería manipulación precisa de pipe buffers.
Copy Fail rompe ese molde por cuatro razones:
Portable: el mismo script exacto funciona en Ubuntu, Amazon Linux, RHEL y SUSE sin offsets por distribución, sin recompilación y sin comprobaciones de versión. Diminuto: el exploit completo es un script Python que usa solo módulos de la librería estándar (os, socket, zlib). Sigiloso: la escritura bypasea el path de escritura VFS ordinario; la página corrompida nunca se marca dirty por el kernel. Las herramientas de integridad de ficheros que comparan checksums en disco no detectarán nada, porque el fichero en disco permanece intacto. Solo el page cache en memoria está corrompido. Impacto cross-container: el page cache es compartido por todos los procesos del sistema, incluyendo a través de fronteras de contenedor.
La Causa Raíz Técnica
AF_ALG es un tipo de socket que expone el subsistema criptográfico del kernel a userspace sin privilegios. Un usuario puede abrir un socket, ligarlo a cualquier template AEAD, e invocar cifrado o descifrado sobre datos arbitrarios. Sin privilegios necesarios.
Cuando un usuario hace splice() de un fichero a un pipe y luego a un socket AF_ALG, el scatterlist de entrada del socket mantiene referencias directas a las páginas cacheadas del kernel de ese fichero. Las páginas no se duplican; las entradas del scatterlist apuntan a las mismas páginas físicas que respaldan cada read(), mmap() y execve() de ese fichero.
El algoritmo authencesn, wrapper AEAD usado por IPsec para soporte de números de secuencia extendidos, usa el buffer de destino del caller como scratch space. La tercera llamada en crypto_authenc_esn_decrypt() escribe 4 bytes en el offset assoclen + cryptlen, más allá del tag AEAD. El algoritmo usa memoria que no le pertenece como área de trabajo temporal.
En el path in-place de AF_ALG, esta escritura cruza desde el buffer de salida a las páginas del page cache del tag encadenadas. scatterwalk_map_and_copy camina más allá del buffer RX, mapea la página del page cache vía kmap_local_page, y escribe seqno_lo directamente en la copia cacheada del kernel del fichero objetivo.
La Historia de Tres Commits: Cómo Nació el Bug
En 2011, authencesn fue añadido al kernel para soporte IPsec ESP. En 2015, AF_ALG ganó soporte AEAD con un path de splice(). En 2017, se añadió una optimización in-place a algif_aead.cque copiaba AAD y ciphertext al buffer RX, pero encadenaba las páginas del tag por referencia usando sg_chain(), poniendo páginas del page cache en un scatterlist escribible. Nadie conectó la optimización de 2017 con las escrituras scratch de authencesn ni con el uso de páginas de page cache por el path de splice().
El Exploit Paso a Paso
El exploit por defecto apunta a /usr/bin/su, un binario setuid-root ampliamente presente en las principales distribuciones Linux. El atacante controla tres cosas: qué fichero (cualquier fichero legible por el usuario actual), qué offset (los parámetros AEAD determinan exactamente qué 4 bytes del page cache se sobreescriben), y qué valor (los 4 bytes provienen de los bytes 4-7 del AAD, construidos por el atacante en sendmsg()).
Tras las escrituras, una llamada a execve("/usr/bin/su") carga el binario desde el page cache ya corrompido. Como su es setuid-root, el shellcode inyectado se ejecuta como UID 0.
Distribuciones Verificadas
El mismo exploit sin modificar funcionó en Ubuntu 24.04 LTS (kernel 6.17.0-1007-aws), Amazon Linux 2023 (kernel 6.18.8-9.213.amzn2023), RHEL 10.1 (kernel 6.12.0-124.45.1.el10_1) y SUSE 16 (kernel 6.12.0-160000.9-default).
Timeline de Divulgación
El 23 de marzo de 2026 se reportó al equipo de seguridad del kernel de Linux; el 24 de marzo se recibió el acknowledgment inicial; el 25 de marzo se propusieron y revisaron los parches; el 1 de abril se realizó el commit al mainline; el 22 de abril se asignó el CVE-2026-31431; el 29 de abril se hizo la divulgación pública.
Cómo fue encontrado: IA en la Investigación de Seguridad
Taeyang Lee (investigador de Theori) sospechaba que la proveniencia de páginas en scatterlists podía ser una fuente de vulnerabilidades poco explorada. Usando Xint Code, el prompt al sistema fue simple: "Este es el subsistema crypto/ de Linux. Examina todos los codepaths alcanzables desde syscalls de userspace. Nota clave: splice() puede entregar referencias de page-cache de ficheros de solo lectura (incluyendo binarios setuid) a crypto TX scatterlists." Después de aproximadamente una hora de escaneo, Copy Fail fue el hallazgo de mayor severidad.
Dirty Frag: El Sucesor que Ya Está Aquí — y No Tiene Parche
Apenas días después de la divulgación de Copy Fail, el investigador Hyunwoo Kim (@v4bel) publicó Dirty Frag, una vulnerabilidad que extiende la misma clase de bug y añade una capa de peligro adicional: aún no tiene parche oficial.
¿Qué es Dirty Frag?
Dirty Frag es una vulnerabilidad que obtiene privilegios de root en la mayoría de distribuciones Linux encadenando la vulnerabilidad xfrm-ESP Page-Cache Write y la vulnerabilidad RxRPC Page-Cache Write. Es un bug de lógica determinista que no depende de una ventana de timing, no requiere condición de carrera, el kernel no entra en pánico cuando el exploit falla, y la tasa de éxito es muy alta.
La explotación exitosa del fallo permite a un usuario local sin privilegios obtener acceso root elevado en la mayoría de distribuciones Linux, incluyendo Ubuntu 24.04.4, RHEL 10.1, openSUSE Tumbleweed, CentOS Stream 10, AlmaLinux 10 y Fedora 44.
La Diferencia Clave: Dos Primitivas que se Complementan
El ingenio de Dirty Frag está en cómo dos vulnerabilidades distintas se encadenan para cubrir los puntos ciegos de cada una:
xfrm-ESP Page-Cache Write, enraizada en el subsistema IPSec (xfrm), proporciona a los atacantes una primitiva de escritura de 4 bytes como Copy Fail y sobreescribe una pequeña cantidad en el page cache del kernel. Sin embargo, el exploit requiere que el usuario sin privilegios cree un namespace, paso que Ubuntu bloquea mediante AppArmor.
RxRPC Page-Cache Write no requiere el privilegio para crear un namespace, pero el módulo rxrpc.ko en sí no está incluido en la mayoría de distribuciones. Por ejemplo, la build por defecto de RHEL 10.1 no incluye rxrpc.ko. Sin embargo, en Ubuntu, el módulo rxrpc.ko se carga por defecto. Encadenando los dos variantes se cubren mutuamente los puntos ciegos.
El Detalle Crítico: No lo Detiene la Mitigación de Copy Fail
Dirty Frag puede ser triggereado independientemente de si el módulo algif_aead está disponible. En otras palabras, incluso en sistemas donde se ha aplicado la mitigación conocida de Copy Fail (blacklist de algif_aead), tu Linux sigue siendo vulnerable a Dirty Frag.
La Causa Técnica
El bug reside en los fast paths de descifrado in-place de esp4, esp6 y rxrpc: cuando un socket buffer lleva fragmentos paginados que no son propiedad privada del kernel (como páginas de pipe adjuntas vía splice(2)/sendfile(2)/MSG_SPLICE_PAGES), el path de recepción descifra directamente sobre esas páginas respaldadas externamente, exponiendo o corrompiendo texto plano al que un proceso sin privilegios aún mantiene una referencia.
Impacto en Entornos Reales: ¿Quién Debe Preocuparse Más?
Ambas vulnerabilidades comparten una superficie de ataque amplia. Estos son los escenarios de mayor riesgo:
Entornos multi-tenant: Servidores de desarrollo compartidos, jump hosts, build servers. Cualquier usuario se convierte en root.
Kubernetes y clusters de contenedores: El page cache es compartido en todo el host. Un pod con las primitivas correctas compromete el nodo y cruza fronteras de tenant.
CI runners y build farms: GitHub Actions self-hosted runners, GitLab runners, Jenkins agents — cualquier cosa que ejecute código de PRs no confiables como usuario regular sobre un kernel compartido. Un PR se convierte en root en el runner.
Cloud SaaS ejecutando código de usuario: Notebook hosts, sandboxes de agentes, funciones serverless.
Servidores Linux estándar: Incluso en producción single-tenant, la vulnerabilidad encadena perfectamente con un RCE web o credenciales robadas.
Mitigación Inmediata
Para Copy Fail (CVE-2026-31431):
Actualizar el kernel es la solución definitiva. El parche revierte algif_aead.c a operación out-of-place.
Como mitigación temporal:
# Deshabilitar el módulo algif_aead
echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif.conf
rmmod algif_aead
Esto no afectará a dm-crypt/LUKS, kTLS, IPsec/XFRM, TLS en kernel, builds por defecto de OpenSSL/GnuTLS/NSS, SSH ni al keyring criptográfico del kernel.
Para Dirty Frag (sin parche aún):
# Bloquear los módulos afectados
sudo sh -c "printf 'install esp4 /bin/false\ninstall esp6 /bin/false\ninstall rxrpc /bin/false\n' \
> /etc/modprobe.d/dirtyfrag.conf; rmmod esp4 esp6 rxrpc 2>/dev/null; true"
Advertencia crítica: Dirty Frag puede explotarse independientemente de si se ha aplicado la mitigación de Copy Fail. Aplicar solo el blacklist de algif_aead no protege contra Dirty Frag.
Lecciones de Seguridad: Lo que Estos Bugs nos Enseñan
1. Los subsistemas criptográficos son superficie de ataque de alta densidad
Ambas vulnerabilidades viven en el subsistema crypto/networking del kernel. La asunción de que "código criptográfico es código de seguridad" no implica que esté libre de bugs de lógica. Al contrario, su complejidad lo convierte en terreno fértil para vulnerabilidades que cruzan capas de abstracción.
2. Los commits de optimización son vectores de vulnerabilidad
Nadie conectó la optimización in-place de 2017 con las escrituras scratch de authencesn ni con el uso de páginas de page cache por el path de splice(). Cada cambio era razonable en aislamiento. La vulnerabilidad existe en la intersección de los tres.
3. Las mitigaciones parciales crean falsa seguridad
El caso de Dirty Frag es un ejemplo perfecto: los administradores que aplicaron la mitigación de Copy Fail (blacklist de algif_aead) podrían creer estar protegidos. No lo están frente a Dirty Frag.
4. La IA como herramienta de investigación de vulnerabilidades está madurando
Copy Fail fue encontrado con aproximadamente una hora de tiempo de escaneo por Xint Code contra el subsistema crypto/ de Linux. El mismo escaneo también identificó otros bugs de alta severidad que aún están en proceso de divulgación coordinada.
Conclusión: Parchea Ahora, Monitoriza Siempre
Copy Fail y Dirty Frag son un recordatorio brutal de que el kernel de Linux, a pesar de sus décadas de hardening y la revisión de miles de desarrolladores, sigue siendo un objetivo viable para investigadores y atacantes. La buena noticia es que ambas vulnerabilidades fueron descubiertas y divulgadas responsablemente. La mala es que con un PoC público disponible y Dirty Frag aún sin parche oficial, el reloj corre.
Si gestionas servidores Linux, la acción es hoy. No mañana.