⏱️ Lectura: 25 min

El 7 de mayo de 2026, el investigador de seguridad surcoreano Hyunwoo Kim (@v4bel) publicó en su repositorio dirtyfrag en GitHub la divulgación completa, con prueba de concepto funcional, de una nueva clase de escalada de privilegios local en el kernel Linux. La llamó Dirty Frag, en línea explícita con la genealogía de Dirty COW (2016) y Dirty Pipe (2022). El nombre no es marketing: el exploit ataca el manejo de fragmentos de socket (skb_frag_list) en el page cache del kernel, y a partir de ahí escribe en archivos privilegiados como /etc/passwd o /usr/bin/su. El resultado es root, sin condiciones de carrera, sin pánico de kernel, sin reinicio.

📑 En este artículo
  1. TL;DR de Dirty Frag
  2. Línea temporal: anatomía de un embargo roto
  3. Anatomía de CVE-2026-43284: el bug en xfrm-ESP
    1. El primitivo de exploitación
    2. Pre-requisitos del atacante para el bug de ESP
  4. Anatomía de CVE-2026-43500: el bug en RxRPC
    1. El primitivo de RxRPC
    2. Pre-requisitos del atacante para RxRPC
  5. La estrategia de cadena: ESP first, RxRPC fallback
  6. Distribuciones afectadas y kernels confirmados
  7. Parches y respuestas vendor
  8. Mitigación inmediata: blacklist + drop_caches
  9. Implicaciones para Kubernetes y multi-tenant
  10. Verificá si tu sistema es vulnerable
  11. Por qué «Dirty Frag»: la genealogía de la familia
  12. Lecciones operativas para SREs y devs LATAM
  13. La decisión de Kim: por qué publicar sin parches universales
  14. FAQ
    1. ¿Mi laptop personal corriendo Ubuntu Desktop está afectada?
    2. ¿Funciona si solo tengo SSH como usuario sin privilegios en un servidor remoto?
    3. ¿Y si el servidor tiene SELinux enforcing?
    4. ¿Puedo detectar si me explotaron con auditd?
    5. ¿KernelCare es la solución correcta para producción que no puede reiniciar?
    6. ¿Por qué Sophos dice «Not affected» en todos sus productos?
    7. ¿El bug afecta también a Android?
    8. ¿Hay PoCs alternativos al de Kim?
    9. ¿Cuál es el costo de no aplicar la mitigación si mi servidor solo es accesible vía VPN corporativa?
  15. Referencias
    1. 📚 Artículos relacionados

Las dos vulnerabilidades que componen la cadena son CVE-2026-43284 (subsistema xfrm-ESP, presente desde el 17 de enero de 2017) y CVE-2026-43500 (subsistema RxRPC, introducida en junio de 2023). Canonical y Red Hat las clasifican como HIGH (CVSS 7.8). La primera ya tiene parche en el árbol upstream netdev —merge del commit f4c50a4034e6 el 7 de mayo—; la segunda sigue sin parche aceptado al momento de redactar esto. El embargo se rompió cuando un tercero ajeno a la coordinación publicó detalles parciales del bug de ESP, y Hyunwoo Kim decidió liberar el writeup completo y el PoC para que defensores y proveedores tuvieran al menos paridad informativa con potenciales atacantes.

Este artículo desarma la cadena pieza por pieza: qué es exactamente un page cache write, por qué los fragmentos de un socket buffer rompen la suposición de copy-on-write del kernel, cómo un usuario sin privilegios convierte un STORE de 4 bytes en un shell de root, qué distribuciones están afectadas y cuáles tienen parche, y qué medidas concretas tomar hoy —antes de que Red Hat, Ubuntu o SUSE liberen el kernel actualizado en sus repos estables—.

