Dirty Frag: Análisis Profundo de la Vulnerabilidad de Escalada de Privilegios en el Kernel Linux
Dirty Frag: Una cadena de vulnerabilidades en la ruta de copia cero del kernel Linux que contamina la escritura en caché de páginas, encadenando las vulnerabilidades xfrm-ESP y RxRPC. Afecta a casi todas las distribuciones principales desde 2017 y permite la escalada de privilegios a root sin contraseña.
¿Otra Vez? ¿No Nos Dejan en Paz?
Para ser honesto, no esperaba tener que escribir otro artículo sobre escalada de privilegios en el kernel tan pronto.
Han pasado solo ocho días desde el artículo de Copy Fail. ¡Ocho días! La lista negra de algif_aead de Copy Fail apenas se había escrito en la terminal, el parche ni siquiera se había enfriado, y entonces llegó — Dirty Frag.
Y lo más absurdo es que las mitigaciones de Copy Fail son completamente ineficaces contra Dirty Frag. Esta vez, el ataque se dirige a subsistemas completamente diferentes del kernel — las rutas de cifrado xfrm-ESP y RxRPC — así que da igual si desactivas algif_aead o no.
Dirty Pipe (2022), Copy Fail (2026.04), Dirty Frag (2026.05)… Cada vez es “afecta a casi todas las distribuciones desde 2017”. ¿Sabes lo que eso significa? Significa que durante casi la última década, cualquiera que haya iniciado sesión en una cuenta sin privilegios de tu sistema ha tenido la oportunidad de convertirse silenciosamente en root.
Pero pensándolo bien, ¿es esto enteramente culpa de los desarrolladores del kernel? No necesariamente.
El crecimiento explosivo de herramientas de auditoría de código asistidas por IA en los últimos años permite a los investigadores de seguridad descubrir vulnerabilidades ocultas durante casi una década en cuestión de horas. Errores que antes requerían revisión manual línea por línea ahora son detectados en masa por IA. Copy Fail fue localizado por la herramienta Xint Code en una hora. Aunque Dirty Frag provino de la auditoría manual del investigador coreano Hyunwoo Kim, las rutas de código que explota pertenecen a la misma familia que Copy Fail — escritura en caché de páginas en rutas de copia cero — lo que indica que este tipo de defecto de diseño está lejos de ser un caso aislado. Mejores herramientas, mayor eficiencia, y naturalmente más vulnerabilidades son “descubiertas”.
Lo más inquietante es el proceso de divulgación esta vez. El investigador envió originalmente los detalles de la vulnerabilidad al equipo de seguridad del kernel con un embargo de 5 días acordado para dar tiempo a las distribuciones a parchear. Pero el mismo día, un tercero no relacionado publicó directamente los detalles completos y el exploit de la vulnerabilidad ESP(xfrm). Sin CVE, sin parche, pero el PoC estaba disponible para todos. Esto no es divulgación responsable — es apuñalar por la espalda a todos los usuarios de Linux. La ventana de parcheo fue destruida, y todos se vieron forzados a correr desprotegidos.
Bien, terminé la queja. Veamos en serio de qué trata esta vulnerabilidad.
Línea Temporal
| Fecha | Evento |
|---|---|
| 2017-01 | La vulnerabilidad xfrm-ESP se introduce con el commit cac2661c53f3 (latente durante 9 años) |
| 2023-06 | La vulnerabilidad RxRPC se introduce con el commit 2dc334f1a63a |
| 2026-04-29 | El investigador coreano Hyunwoo Kim (@v4bel) reporta la vulnerabilidad RxRPC y el exploit completo a security@kernel.org |
| 2026-05-07 | Los detalles de la vulnerabilidad se envían a la lista de correo linux-distros con un embargo de 5 días acordado |
| 2026-05-07 | El mismo día, un tercero publica los detalles y el exploit de la vulnerabilidad ESP(xfrm), el embargo se rompe inmediatamente |
| 2026-05-07 | Tras consulta con los mantenedores de distribuciones, se publica la documentación completa de Dirty Frag. En este momento sin CVE, sin parche oficial |
| 2026-05-08 | Al momento de escribir, las distribuciones principales aún esperan la fusión del parche upstream |
Análisis de Impacto
| Métrica | Detalles |
|---|---|
| CVE | Ninguno aún (NVD no tuvo tiempo de asignar antes de que se rompiera el embargo) |
| Tipo de Vulnerabilidad | Fallo lógico determinista, no una condición de carrera |
| Tasa de Éxito de Explotación | 100%, éxito garantizado en la primera ejecución |
| Rango Afectado | Casi todas las distribuciones Linux principales desde 2017 (hasta mayo de 2026, el kernel 7.0.3 más reciente también se ve afectado) |
| Método de Explotación | Payload de 192 bytes, ensamblando un ELF root-shell a través de 48 escrituras de 4 bytes |
| Huella en Disco | Sin modificación persistente — solo contamina la caché de páginas en memoria, evade inotify; se restaura al reiniciar |
| Evita la Mitigación de Copy Fail | La desactivación de algif_aead de Copy Fail es completamente ineficaz ya que ataca subsistemas diferentes |
Comparación con vulnerabilidades LPE históricas del kernel:
| Característica | Dirty Cow (2016) | Dirty Pipe (2022) | Copy Fail (2026) | Dirty Frag (2026) |
|---|---|---|---|---|
| Condición de carrera | Requerida | No requerida | No requerida | No requerida |
| Rango afectado | Versiones específicas | 5.8+ | Todas las distros principales desde 2017+ | Todas las distros principales desde 2017+ |
| Complejidad del código de explotación | Compleja | Compleja | 10 líneas Python | Programa C de un solo archivo |
| Huella en disco | Sí | Sí | No | No |
| Estado del parche | Corregido | Corregido | Corregido | Sin parche oficial aún |
Distribuciones afectadas confirmadas:
| Distribución | Versión del Kernel Probada |
|---|---|
| Ubuntu 24.04.4 | 6.17.0-23-generic |
| RHEL 10.1 | 6.12.0-124.49.1 |
| CentOS Stream 10 | 6.12.0-224 |
| AlmaLinux 10 | 6.12.0-124.52.3 |
| Fedora 44 | 6.19.14-300 |
| openSUSE Tumbleweed | 7.0.2-1 |
| Arch Linux | 7.0.3 |
Desde 6.12 hasta 7.0, desde Ubuntu hasta Arch — cobertura total de plataformas. Sí, prácticamente cualquier distribución principal que tengas instalada probablemente se ve afectada.
Principios Técnicos: ¿Por Qué “Dirty Frag”?
El Núcleo en Una Frase
splice() implanta una referencia de caché de página de archivo de solo lectura en la ranura frag del búfer de envío de red (skb) → el kernel receptor realiza operaciones criptográficas in situ en el frag (in-place crypto, src == dst apuntando a la misma memoria) → lo que debería haber sido una operación de descifrado en texto cifrado se convierte en una primitiva STORE que escribe directamente en la caché de página de solo lectura → reemplazando el código máquina de su con un ELF root-shell.
“Dirty” se refiere a contaminar la caché de páginas, “Frag” se refiere a explotar el mecanismo de fragmentos del skb (socket buffer). Juntos — Dirty Frag.
Contaminación de Frag skb en la Ruta de Copia Cero
Esta parte es clave para entender toda la vulnerabilidad, así que profundicemos.
Normalmente, cuando escribes datos en un socket, el kernel copia los datos del espacio de usuario a su skb. Pero splice() toma la ruta de copia cero — inserta directamente el puntero a la página de caché de página del archivo (estructura page + offset) en el array frag del skb sin copiar los datos en sí:
struct skb_shared_info {
struct sk_buff *frag_list; // lista enlazada de frag
skb_frag_t frags[MAX_SKB_FRAGS]; // array de frag, cada uno es {page, offset, size}
// ...
};
El punto clave aquí: la page pasada a splice() es la página de caché de página en memoria de tu archivo (por ejemplo, /usr/bin/su) — solo tienes permisos de lectura, pero una referencia a esta página ya ha sido insertada en el skb de la pila de protocolos de red.
A continuación, depende de si la pila de protocolos de red receptora “se pica las manos” y escribe en esta página.
Vulnerabilidad 1: Escritura en Caché de Página xfrm-ESP
La primera vulnerabilidad reside en la ruta de descifrado de IPsec ESP (Encapsulating Security Payload).
La función esp_input() se utiliza para descifrar datos cifrados. Normalmente, si la región de datos del skb se compartiría con un frag, el kernel debería llamar primero a skb_cow_data() (Copy-on-Write) para copiar la página compartida antes de operar. Sin embargo, existe una ruta de código en esp_input() que evita COW:
static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
{
if (!skb_cloned(skb)) {
if (!skb_is_nonlinear(skb)) {
// [1] skb lineal: solo datos de cabecera, sin frag, seguro
nfrags = 1;
goto skip_cow;
} else if (!skb_has_frag_list(skb)) {
// [2] Tiene frag, pero no frag_list → ¡salta cow directamente!
nfrags = skb_shinfo(skb)->nr_frags;
nfrags++;
goto skip_cow; // La bomba está aquí
}
}
// Ruta normal: copiar datos, seguro
err = skb_cow_data(skb, 0, &trailer);
}
Cuando el skb es no lineal (tiene frags que contienen la caché de página pasada por splice) pero frag_list está vacío, el código salta directamente a skip_cow. Luego, el subsiguiente crypto_authenc_esn_decrypt() realiza el descifrado AEAD in situ — src y dst apuntan a la misma scatterlist, que es la página de caché de página implantada por el atacante.
Durante el proceso de descifrado, hay una línea de código particularmente crítica:
// Mueve los 4 bytes altos del número de secuencia al final de dst SGL
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1);
Esta línea escribe 4 bytes en dst (tu página de caché de su) en el offset assoclen + cryptlen. El valor de tmp + 1 proviene de los 32 bits altos del número de secuencia del encabezado ESP — algo que el atacante controla completamente a través de XFRMA_REPLAY_ESN_VAL.seq_hi al registrar el XFRM SA (Security Association).
Así que el atacante controla simultáneamente:
- Dónde escribir (offset de archivo, posicionado ajustando la longitud del payload)
- Qué valor escribir (4 bytes, especificado vía
seq_hi)
Al registrar 48 XFRM SAs diferentes, cada uno con su seq_hi almacenando un fragmento de 4 bytes del ELF, y haciendo un bucle 48 veces, un ELF root-shell completo se ensambla en la caché de página de su.
Sin embargo, esta vulnerabilidad tiene una limitación: registrar XFRM SAs requiere privilegios CAP_NET_ADMIN. Los atacantes pueden obtener esto creando espacios de nombres de usuario (unshare(CLONE_NEWUSER | CLONE_NEWNET)) — pero AppArmor de Ubuntu impide que los usuarios sin privilegios creen espacios de nombres de red.
Por eso se necesita una segunda vulnerabilidad.
Vulnerabilidad 2: Escritura en Caché de Página RxRPC
La segunda vulnerabilidad reside en la ruta de descifrado de autenticación Kerberos del protocolo RxRPC.
La función rxkad_verify_packet_1() realiza descifrado pcbc(fcrypt) in situ en los primeros 8 bytes de los paquetes de datos recibidos:
skcipher_request_set_crypt(req, sg, sg, 8, iv.x);
// ^^ ^^
// src==dst → ¡operación in situ!
ret = crypto_skcipher_decrypt(req); // La escritura de 8 bytes ocurre aquí
skb_to_sgvec() convierte directamente el frag del skb (que contiene la página de caché de página empalamada por el atacante) en una scatterlist, con src y dst siendo el mismo sg. Así que la operación de descifrado escribe directamente el “resultado del descifrado” de 8 bytes de vuelta a esa página de caché de página de solo lectura.
Comparado con xfrm-ESP:
| Característica | xfrm-ESP | RxRPC |
|---|---|---|
| Tamaño de escritura | 4 bytes | 8 bytes |
| Control de valor | Control directo (seq_hi) | Indirecto (requiere fuerza bruta de clave fcrypt) |
| Privilegio requerido | Espacio de nombres de usuario | Sin privilegio requerido |
| Tiempo de introducción | 2017-01 | 2023-06 |
Los valores escritos a través de la ruta RxRPC no pueden controlarse directamente — son el resultado de fcrypt_decrypt(C, K). El atacante necesita primero registrar una clave K vía add_key("rxrpc", ...), luego realizar fuerza bruta en el espacio de usuario para encontrar la K que produce los 8 bytes de texto plano objetivo. Afortunadamente, fcrypt es un cifrado de 56 bits, bloque de 8 bytes dedicado al Andrew File System, así que la fuerza bruta no es un gran problema.
El punto más crítico: la ruta RxRPC no requiere absolutamente ningún privilegio. No necesita crear espacios de nombres de usuario, no necesita espacios de nombres de red, no necesita CAP_NET_ADMIN. Y Ubuntu carga el módulo rxrpc.ko por defecto.
Lógica de Encadenamiento
Las dos vulnerabilidades se complementan, proporcionando cobertura total:
| Escenario | Vulnerabilidad Utilizada | Razón |
|---|---|---|
| Ubuntu (AppArmor bloquea espacios de nombres) | RxRPC | rxrpc.ko cargado por defecto, sin privilegio requerido |
| RHEL / Fedora / openSUSE | xfrm-ESP | Espacios de nombres disponibles, escrituras ESP precisamente controlables |
| Otras distribuciones | xfrm-ESP o RxRPC | Elegir según la carga de módulos, al menos una ruta disponible |
Esto es lo que hace que Dirty Frag sea aterrador — no importa cómo lo configures, siempre hay un camino a root.
Análisis del PoC
El exploit completo está disponible en código abierto en github.com/V4bel/dirtyfrag. Compilar y ejecutar requiere solo una línea:
git clone https://github.com/V4bel/dirtyfrag.git
cd dirtyfrag && gcc -O0 -Wall -o exp exp.c -lutil && ./exp
La idea central no es complicada:
- Preparar un ELF mínimo de 192 bytes — un root-shell que ejecuta con escalada de privilegios
- Dividir estos 192 bytes en 48 fragmentos de 4 bytes (si se usa la ruta xfrm-ESP)
- Registrar un XFRM SA para cada fragmento de 4 bytes, con su
seq_hiestablecido al valor de ese fragmento - Cada vez, usar
splice()para enviar la caché de página desual skb, activando una escritura in situ - Hacer un bucle 48 veces, y la región de caché de página de
su(primeros 192 bytes) se reemplaza completamente con el ELF root-shell execve("/usr/bin/su")→ shell root
Todo el proceso nunca toca archivos en disco. El /usr/bin/su en disco permanece intacto, su md5 sigue siendo el md5 original. Pero en la caché de página del kernel, ha sido secretamente reemplazado.
Cuando cualquier proceso inicia execve en su, el kernel lee de la caché de página — ups, ejecuta el binario que inyectaste. Root obtenido.
Respuesta de Emergencia: Desactivar Temporalmente los Módulos Vulnerables
A partir del 8 de mayo de 2026, los parches oficiales del kernel aún no han sido lanzados. Hasta que los parches estén disponibles, la única mitigación temporal es descargar y poner en lista negra los tres módulos vulnerables.
Primero, confirma si tu sistema se ve afectado:
lsmod | grep -E 'esp4|esp6|rxrpc'
Si hay alguna salida, estás afectado.
Ejecuta los siguientes comandos inmediatamente (no se requiere reinicio):
sudo sh -c "printf 'install esp4 /bin/false\ninstall esp6 /bin/false\ninstall rxrpc /bin/false\n' > /etc/modprobe.d/dirtyfrag.conf"
sudo rmmod esp4 esp6 rxrpc 2>/dev/null
Verifica:
lsmod | grep -E 'esp4|esp6|rxrpc'
Importante: Si sospechas que el PoC ya se ha ejecutado, debes limpiar la caché de página:
echo 3 | sudo tee /proc/sys/vm/drop_caches
Si no haces esto, incluso después de desactivar los módulos, la caché de página contaminada permanece en memoria — ejecutar su todavía da una shell root.
Efectos secundarios:
- Desactivar
esp4/esp6interrumpirá los túneles VPN IPsec. Los usuarios de escritorio y la mayoría de servidores no se ven afectados, pero si dependes de VPN IPsec (como strongSwan, Libreswan), evalúa el impacto primero. - Desactivar
rxrpctiene un impacto mínimo a menos que estés usando AFS (Andrew File System).
La Carrera Armamentista de Vulnerabilidades Impulsada por IA
La exposición de Dirty Frag nos obliga a pensar en una pregunta más profunda: ¿Por qué las vulnerabilidades LPE del kernel están apareciendo una tras otra recientemente?
| Vulnerabilidad | Tiempo de Descubrimiento | Herramienta Clave | Del Reporte a lo Público |
|---|---|---|---|
| Dirty Pipe | 2022 | Auditoría manual | Proceso estándar |
| Copy Fail | 2026-04 | Xint Code (IA) | Aproximadamente un mes |
| Dirty Frag | 2026-05 | Auditoría manual | 8 días (embargo roto el mismo día) |
Las vulnerabilidades LPE del kernel pasaron de una por año a una por mes, y ahora de una por mes a… ¿una por semana?
Detrás de esto está el crecimiento explosivo de herramientas de auditoría de código asistidas por IA. Antes, confiando en la revisión humana línea por línea, una vulnerabilidad sin descubrir durante diez años era normal. Ahora la IA puede escanear un subsistema completo en horas, extrayendo todas las rutas de copia cero potenciales, operaciones in situ y referencias compartidas. Mejores herramientas, mayor eficiencia, y naturalmente más vulnerabilidades son “descubiertas” — el kernel no ha empeorado de repente, es solo que las deudas viejas escondidas en rincones están siendo descubiertas una por una por la IA.
Aún más alarmante es el cambio en el ecosistema de divulgación. El embargo de Dirty Frag fue deliberadamente roto por un tercero, con los detalles de la vulnerabilidad y el PoC publicados el mismo día. ¿Qué significa esto? Significa que desde que el investigador reportó la vulnerabilidad a security@kernel.org hasta que los hackers de todo el mundo obtuvieron sus armas, solo pasaron ocho días. La ventana de parcheo — desaparecida.
Podemos culpar a la persona que rompió el embargo por ser poco ética. Pero la realidad es que esto solo ocurrirá más y más. La IA hace que encontrar vulnerabilidades sea más rápido, y la weaponización también. No puedes contar siempre con que todos respeten los acuerdos de embargo.
Y no olvides, la misma familia de vulnerabilidades sigue siendo descubierta:
| Vulnerabilidad | Subsistema | Estado |
|---|---|---|
| Copy Fail | AF_ALG + authencesn | Corregido |
| Dirty Frag | xfrm-ESP + RxRPC | Sin parche |
| Copy Fail 2 | ESP-in-UDP | Divulgado públicamente |
| ZCRX Freelist | io_uring ZCRX | Divulgado públicamente |
Los principios centrales de estas cuatro vulnerabilidades son sorprendentemente similares — splice() inserta referencias de caché de página de solo lectura en subsistemas del kernel, y los subsistemas escriben in situ en los frags. Lo que exponen es en realidad la misma clase de problema de diseño:
| Componente | Razón de Introducción | Efecto Secundario |
|---|---|---|
splice() | Copia cero, optimización de rendimiento | Referencias de caché de página de solo lectura enviadas a subsistemas del kernel |
AF_ALG | Exponer capacidades criptográficas del kernel | Usuarios sin privilegios pueden iniciar sesiones de cifrado directamente |
| xfrm-ESP | Aceleración IPsec | Descifrado in situ, usando páginas de solo lectura como búferes de salida |
| RxRPC | Soporte de protocolo de red AFS | Igual que arriba, ni siquiera necesita privilegios de espacio de nombres |
Cada diseño, tomado individualmente, es una optimización de rendimiento razonable o un requisito funcional. Pero juntos, forman una cadena de vulnerabilidades donde cualquier usuario local puede convertirse en root sin contraseña.
A menos que el kernel upstream reexamine a fondo el paradigma de “operaciones in situ en rutas de copia cero”, te lo garantizo — este no será el último.
Para usuarios comunes, mi consejo es simple:
- Ejecuta los comandos de lista negra de arriba ahora mismo. Vuélvelos a cambiar cuando llegue el parche oficial.
- Monitorea de cerca las actualizaciones del kernel de tu gestor de paquetes. Una vez que esté disponible una versión corregida, actualiza y reinicia inmediatamente.
- Verifica regularmente con
lsmod | grepsi estos módulos se han cargado accidentalmente.
Referencias
- Repositorio GitHub PoC: https://github.com/V4bel/dirtyfrag
- Reporte LWN: https://lwn.net/Articles/1071719/
- Reporte Phoronix: https://www.phoronix.com/news/Dirty-Frag-Linux
- Análisis Técnico en Coreano (GeekNews): https://news.hada.io/topic?id=29275
- Sitio de Divulgación Copy Fail: https://copy.fail/
- Copy Fail 2 (Electric Boogaloo): https://github.com/0xdeadbeefnetwork/Copy_Fail2-Electric_Boogaloo
Infografías

Figura 1: Visión general de la vulnerabilidad Dirty Frag — cómo las referencias de caché de página de copia cero son explotadas a través de skb frags