Les nœuds /dev/mem (mémoire physique), /dev/kmem (mémoire virtuelle du noyau) et /dev/port (ports d'E/S) sont des fenêtres sur le noyau hôte en direct. Ils ne sont pas cloisonnés par espace de noms, de sorte qu'une écriture via /dev/mem depuis l'intérieur d'un conteneur modifie la mémoire du noyau de l'hôte. Lorsqu'un conteneur expose ces nœuds, généralement sous --privileged ou via un --device=/dev/mem explicite, un attaquant qui y a accès peut patcher des structures de données du noyau pour élever ses privilèges ou désactiver des protections.
Confirmez les nœuds et si l'accès à la RAM est autorisé :
ls -l /dev/mem /dev/kmem /dev/port 2>/dev/null
grep -E 'STRICT_DEVMEM|IO_STRICT_DEVMEM' /boot/config-$(uname -r) 2>/dev/null
# STRICT_DEVMEM=y confines /dev/mem to device ranges and blocks general RAM
Voie : écraser les identifiants d'un processus#
L'objectif classique est de trouver la structure cred d'un processus shell et de mettre à zéro ses champs UID/GID, le transformant en root, ou d'effacer un drapeau d'application d'un LSM. L'attaquant a besoin d'une adresse noyau (depuis /proc/kallsyms, un décalage connu pour la version du noyau, ou une fuite) et du mappage physique pour /dev/mem.
int fd = open("/dev/mem", O_RDWR);
off_t phys = virt_to_phys(target_kvaddr); // via known offset / leak
void *m = mmap(NULL, 0x1000, PROT_READ|PROT_WRITE, MAP_SHARED, fd, phys & ~0xfff);
uint32_t *cred = (uint32_t *)((char*)m + (phys & 0xfff));
cred[0] = cred[1] = cred[2] = cred[3] = 0; // uid,gid,suid,sgid -> 0
Lire d'abord avec le même mappage vous permet de confirmer la signature de la structure (par exemple l'UID attendu du processus cible) avant d'écrire, ce qui évite de corrompre la mauvaise page.
Voie : ports d'E/S#
/dev/port et la surface iopl/ioperm atteignent directement les contrôleurs de périphériques. Sur un matériel adapté, cela pilote un périphérique capable de DMA pour lire ou écrire une mémoire physique arbitraire, obtenant la même écriture du noyau sans accès à la RAM via /dev/mem.
Notes d'exploitation#
CONFIG_STRICT_DEVMEM(par défaut sur les distributions modernes) bloque l'accès général à la RAM via/dev/mem, ne laissant que les plages de périphériques ; lorsqu'il est positionné, préférez CAP_SYS_MODULE ou un montage de disque./dev/kmemest retiré de la plupart des noyaux actuels.- Cette voie dépend de décalages de noyau exacts pour la version précise en cours d'exécution ; des décalages incorrects corrompent la mémoire et font paniquer l'hôte, alors identifiez d'abord précisément
uname -ret le noyau de la distribution. - L'accès à ces nœuds implique aussi la voie de capacité d'E/S brute ; voir CAP_SYS_RAWIO.