TL;DR de Dirty Frag

  • Investigador: Hyunwoo Kim (@v4bel)
  • Divulgación pública: 7 de mayo de 2026 (forced disclosure tras embargo roto)
  • Reporte a maintainers: 30 de abril de 2026
  • CVEs: CVE-2026-43284 (xfrm-ESP) y CVE-2026-43500 (RxRPC)
  • Severidad: CVSS 7.8 HIGH (asignación de Canonical y Red Hat; oficial pendiente)
  • Bug class: page-cache write primitive vía splice() y operaciones criptográficas in-place
  • Versiones afectadas: prácticamente todo kernel mainline desde 4.10 (xfrm-ESP, 2017-01-17) y desde 6.5 (RxRPC, junio 2023)
  • Distros confirmadas vulnerables: Ubuntu 24.04.4, RHEL 10.1, openSUSE Tumbleweed, CentOS Stream 10, AlmaLinux 10, Fedora 44
  • Parche xfrm-ESP: aplicado upstream en netdev tree (commit f4c50a4034e6)
  • Parche RxRPC: pendiente al 9 de mayo de 2026
  • Mitigación inmediata: blacklistear módulos esp4, esp6, rxrpc y limpiar page cache
  • PoC público: gcc -O0 -Wall -o exp exp.c -lutil desde el repo V4bel/dirtyfrag (3.2k estrellas en 48h)

«Dirty Frag is a case that extends the bug class to which Dirty Pipe and Copy Fail belong. Because it is a deterministic logic bug that does not depend on a timing window, no race condition is required.»
Hyunwoo Kim, en la documentación pública del exploit

La frase clave es «deterministic logic bug». Dirty COW dependía de una race condition entre madvise(MADV_DONTNEED) y un write a un mapping COW; era confiable solo después de varios intentos. Dirty Pipe necesitaba un splice previo más una operación específica de escritura a pipe sobre páginas con flag PIPE_BUF_FLAG_CAN_MERGE heredado. Dirty Frag elimina ambas variables: la lógica del bug se dispara con una secuencia de syscalls deterministas, y el primer disparo ya escribe.

Línea temporal: anatomía de un embargo roto

Fecha Evento
2017-01-17 Bug de xfrm-ESP introducido en el kernel mainline. Una optimización en esp_input() añade el goto skip_cow cuando un skb no está clonado y sí tiene nr_frags. La intención era evitar copias innecesarias en hot path; el efecto colateral es que páginas spliced del page cache pueden bypassear el copy-on-write.
2023-06 Bug de RxRPC introducido en net/rxrpc/call_event.c durante una refactorización del manejo de skbs no lineales. La verificación se queda en skb_cloned(skb) sin revisar skb->data_len.
2026-04-30 Hyunwoo Kim reporta la cadena completa al equipo de Linux kernel maintainers vía la lista privada de seguridad.
2026-05-07 Embargo roto: un tercero publica análisis parcial del bug de ESP. Kim decide divulgación pública controlada y libera writeup + PoC. El parche para CVE-2026-43284 entra al árbol netdev como commit f4c50a4034e6. RxRPC queda sin parche.
2026-05-08 Microsoft Threat Intelligence reporta intentos limitados de explotación in-the-wild. Red Hat, Ubuntu, SUSE, Canonical, Amazon Linux, Debian y Rocky Linux publican advisories oficiales. CloudLinux libera kernel parchados.
2026-05-09 KernelCare distribuye livepatch para producción sin reboot. CVE-2026-43500 sigue sin merge upstream; los advisories vendor recomiendan blacklist como mitigación primaria.

«The vulnerability’s embargo was broken after detailed information and an exploit for the xfrm-ESP flaw were published by an unrelated third party, forcing public disclosure despite patches remaining unavailable.»
The Hacker News, 8 de mayo de 2026

Este es el patrón recurrente de la divulgación coordinada cuando hay múltiples investigadores trabajando en paralelo sobre la misma superficie de ataque. El protocolo formal asume buena fe entre las partes; cuando una parte se desvía, las demás enfrentan un dilema: publicar antes de tener parches y dar paridad informativa a defensores, o esperar y dejar que solo los atacantes con acceso privado al material filtrado tengan ventaja. La decisión de Kim fue publicar.

Anatomía de CVE-2026-43284: el bug en xfrm-ESP

El xfrm framework es la implementación de IPsec en el kernel Linux. El módulo ESP (Encapsulating Security Payload, definido en RFC 4303) se encarga de cifrar y autenticar paquetes IP. Para servidores que terminan túneles IPsec —VPNs corporativas, conexiones site-to-site, mesh networks— este código se ejecuta para cada paquete recibido. Es performance-critical, y cualquier copia innecesaria de buffers tiene impacto visible.

