DEV Community

Cover image for Dirty Frag (CVE-2026-43284 y CVE-2026-43500): xfrm-ESP y RxRPC, los page-cache write primitives detrás del nuevo LPE de mayo
lu1tr0n
lu1tr0n

Posted on • Originally published at elsolitario.org

Dirty Frag (CVE-2026-43284 y CVE-2026-43500): xfrm-ESP y RxRPC, los page-cache write primitives detrás del nuevo LPE de mayo

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.

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 */
    }
}
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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
│└──────────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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 */
Enter fullscreen mode Exit fullscreen mode

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 */
}
Enter fullscreen mode Exit fullscreen mode

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 */
}
Enter fullscreen mode Exit fullscreen mode

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:

  • 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—.
  • 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.
  • 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
Enter fullscreen mode Exit fullscreen mode

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)) {
Enter fullscreen mode Exit fullscreen mode

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

if (skb_cloned(skb) || skb->data_len) {
    /* slow path */
}
Enter fullscreen mode Exit fullscreen mode

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 /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
Enter fullscreen mode Exit fullscreen mode

⚠️ 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
Enter fullscreen mode Exit fullscreen mode

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 /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: /
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Windows con WSL2:

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

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

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.

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.

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).

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.

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

Top comments (0)