Dirty Frag
es una nueva vulnerabilidad descubierta y reportada por el investigador
coreano Hyunwoo Kim (@v4bel) que permite a un usuario sin privilegios obtener una shell de
root en la mayoría de las distribuciones Linux
modernas. Fue divulgada públicamente el 7 de mayo de 2026, en parte
forzada por una tercera parte que la filtró antes de que todos los parches
estuvieran listos.
En el momento de publicación de esta advertencia,
ninguna de las distribuciones populares de Linux ha proporcionado aún
actualizaciones que contengan el parche de seguridad. Recomendamos implementar una mitigación temporal desactivando los módulos
esp4, esp6 y rxrpc.
La vulnerabilidad combina dos fallas independientes del kernel de Linux para
lograr escritura arbitraria sobre la caché de páginas de
archivos de solo lectura críticos del sistema, como /etc/passwd o
/usr/bin/su, sin necesidad de conocer ninguna clave
criptográfica.
Linaje: Dirty Pipe, Copy Fail y Dirty Frag
Para entender Dirty Frag, es imprescindible conocer a sus predecesoras.
-
Dirty Pipe (CVE-2022-0847), descubierta en 2022, demostró
que era posible sobreescribir archivos de solo lectura en Linux a través de
una condición de carrera en las estructuras internas de los pipes del kernel
(
struct pipe_buffer). Fue una de las vulnerabilidades más
impactantes de los últimos años.
-
La reciente
Copy Fail, la hermana menos conocida, refinó el concepto: en lugar de atacar
pipe_buffer, atacó los scatter-gather lists del
subsistema de criptografía del kernel (AF_ALG), logrando
escritura sobre páginas de caché a través de operaciones AEAD in-place.
Dirty Frag reproduce exactamente el mismo patrón, pero esta
vez el vector de ataque son los
fragmentos (frags) de los
socket buffers no lineales (struct sk_buff) que se
originan de una llamada splice().
El nombre no es accidental: "frag" refiere al campo frag del
sk_buff, análogo al pipe_buffer de Dirty Pipe.
Distribuciones afectadas
Este fragmento de vulnerabilidad se ha probado en las siguientes versiones de
distribución:
- Ubuntu 24.04.4: 6.17.0-23-generic
- RHEL 10.1: 6.12.0-124.49.1.el10_1.x86_64
- openSUSE Tumbleweed: 7.0.2-1-default
- CentOS Stream 10: 6.12.0-224.el10.x86_64
- AlmaLinux 10: 6.12.0-124.52.3.el10_1.x86_64
- Fedora 44: 6.19.14-300.fc44.x86_64
- ...
Mitigación
Debido a que se ha incumplido el calendario de divulgación responsable,
no existe ningún parche oficial para ninguna distribución. Se deben utilizar los siguiente comando para eliminar los módulos que contienen las
vulnerabilidades.
sudo tee /etc/modprobe.d/dirtyfrag.conf >/dev/null <<'EOF'
install esp4 /bin/false
install esp6 /bin/false
install rxrpc /bin/false
EOF
Eliminar los módulos:
sudo modprobe -r esp4 esp6 rxrpc 2>/dev/null || true
Verificar con:
cat /etc/modprobe.d/dirtyfrag.conf
El resultado esperado es:
install esp4 /bin/false
install esp6 /bin/false
install rxrpc /bin/false
En algunos casos, probablemente sea necesario reiniciar.
Estas directivas indican que, en lugar de cargar ese módulo, se ejecute
/bin/false (que simplemente retorna error). Es decir que,
se impide que esos módulos se carguen automáticamente en el
futuro, incluso si algún proceso los solicita.
El concepto central: criptografía sobre páginas "prestadas"
El corazón de Dirty Frag se puede explicar en términos simples:
-
splice() es una llamada al sistema que permite mover datos
entre descriptores de archivo sin copiarlos en espacio de usuario. Cuando un
proceso hace splice() de un archivo a un socket, el
kernel toma una referencia directa a la página de caché del archivo y la
planta en el buffer de transmisión del socket. El proceso que hizo el
splice() solo tiene permiso de lectura sobre ese archivo, pero
la página de caché ahora vive dentro del buffer de red.
-
El problema ocurre cuando el subsistema de red, al recibir ese paquete en el
lado receptor, realiza una operación criptográfica directamente sobre esa
misma página, modificándola en memoria. Como la página de caché es
compartida entre el archivo en disco y todos los procesos que lo lean, todos
los lectores posteriores verán la versión modificada, sin que haya ninguna
escritura en disco.
El impacto es permanente en RAM hasta que se limpia la caché o se reinicia el
sistema. El atacante puede reemplazar el contenido de archivos protegidos del
sistema operativo.
Las dos vulnerabilidades que componen Dirty Frag
Variante 1 — xfrm-ESP Page-Cache Write (requiere namespace de usuario)
XFRM es el framework de IPsec del kernel de Linux. Cuando
llega un paquete ESP (Encapsulating Security Payload), la función
esp_input() debe, ante un buffer no lineal, crear una copia
privada de los datos antes de aplicar criptografía. Sin embargo, existe una
rama de código que salta ese paso de copia cuando el buffer
tiene fragmentos pero no tiene una frag list.
El resultado: la operación de descifrado AEAD se ejecuta directamente sobre la
página de caché plantada por splice(). Peor aún, parte del
preprocesamiento del protocolo ESN realiza un
write de 4 bytes en una posición del buffer que el atacante
puede controlar con precisión, y cuyo valor proviene de un campo del
encabezado ESP que el propio atacante especificó al registrar la asociación de
seguridad. La verificación de autenticación falla después de que la
escritura ya ocurrió, por lo que el error es irrelevante.
Primitiva: Escritura arbitraria de
4 bytes en cualquier offset de un archivo de caché de solo
lectura. Requiere crear un namespace de usuario (capacidad disponible en la
mayoría de sistemas Ubuntu/Debian/Fedora por defecto).
Impacto en la explotación: Con 48 escrituras consecutivas de
4 bytes, el exploit reemplaza los primeros 192 bytes de
/usr/bin/su con un ELF mínimo que llama directamente a
setuid(0) y lanza /bin/sh. Al ejecutar
/usr/bin/su, el bit setuid-root eleva los privilegios y se
obtiene una shell de root, sin pasar por PAM.
Parche: Fusionado en el árbol netdev el 7 de mayo de
2026. Agrega una verificación del flag SKBFL_SHARED_FRAG antes de
saltar la etapa de copia, marcando explícitamente como "compartidas" las
páginas que provienen de splice().
Variante 2 — RxRPC Page-Cache Write (sin privilegios especiales)
RxRPC es el protocolo de red usado por el sistema de archivos
distribuido AFS (Andrew File System) de IBM. Su
implementación en Linux incluye un mecanismo de seguridad llamado
rxkad que, para verificar paquetes de datos, realiza un
descifrado in-place de 8 bytes usando el algoritmo pcbc(fcrypt).
Al igual que con ESP, si el paquete proviene de un splice() con
una página de caché en el fragmento, esa operación criptográfica escribe 8
bytes directamente sobre la página. La diferencia clave: el valor escrito no
es arbitrario, sino el resultado de fcrypt_decrypt(C, K), donde
K es la clave de sesión del token RxRPC que el atacante registró.
Dado que fcrypt tiene un espacio de clave de 56 bits y es
determinista, el atacante puede hacer
búsqueda por fuerza bruta en espacio de usuario hasta
encontrar la K que produce exactamente los 8 bytes deseados. Con
una velocidad de ~18 millones de intentos por segundo, encontrar claves para
objetivos parcialmente restringidos toma desde milisegundos hasta ~1 segundo.
Esta variante no requiere ningún privilegio especial:
add_key(), socket(AF_RXRPC), splice() y
recvmsg() son syscalls accesibles por cualquier usuario.
Impacto en la explotación: El exploit modifica la
línea root de /etc/passwd para eliminar el campo de
contraseña (root::0:0:...). PAM, con la configuración
nullok habitual en Ubuntu, acepta la autenticación sin contraseña
y otorga acceso root.
Parche: Propuesto pero
aún sin fusionar en upstream al momento de la divulgación. El
fix agrega una condición adicional para forzar la copia del buffer cuando el
skb es no lineal, evitando que la página de caché llegue al sink del
descifrado.
Chaining: Por qué la combinación es más Peligrosa que cada parte
Ninguna de las dos variantes por sí sola funciona en todos los entornos:
| Variante |
Requiere namespace de usuario |
Necesita módulo rxrpc.ko |
| xfrm-ESP |
✅ Sí |
❌ No |
| RxRPC |
❌ No |
✅ Sí |
La genialidad del exploit final es que
encadena ambas en un único binario:
-
Intenta primero la variante ESP (más poderosa, escritura directa y
arbitraria).
-
Si falla (porque el sistema bloquea
unshare(CLONE_NEWUSER) o no
tiene el módulo ESP cargado), cae automáticamente en la variante RxRPC.
Ubuntu —el sistema con mayores restricciones de namespaces vía AppArmor— carga
rxrpc.ko por defecto, por lo que el fallback funciona
precisamente allí. RHEL y distribuciones empresariales típicamente permiten
namespaces de usuario pero no incluyen rxrpc.ko, lo que activa la
variante ESP.
Un solo binario cubre la mayoría de las distribuciones Linux.
Impacto y Mitigaciones
Distribuciones afectadas: La mayoría de Linux con kernels sin
parchear: Ubuntu, Debian, Fedora, RHEL (con variantes distintas), Arch, y
cualquier otra que use el kernel mainline antes del parche.
Mitigación inmediata:
-
Aplicar el parche del kernel (fusionado el 7/5/2026 en netdev).
-
Como workaround temporal: deshabilitar la creación de namespaces de usuario
no privilegiados (
kernel.unprivileged_userns_clone=0 en sysctl)
bloquea la variante ESP, pero no la variante RxRPC.
-
Descargar o deshabilitar
rxrpc.ko bloquea la variante RxRPC.
Nota importante: La mitigación popularmente conocida para
Copy Fail —bloquear algif_aead—
no protege contra Dirty Frag, ya que esta vulnerabilidad es
completamente independiente de ese módulo.
Conclusión
Dirty Frag es un recordatorio de que los patrones de vulnerabilidad no
mueren: evolucionan.
El mismo concepto que Dirty Pipe explotó en los pipes del kernel
apareció años después en el subsistema de red, en no uno sino dos caminos de
código completamente distintos. La capacidad del investigador de encadenar
ambas variantes para cubrir distintos entornos eleva significativamente la
severidad práctica del hallazgo.
La velocidad de respuesta del equipo del kernel fue notable —parche
fusionado en menos de una semana— pero el hecho de que la promesa de tiempo
fuera rota prematuramente expone la tensión permanente entre responsabilidad
coordinada y la realidad de que, una vez que más de una persona conoce una
vulnerabilidad crítica, el control de la información se vuelve muy frágil.
Fuente original: write-up de Hyunwoo Kim (@v4bel) —
github.com/V4bel/dirtyfrag