El bug vive en net/ipv4/esp4.c (y su gemelo net/ipv6/esp6.c) en la función esp_input(), que se invoca al recibir un paquete ESP cifrado. El flujo conceptual es: validar el paquete, asegurar que el buffer no es compartido (copy-on-write), y luego pasar el contenido a la AEAD para descifrado in-place. La optimización que introduce el bug es esta:

if (!skb_cloned(skb)) {
    if (!skb_is_nonlinear(skb)) {
        nfrags = 1;
        goto skip_cow;
    } else if (!skb_has_frag_list(skb)) {
        nfrags = skb_shinfo(skb)->nr_frags;
        nfrags++;
        goto skip_cow;  /* Vulnerable: skips copy-on-write */
    }
}

La condición se lee así: «si el skb no es clonado y o bien es lineal, o bien tiene fragmentos pero ningún frag_list, entonces saltarse la copia». La hipótesis implícita del autor del código es que un skb no clonado que el atacante envía vía socket tiene fragmentos privados al kernel. Pero el atacante puede sembrar el nr_frags con páginas que él controló previamente vía splice() desde un archivo de solo lectura del filesystem.

Cuando la ejecución continúa después de skip_cow, el kernel invoca a la cadena de descifrado AEAD. En crypto_authenc_esn_decrypt() —el código que maneja ESP con sequence numbers extendidos—, el preprocessing de la sequence number ejecuta:

scatterwalk_map_and_copy(tmp+1, dst, assoclen+cryptlen, 4, 1);

Ese 1 final es el flag de escritura. La operación copia 4 bytes de tmp+1 (controlados por el atacante vía el atributo netlink XFRMA_REPLAY_ESN_VAL, donde se inyecta la parte alta de 32 bits del sequence number) a la posición assoclen+cryptlen dentro del scatter-gather list dst. Si el atacante alineó previamente las páginas del page cache de /usr/bin/su en posiciones específicas del SG list, esos 4 bytes terminan reescribiendo bytes específicos del binario su mientras está cacheado en RAM.

El primitivo de exploitación

La capacidad que extrae el atacante es: «escribir 4 bytes arbitrarios en un offset arbitrario de una página del page cache». Para construir un shell de root completo, Kim escribe un binario ELF de 192 bytes que contiene esencialmente setuid(0); execve("/bin/sh"). Eso requiere 48 invocaciones del primitivo —una por cada chunk de 4 bytes del payload—. Cada invocación es una serie de syscalls xfrm_state_add + sendmsg con datos cuidadosamente formateados.

┌──────────── Atacante (userspace) ────────────┐
│ 1. unshare(CLONE_NEWUSER)        # CAP_NET_ADMIN
│ 2. socket(AF_INET, SOCK_RAW, …)  # canal ESP
│ 3. open("/usr/bin/su", O_RDONLY)
│ 4. splice(fd_su, NULL, pipe[1])  # planta páginas en pipe
│ 5. vmsplice(pipe[0], iov, ...)   # extrae páginas como frags
│ 6. xfrm_state_add(SPI, key, ESN) # registra SA
│ 7. sendmsg(esp, controlled_buf)  # ejecuta esp_input()
│       └─→ esp_input() ─→ skip_cow ─→ AEAD decrypt
│              └─→ scatterwalk_map_and_copy()
│                  └─→ 4-byte STORE en page cache /usr/bin/su
│ 8. drop_caches() opcional        # forzar visibilidad
│└──────────────────────────────────────────────┘

Pre-requisitos del atacante para el bug de ESP

El bug requiere CAP_NET_ADMIN para registrar las XFRM Security Associations. En sistemas modernos esto se obtiene vía unshare(CLONE_NEWUSER), que da al usuario un user namespace con privilegios elevados dentro del namespace pero sin afectar al root real. La mayoría de las distros permite esto por default —es lo que habilita rootless containers, sandboxes de browser y sistemd-nspawn—.

Sistemas que bloquean la creación de user namespaces sin privilegios eran inmunes al bug de ESP, pero no al de RxRPC. Ubuntu por default no bloquea, aunque AppArmor en algunos casos limita. Para verificar:

sysctl kernel.unprivileged_userns_clone
# Si imprime "0", user namespaces unprivileged están bloqueados
sysctl user.max_user_namespaces
# Si es 0, también está bloqueado

