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 — Prova de conceito em C para a CVE-2026-8933, uma escalada de privilégios local no snap-confine que utiliza congelamento de cgroup, corridas de symlink e injeção de regras udev para executar comandos como root. | Kitploit
Ferramentas/GitHubGitHub/yifengchen-cc/cve-2026-8933
Escalada de PrivilégiosSegurança de ContêineresAnálise de VulnerabilidadesExploração
GitHubyifengchen-cc/cve-2026-8933

CVE-2026-8933

Prova de conceito em C para a CVE-2026-8933, uma escalada de privilégios local no snap-confine que utiliza congelamento de cgroup, corridas de symlink e injeção de regras udev para executar comandos como root.

Ver Repositório
há 14 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 — snap-confine set-capabilities 本地提权 PoC

Reproduza o comunicado da Qualys "Local Privilege Escalation in set-capabilities versions of snap-confine" (https://cdn2.qualys.com/advisory/2026/07/21/snap-confine-set-capabilities.txt).

Testado na máquina local (Ubuntu 25.10 / snapd 2.73+ubuntu25.10.1 / kernel 6.17): partindo do uid 1000, finalmente o systemd-udevd executa o comando como root, /tmp/pwned obtém uid=0(root) gid=0(root) groups=0(root), consistente com o efeito demonstrado no final do aviso.

O registro das dificuldades encontradas durante a reprodução, e por que a primeira avaliação julgou erroneamente "não explorável", veja NOTES.md.

Arquivos

ArquivoDescrição
poc.cPoC completo (arquivo único)
MakefileBuild (vincula o libfuse3.so.3.17.4 já instalado no sistema)
include/Cabeçalhos do libfuse3 3.17.4 (correspondentes à biblioteca de runtime do sistema)
NOTES.mdRegistro das dificuldades + retrospectiva da metodologia de análise de alcançabilidade

Princípio da vulnerabilidade

cmd/snap-confine/mount-support.c (snapd 2.73):

sc_bootstrap_mount_namespace()      // 第 475 行起
  479:  mkdtemp("/tmp/snap.rootfs_XXXXXX")          <- 目录先归调用者所有
  491:  sc_do_mount(scratch, scratch, NULL, MS_BIND)
  498:  sc_do_mount("none", scratch, NULL, MS_UNBINDABLE)
  503:  sc_do_mount("none", scratch, "tmpfs", ...)
  504:  sc_replicate_base_rootfs(scratch, rootfs_dir, mounts)

sc_replicate_base_rootfs()
  330:  chown(scratch, 0, 0)
  418:  fd = open(full_path, O_CREAT | O_TRUNC, 0644)   <- 缺少 O_NOFOLLOW
  422:  fchown(fd, 0, 0)

Os números de linha foram extraídos do código-fonte do snapd 2.73 desta máquina (cmd/snap-confine/mount-support.c). O aviso da Qualys cita sua própria cópia do arquivo, cujos números de linha correspondentes são 511 / 523 / 530 / 535 / 536 / 362 / 450 / 454 — as instruções correspondem uma a uma, apenas os números de linha diferem.

O /usr/lib/snapd/snap-confine desta máquina é mode=755 + file capabilities (não setuid-root), portanto é executado com o euid do atacante, mas detém capacidades quase de root: os diretórios e ficheiros que cria pertencem ao atacante durante um breve período, e o open() na linha 418 segue links simbólicos.

A desmontagem confirma: nesta máquina, os flags de open@plt são 0x240 (O_CREAT|O_TRUNC, sem O_NOFOLLOW); no mesmo ponto da versão 2.77.1 corrigida, são 0x20240.

As seis etapas do PoC

  1. Colocar o snap-confine no próprio cgroup: systemd-run --user --scope --unit=snap.<snap>.<app>. Esse scope pertence ao usuário atual, cgroup.freeze é gravável, portanto é possível liberar o snap-confine chamada de sistema por chamada de sistema.
  2. Congelar no momento certo: com SNAPD_DEBUG=1, o snap-confine imprime associated snap application process ... with device cgroup. Essa linha aparece após o attach do programa BPF do cgroup de dispositivos e antes de mkdtemp(). Não se pode congelar antes: o verificador BPF retorna EAGAIN quando há um freeze trap, e o snap-confine simplesmente encerra. O stderr está conectado a um pty (não a um pipe): caso contrário, o stdio seria armazenado em buffer de bloco e o marcador frequentemente só seria descarregado após mkdtemp() e o bind mount. Além disso, o scope é iniciado com CPUQuota=1%: do marcador até mkdtemp() há apenas algumas centenas de microssegundos de tempo de CPU, da mesma ordem de grandeza da latência de despertar do processo capturador; a limitação de taxa estende essa janela em tempo real para a ordem de milissegundos, e, após confirmar o congelamento, cpu.max é imediatamente restaurado para 100%.
  3. Substituir o diretório scratch por um symlink apontando para o nosso próprio diretório: mount(2) segue os symlinks no caminho de destino, então o bind/unbindable/tmpfs do snap-confine cai todo em <scratch>.dA, enquanto o laço de cópia continua usando a string do diretório scratch.
  4. Após o tmpfs ser montado (ns_mount_count(sc, .dA) >= 2), redirecionar o symlink para <scratch>.dB, e colocar em dB symlinks com os mesmos nomes dos arquivos regulares de nível superior do rootfs base, apontando para /run/udev/rules.d/97-cve-2026-8933-<pid>-<rand>.rules. Nesse momento, a resolução de caminho do laço de cópia recai em dB — um diretório comum que controlamos completamente. O tmpfs fica em dA e deixa de nos atrapalhar. Atenção: quando há apenas 1 montagem em .dA, trata-se de um bind mount (o /tmp em si é tmpfs; após o bind, o fstype continua sendo tmpfs); é preciso esperar a segunda montagem (o tmpfs real) aparecer para redirecionar, caso contrário o mount --make-unbindable do snap-confine falhará com EINVAL porque o caminho não é mais a raiz de uma montagem.
  5. Vencer a janela entre open()/fchown(): o laço de cópia executa, para o primeiro arquivo regular, open(O_CREAT|O_TRUNC) (seguindo o symlink, criando o arquivo como root em /run/udev/rules.d), e em seguida fchown(fd,0,0). O arquivo ainda nos pertence nesse instante. O PoC usa simultaneamente dois meios:
    • Caminho principal: continuar usando o freezer para liberar aproximadamente uma chamada de sistema por vez; assim que stat() vê o arquivo e o uid ainda é o nosso, executar imediatamente chmod 0666 + escrever a regra udev (nesse momento o snap-confine está congelado e a janela é "escancarada");
    • Rede de segurança: vários processos spinner disputam a mesma janela em um laço ativo de chmod(). Quando o spinner vence, o arquivo pertence a root, mas o modo é 0666 — os bits de modo permanecem após fchown(0,0), então o caminho principal também consegue terminá-lo (o código verifica "é possível escrever", não "é o proprietário").
  6. Acionar o udev: o perfil AppArmor do snap-confine permite /run/udev/** rw. Montar/desmontar um sistema de arquivos FUSE faz o kernel emitir um uevent add para o subsistema bdi, e o systemd-udevd executa imediatamente o PROGRAM= da regra como root.

Uso

make
./poc --diagnose            # 只读自检,不改动任何系统状态
./poc                       #  exploit,默认最多 5 次尝试
./poc --attempts 8          # 增加尝试次数
./poc --file default256.png # 只用 base rootfs 里的这一个普通文件
sudo ./poc --cleanup        # 清理(仅在异常中断留下残留时需要)

Parâmetros:

ParâmetroDescrição
--snap NAMEQual rootfs de snap usar (padrão firefox, também pode usar a variável de ambiente CVE8933_SNAP)
--app NAMEO app desse snap (por padrão, o primeiro sob apps: em meta/snap.yaml)
--file NAMEUsar apenas este arquivo comum do rootfs base; se não houver correspondência, encerra com erro
--attempts NNúmero de tentativas (padrão 5)
--step US / --step2 USTempo de CPU por fatia em cada uma das duas fases (microssegundos), para depuração
--keepManter os diretórios <scratch>.dA / .dB e os links simbólicos (para depuração)
--diagnoseAutoverificação somente leitura
--cleanupLimpar resíduos históricos (requer root)

Os logs são gravados em /tmp/cve8933.log, e a saída de depuração do snap-confine é gravada em /tmp/cve8933-debug.txt.

CVE8933_PAYLOAD_CMD='<comando shell>' pode substituir o corpo do payload (para demonstrar a execução de outros comandos root); nesse caso, a limpeza automática não ocorre; o comando personalizado ainda precisa gravar em /tmp/pwned, caso contrário o PoC considerará que desta vez não houve sucesso.

Resultados dos testes reais

$ ./poc
[+] WIN: uid=0(root) gid=0(root) groups=0(root)
[+] exploit succeeded, evidence in /tmp/pwned

/tmp/cve8933.log 中对应的一次成功过程(2026-10-23,改动后复测):

Baixar ferramenta