Anatomía de CVE-2026-43500: el bug en RxRPC

El protocolo RxRPC (Remote Procedure Call sobre UDP) es el transport layer del Andrew File System (AFS), un sistema de archivos distribuido que se usa principalmente en universidades y entornos corporativos legacy. La mayoría de los servidores Linux modernos no lo cargan, pero Ubuntu lo distribuye con rxrpc.ko en la imagen del kernel por default, y se carga automáticamente cuando un programa abre un socket AF_RXRPC. Cualquier usuario sin privilegios puede crearlo:

# Carga rxrpc.ko on-demand sin privilegios
strace -e openat,socket bash -c 'exec 3<>/dev/null'  # not enough
python3 -c "import socket; s=socket.socket(34, socket.SOCK_DGRAM, 0)" 2>&1
# AF_RXRPC = 34

El bug vive en rxkad_verify_packet_1() —la función de verificación del modo de seguridad rxkad de RxRPC— en net/rxrpc/call_event.c cerca de la línea 337. El código vulnerable:

skcipher_request_set_crypt(req, sg, sg, 8, iv.x);  /* src == dst */
ret = crypto_skcipher_decrypt(req);                /* 8-byte STORE */

Notar req, sg, sg: la operación de descifrado opera in-place sobre el mismo scatter-gather list para input y output. Si sg apunta a páginas spliced del page cache, el 8-byte STORE del descifrador termina escribiendo sobre el contenido cacheado del archivo.

La verificación previa al descifrado:

if (skb_cloned(skb)) {
    /* slow path: copiar y luego descifrar */
}

La intención era detectar skbs compartidos. Pero un skb no clonado puede tener data_len > 0 y un frag list con páginas spliced; el check no las detecta. El correcto sería:

if (skb_cloned(skb) || skb->data_len) {
    /* slow path: copiar */
}

Ese es exactamente el parche que Hyunwoo Kim propuso y que está pendiente de merge upstream.

El primitivo de RxRPC

A diferencia de ESP, RxRPC produce un STORE de 8 bytes en lugar de 4. La estructura del bloque escrito es fcrypt_decrypt(C, K) donde:

  • C = ciphertext en el offset target del archivo (el atacante elige cuál)
  • K = la clave de sesión rxkad, que el atacante controla cuando construye el token de autenticación inicial

El atacante prueba valores de K en userspace —que no requiere privilegios— hasta que fcrypt_decrypt(C, K) produce el plaintext deseado. Para reescribir la primera línea de /etc/passwd con root::0:0:GGGGGG: (sin password), Kim ejecuta tres escrituras superpuestas de 8 bytes con semántica last-write-wins.

Pre-requisitos del atacante para RxRPC

  • El módulo rxrpc.ko debe estar disponible (lo está por default en Ubuntu, no en RHEL).
  • No requiere user namespace ni capability alguna.
  • La máquina debe tener al menos un proceso que abra un socket AF_RXRPC, lo cual el propio atacante puede hacer.

Esto hace al bug de RxRPC más peligroso que el de ESP en sistemas Ubuntu desktop o cloud que no han endurecido el kernel: cualquier usuario local con shell, incluso uno sandboxed por seccomp por default, puede ejecutarlo si la política seccomp no bloquea explícitamente AF_RXRPC.

La estrategia de cadena: ESP first, RxRPC fallback

El binario PoC de Kim (exp.c en el repo V4bel/dirtyfrag) implementa una estrategia adaptativa:

  1. Intenta ESP primero: si unshare(CLONE_NEWUSER) y xfrm_state_add funcionan, ejecuta la cadena ESP. Es más eficiente —4 bytes por shot, target binario /usr/bin/su que el atacante puede invocar directamente—.
  2. Falla a RxRPC si ESP está bloqueado: si los user namespaces están deshabilitados o el módulo esp4 no se carga, prueba abrir socket AF_RXRPC. Si funciona, ejecuta la cadena RxRPC con escrituras de 8 bytes a /etc/passwd.
  3. Limpia evidencia: tras obtener root, ejecuta echo 3 > /proc/sys/vm/drop_caches para forzar relectura desde disco y eliminar la modificación de la copia en memoria. Si el atacante quiere persistencia tendrá que escribir al disco con su nuevo root; si solo quiere ejecutar comandos puntuales y desaparecer, la limpieza del cache lo hace casi indetectable.

«ESP variant: Powerful 4-byte arbitrary write, but blocked where user namespaces are restricted. RxRPC variant: Works unprivileged but depends on module availability. The two cover each other’s weaknesses.»
Wiz Research blog

Compila con:

gcc -O0 -Wall -o exp exp.c -lutil

El -O0 es deliberado: la cadena depende de la layout exacto de buffers en stack que los optimizadores reordenarían.

Distribuciones afectadas y kernels confirmados

Hyunwoo Kim tested la cadena en seis distribuciones:

Distro Versión Kernel Estado
Ubuntu 24.04.4 LTS 6.17.0-23 Vulnerable a ambas
RHEL 10.1 6.12.0-124.49.1 Vulnerable a ESP (RxRPC ausente)
openSUSE Tumbleweed 7.0.2-1 Vulnerable a ambas
CentOS Stream 10 6.12.x Vulnerable a ESP
AlmaLinux 10 6.12.x Vulnerable a ESP
Fedora 44 6.17.x Vulnerable a ambas

Ubuntu confirmó en su advisory oficial que todas las releases desde Trusty Tahr (14.04 LTS) hasta Resolute Raccoon (26.04 LTS) están afectadas. CloudLinux por su parte detalló en su post que CL7 regular no está afectado (kernel demasiado viejo, anterior a la introducción del bug en RxRPC y con ESP shipped pero hardened), mientras CL7 Hybrid, CL8, CL9 y CL10 sí.

«Any unprivileged local user can use it to gain root in a single command.»
CloudLinux Blog, 9 de mayo de 2026

Parches y respuestas vendor

Vendor Stream Kernel parchado Estado
Linux mainline netdev tree commit f4c50a4034e6 (ESP) Mergeado 7 mayo
Linux mainline RxRPC Pendiente al 9 mayo
Red Hat RHEL 10 en proceso Expedited release announced
Red Hat RHEL 9 en proceso Expedited release announced
Red Hat RHEL 8 en proceso Expedited release announced
Ubuntu 24.04 LTS en proceso Patches when available
CloudLinux CL8 kernel-4.18.0-553.123.2.lve Disponible en stable
CloudLinux CL9 kernel-5.14.0-611.54.3.el9_7 Disponible en stable
CloudLinux CL10 kernel-6.12.0-124.55.2.el10_1 Disponible en stable
KernelCare livepatch Disponible sin reboot

El patch de ESP en mainline cambia la condición que dispara skip_cow para incluir la verificación de fragmentos compartidos:

} else if (!skb_has_frag_list(skb) && !skb_has_shared_frag(skb)) {

El patch propuesto para RxRPC fuerza la copia cuando el skb tiene data_len > 0:

if (skb_cloned(skb) || skb->data_len) {
    /* slow path */
}

Ambos parches son intervenciones quirúrgicas: añaden una condición a un check existente, sin reorganizar lógica circundante. Esto hace que sean candidatos ideales para backport a kernels LTS (5.4, 5.10, 5.15, 6.1, 6.6, 6.12).

Mitigación inmediata: blacklist + drop_caches

Mientras los parches kernel de tu distro se preparan, la única mitigación universal es deshabilitar los módulos vulnerables y purgar el page cache. CloudLinux, Ubuntu, Red Hat y Sophos coinciden en esta secuencia:

# 1. Crear archivo modprobe blacklist
sudo sh -c "cat > /etc/modprobe.d/dirty-frag.conf << 'EOF'
install esp4 /bin/false
install esp6 /bin/false
install rxrpc /bin/false
EOF"

# 2. Descargar módulos si están cargados
sudo rmmod esp4 esp6 rxrpc 2>/dev/null

# 3. Purgar page cache (elimina cualquier modificación previa cacheada)
echo 3 | sudo tee /proc/sys/vm/drop_caches

# 4. Regenerar initramfs
sudo update-initramfs -u            # Debian / Ubuntu
sudo dracut --force                 # RHEL / Fedora / openSUSE

# 5. Reboot recomendado para garantizar que módulos ya no cargan
sudo reboot

⚠️ Caveat crítico: El blacklist de esp4 y esp6 rompe IPsec. Si tu servidor termina túneles VPN site-to-site, mesh WireGuard sobre ESP, o cualquier configuración StrongSwan / Libreswan, esta mitigación corta la conectividad.
Para esos casos: KernelCare livepatch (sin reboot, sin perder IPsec) o esperar al kernel parchado de tu distro.

💡 El blacklist de rxrpc es seguro en la mayoría de servidores web/cloud. AFS está prácticamente extinto fuera de entornos universitarios y CMU/MIT legacy. Si tu inventario no incluye AFS, deshabilitar rxrpc es zero-impact.

Para Windows administradores que gestionan WSL2:

# WSL2 corre un kernel Linux real, también afectado.
# Reiniciar WSL para tomar kernel actualizado tras update:
wsl --shutdown

Para macOS no aplica: el kernel XNU no comparte código con Linux.

Implicaciones para Kubernetes y multi-tenant

El escenario más preocupante de Dirty Frag es cualquier máquina Linux donde múltiples usuarios o workloads sin confianza compartan el mismo kernel. Eso incluye:

  • Nodos de Kubernetes corriendo pods de tenants distintos.
  • VPS compartidos —hosting tipo Hetzner, DigitalOcean droplets sin dedicación—.
  • Ambientes de CI/CD multi-job sobre el mismo runner.
  • Workstations multi-usuario con SSH abierto a desarrolladores.

Nebius propuso un patrón DaemonSet para Kubernetes que aplica el blacklist a nivel de nodo antes de que ningún pod arranque:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: dirtyfrag-mitigation
  namespace: kube-system
spec:
  selector:
    matchLabels:
      name: dirtyfrag-mitigation
  template:
    metadata:
      labels:
        name: dirtyfrag-mitigation
    spec:
      hostPID: true
      hostNetwork: true
      tolerations:
        - operator: Exists
      initContainers:
        - name: apply-blacklist
          image: busybox:stable
          securityContext:
            privileged: true
          command:
            - sh
            - -c
            - |
              chroot /host sh -c '
                cat > /etc/modprobe.d/dirty-frag.conf <<EOF
              install esp4 /bin/false
              install esp6 /bin/false
              install rxrpc /bin/false
              EOF
                rmmod esp4 esp6 rxrpc 2>/dev/null
                echo 3 > /proc/sys/vm/drop_caches
              '
          volumeMounts:
            - name: host-root
              mountPath: /host
      containers:
        - name: pause
          image: registry.k8s.io/pause:3.9
      volumes:
        - name: host-root
          hostPath:
            path: /

El patrón corre como initContainer privileged que monta / del host y aplica el blacklist + drop cache antes de que el pod principal (que solo es un pause) quede running. El DaemonSet asegura que cada nodo nuevo del cluster recibe la mitigación automáticamente.

Para entornos donde IPsec es necesario en algunos nodos —edge gateways, VPN terminators—, dividí el cluster en pools con nodeSelectors:

  • Pool crypto-enabled: sin la mitigación. Aplicá KernelCare livepatch o tomá kernel parchado primero.
  • Pool default: con la mitigación DaemonSet. El bug de ESP queda inalcanzable.

Verificá si tu sistema es vulnerable

Linux/macOS:

# 1. Ver versión del kernel
uname -r

# 2. Ver si los módulos vulnerables están cargados
lsmod | grep -E '^(esp4|esp6|rxrpc)\b'

# 3. Verificar si el kernel ya tiene el parche xfrm-ESP
zcat /proc/config.gz 2>/dev/null | grep CONFIG_XFRM_ESP
# Si CONFIG_XFRM_ESP=m o =y, el módulo está habilitado y aplicable

# 4. Chequear si user namespaces sin privilegios están permitidos
sysctl kernel.unprivileged_userns_clone 2>/dev/null
sysctl user.max_user_namespaces

# 5. Probar que el módulo rxrpc se carga on-demand (Ubuntu típico)
python3 -c "import socket; socket.socket(34, 2, 0)" 2>&1 | head -3

Windows con WSL2:

# Versión del kernel WSL
wsl uname -r
# Estado de actualizaciones
wsl --update --status

Si lsmod muestra alguno de los módulos cargados Y kernel.unprivileged_userns_clone=1, sos vulnerable a la cadena completa. Si solo tenés rxrpc cargado, sos vulnerable al bug de RxRPC sin necesidad de namespaces.

Por qué «Dirty Frag»: la genealogía de la familia

Hyunwoo Kim eligió el nombre deliberadamente. La familia de «Dirty » en kernel Linux tiene un linaje técnico que describe la superficie atacada*:

Año Nombre CVE Surface Primitivo
2016 Dirty COW CVE-2016-5195 mm/gup.c __get_user_pages() Race entre madvise(MADV_DONTNEED) y write
2022 Dirty Pipe CVE-2022-0847 lib/iov_iter.c + pipe buffers splice + PIPE_BUF_FLAG_CAN_MERGE heredado
2024 Copy Fail (sin CVE público) algif_aead + page cache In-place AEAD sobre páginas spliced
2026 Dirty Frag CVE-2026-43284 + CVE-2026-43500 xfrm-ESP + RxRPC In-place AEAD sobre páginas spliced sin algif

Los cuatro tienen un patrón común: el atacante usa splice() para colocar páginas del page cache de un archivo de solo lectura dentro de un buffer del kernel, y luego invoca una operación que escribe in-place sobre ese buffer. La diferencia entre cada generación es qué función concreta del kernel es la que escribe.

«Both flaws allow modification of page-cache-backed memory that is not exclusively owned by the kernel, enabling corruption of sensitive files and ultimately privilege escalation.»
Wiz Research

El insight estructural es que splice() —una primitiva diseñada para zero-copy networking— viola implícitamente la suposición de que las páginas que llegan a un syscall determinado son de propiedad exclusiva del kernel. Cada vez que un nuevo subsistema asume «skbs no clonados son seguros para in-place ops», aparece una nueva variante de la familia. La pregunta abierta entre los kernel maintainers es si el remedio correcto es endurecer cada subsistema individualmente —el approach actual— o introducir una invariante a nivel de skb que impida que páginas del page cache lleguen a operaciones de escritura.

Lecciones operativas para SREs y devs LATAM

  1. Tu superficie de ataque local importa. La mayoría de los runbooks de seguridad latinoamericanos asumen que un atacante necesita primero RCE remoto para llegar al kernel. Dirty Frag desmiente eso: cualquier shell user-level local —SSH legítimo, contenedor escapado, exploit web no privilegiado— se convierte en root en una sola invocación. Si vos manejás un VPS compartido, un cluster K8s multi-tenant o un servidor con cuentas SSH para colaboradores externos, el blast radius es directo.

  2. El kernel del cloud provider no necesariamente está parchado. EC2, Compute Engine, Azure VMs y Nebius Compute corren la imagen de Linux que vos elegiste. Si tu AMI usa Ubuntu 24.04 LTS y todavía no aplicaste el blacklist o esperás kernel actualizado, el provider no te protege. Aplicá la mitigación a nivel de tu workload.

  3. Las imágenes Docker base están afectadas indirectamente. El kernel viene del host, no del container. Pero las herramientas dentro del container pueden facilitar la explotación: gcc para compilar el PoC, unshare user namespace si el container corre en modo privileged. Endurecé tus pods con securityContext.allowPrivilegeEscalation: false, runAsNonRoot: true, y seccomp profiles que bloqueen unshare(CLONE_NEWUSER) y socket(AF_RXRPC).

  4. WSL2 hereda el kernel Linux real. Si usás WSL2 en Windows para desarrollo y le pusiste credenciales reales o secrets, el kernel Microsoft-mantenido es vulnerable hasta que liberen update. wsl --update regularmente.

  5. El monitoreo de page cache es no-trivial. EDRs comerciales —CrowdStrike, SentinelOne, Defender for Endpoint— detectan modificaciones de archivos en disco, no en page cache. Una explotación Dirty Frag que no toca disco es invisible para esos productos. La detección útil es a nivel kernel: auditar invocaciones de xfrm_state_add desde namespaces no privilegiados, alertar sobre uso de socket(AF_RXRPC) por procesos no esperados.

La decisión de Kim: por qué publicar sin parches universales

«I felt compelled to make the vulnerabilities public — without updates for affected Linux distributions or a CVE vulnerability entry being available.»
Hyunwoo Kim, citado por heise online, 8 de mayo de 2026

La frase resume el dilema clásico de la divulgación coordinada cuando una parte rompe el embargo. Kim había seguido el protocolo: reportó a maintainers el 30 de abril, esperó coordinación, no publicó nada. Cuando un tercero —cuyas motivaciones siguen sin ser públicas— filtró un análisis parcial del bug de ESP, Kim enfrentó la opción de mantener silencio (dejando solo a actores con acceso al material filtrado con conocimiento operativo) o publicar el writeup completo y el PoC funcional para que defensores, vendors y operadores tuvieran al menos paridad informativa.

Publicar fue la decisión éticamente defendible y la que está alineada con el consenso histórico de la comunidad de full-disclosure. El costo —miles de servidores Linux explotables durante días hasta que vendors emitan parches— se pagó parcialmente con el ESP patch upstream el mismo día y con los vendor advisories en menos de 24 horas. RxRPC sigue sin parche al momento de redactar; ese es el costo residual del embargo roto.

El repositorio V4bel/dirtyfrag acumuló 3.2k estrellas en 48 horas y 511 forks, números que indican adopción masiva tanto por researchers como por equipos de red team y blue team. La asimetría informativa que la decisión de Kim eliminó era real.

FAQ

¿Mi laptop personal corriendo Ubuntu Desktop está afectada?

Sí. El bug aplica a cualquier kernel Linux mainline desde 4.10 (xfrm-ESP) y 6.5 (RxRPC). Aplicá el blacklist como medida temporal y apt update && apt full-upgrade cuando Ubuntu publique el kernel parchado en archivos.

¿Funciona si solo tengo SSH como usuario sin privilegios en un servidor remoto?

Sí. Todo el exploit corre desde userspace sin necesidad de privilegios previos. SSH como cualquier cuenta válida es suficiente.

¿Y si el servidor tiene SELinux enforcing?

Reduce el riesgo de las técnicas más obvias —target binarios protegidos como /usr/bin/su— pero no lo elimina. Los offsets escribibles dependen de qué archivos del page cache son accesibles para el contexto del atacante. SELinux no es una mitigación completa.

¿Puedo detectar si me explotaron con auditd?

Detectar la ejecución es muy difícil porque el bug no genera entradas auditd estándar. Sí podés detectar las precondiciones: log de unshare(CLONE_NEWUSER), log de xfrm_state_add por usuarios no admin, log de socket(AF_RXRPC). Configurá rules específicas para esas tres syscalls y tag los logs como high-priority.

¿KernelCare es la solución correcta para producción que no puede reiniciar?

Sí, si tu compliance permite livepatching. KernelCare aplica el parche al kernel running sin reboot y mantiene IPsec/RxRPC funcionales. Es la opción menos disruptiva para servidores con SLA de uptime estricto.

¿Por qué Sophos dice «Not affected» en todos sus productos?

Porque Sophos Endpoint, Firewall, Email y wireless products no exponen los módulos esp4, esp6 o rxrpc en sus paths de ejecución activos. Si tu superficie no incluye los módulos, la vulnerabilidad no es alcanzable. Eso vale para appliances específicos, no para tu OS Linux genérico.

¿El bug afecta también a Android?

Android usa kernel Linux, pero el subsistema xfrm-ESP rara vez está habilitado en builds AOSP de teléfonos consumer, y RxRPC nunca lo está. El riesgo en Android es marginal salvo en builds custom server-oriented.

¿Hay PoCs alternativos al de Kim?

Sí. Apareció un PoC adicional titulado «Copy Fail 2: Electric Boogaloo» según el análisis de Tenable. El nombre referencia Copy Fail (2024) y subraya que el patrón es reutilizable.

¿Cuál es el costo de no aplicar la mitigación si mi servidor solo es accesible vía VPN corporativa?

Reducís el riesgo a «atacante con credenciales VPN compromiso + cuenta SSH». Es menor pero no cero. Cualquier cuenta de servicio o desarrollador comprometida convierte el bug en root.

Referencias

Categorías: Seguridad

Clara Vásquez

Analista de ciberseguridad enfocada en vulnerabilidades críticas, zero-days y amenazas emergentes. Cubre CVEs de alto impacto, análisis de malware, incidentes de ransomware y tendencias de seguridad para LATAM.

0 Comentarios

Deja un comentario

Marcador de posición del avatar

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.