
# Laboratório Docker estilo CTF para CVE-2026-41651 (Pack2TheRoot): escalonamento local de privilégios via PackageKit permissive-polkit
Um laboratório Dockerizado, estilo CTF, de escalonamento local de privilégios, construído em torno do
advisory Pack2TheRoot (CVE-2026-41651), uma falha de 12 anos no
daemon PackageKit divulgada
pela Red Team da Deutsche Telekom em 22 de abril de 2026.
O laboratório inclui três contêineres: um desafio CTF com polkit permissivo, um alvo de comparação endurecido e uma reprodução completa do exploit TOCTOU que compila o PackageKit vulnerável a partir do código-fonte e executa o exploit real da causa raiz do CVE-2026-41651.
| Contêiner | Porta | Função | Resultado do exploit |
|---|
pack2theroot-vuln | tcp/2222 (ssh) | PackageKit ≤ 1.3.4 + regra polkit permissiva | Root via RPM malicioso |
pack2theroot-patched | tcp/2223 (ssh) | O mesmo, mas com polkit endurecido | O exploit falha |
pack2theroot-exploit | — | PackageKit 1.3.4 vulnerável compilado a partir do código-fonte | Root via corrida TOCTOU no D-Bus |
Além disso:
docs/CHALLENGE.md)docs/HINTS.md)docs/SOLUTION.md)docs/diagrams/)| Campo | Valor |
|---|---|
| CVE | CVE-2026-41651 |
| Nome | Pack2TheRoot |
| Classe | Escalonamento Local de Privilégios (TOCTOU / CWE-367) |
| Componente | daemon PackageKit (pk-transaction.c) |
| Faixa vulnerável | >= 1.0.2 e <= 1.3.4 (12 anos de versões) |
| Corrigido em | PackageKit 1.3.5 (commit 76cfb675, lançado em 2026-04-22) |
| CVSS 3.1 | 8.8 (ALTA) — AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H |
| Pré-condições | Shell local sem privilégios em um host executando PackageKit |
| Descobridor | Deutsche Telekom Security GmbH — Red Team |
pk-transaction.c| Bug | Local | Efeito |
|---|---|---|
| BUG 1 | InstallFiles() (~linha 4036) | Sobrescreve cached_transaction_flags e cached_full_paths incondicionalmente — sem guarda de estado |
| BUG 2 | pk_transaction_set_state() (~linhas 876–881) | Descarta silenciosamente transições de estado regressivas em vez de gerar erro — flags já envenenadas |
| BUG 3 | pk_transaction_run() (~linhas 2273–2277) | Lê cached_transaction_flags no momento do despacho, não no momento da autorização |
| Bypass | flag SIMULATE (~linhas 2893–2900) | PK_TRANSACTION_FLAG_SIMULATE (0x4) ignora o polkit completamente |
O exploit envia duas chamadas assíncronas InstallFiles() via D-Bus na mesma
transação: primeiro com SIMULATE (ignora o polkit, enfileira um callback idle do GLib),
e imediatamente depois com NONE + o pacote malicioso (sobrescreve
as flags/caminhos em cache antes do idle disparar). A ordenação por prioridade do GLib
garante que ambas as mensagens D-Bus sejam despachadas antes do callback idle — tornando
isso determinístico, não uma corrida de tempo.
IOC conhecido (do advisory):
journalctl --no-pager -u packagekit | grep -iE 'emitted_finished|pk_transaction_finished_emit|pk-transaction\.c:514'
git clone https://github.com/dinosn/pack2theroot-lab.git
cd pack2theroot-lab
docker compose build
docker compose up -d
ssh labuser@localhost -p 2222 # senha: labuser
# depois trabalhe em docs/CHALLENGE.md
A flag está em /root/flag.txt (modo 0400 root:root). Formato:
PACK2THEROOT{...}
# Compilar e executar — o modo automático executa o exploit imediatamente:
docker compose run --rm exploit
# Ou modo manual:
docker compose run --rm --entrypoint /entrypoint.sh exploit
# Depois, dentro do contêiner:
su - victim -c /exploit/cve-2026-41651
O exploit compila dois pacotes .deb em C (sem necessidade de ferramentas externas),
envia a corrida D-Bus de duas chamadas e cria um bash SUID em
/tmp/.suid_bash. Consulte docs/SOLUTION.md para a
solução técnica completa.
Encerrar:
docker compose down -v
pack2theroot-lab/
├── README.md
├── docker-compose.yml
├── docs/
│ ├── CHALLENGE.md # briefing do jogador
│ ├── HINTS.md # dicas progressivas (ambos os caminhos)
│ ├── SOLUTION.md # solução completa + flag
│ ├── references.md # fontes primárias e secundárias
│ ├── threat-model.md # premissas atacante/defensor
│ └── diagrams/ # diagramas SVG do fluxo do exploit
│ ├── 01-docker-build.svg
│ ├── 02-container-startup.svg
│ ├── 03-exploit-execution.svg
│ ├── 04-dbus-race-sequence.svg
│ ├── 05-attack-overview.svg
│ └── 06-auto-mode-full-run.svg
├── exploit/
│ ├── Dockerfile # compila o PackageKit 1.3.4 vulnerável a partir do código-fonte
│ ├── entrypoint.sh # inicia dbus + polkitd + packagekitd
│ ├── Makefile
│ └── src/
│ └── cve-2026-41651.c # o exploit TOCTOU (PoC público)
├── vulnerable/
│ ├── Dockerfile
│ ├── entrypoint.sh
│ └── policy/
│ └── 10-pack2theroot-lab-misconfig.rules # desafio CTF
├── patched/
│ ├── Dockerfile
│ ├── entrypoint.sh
│ ├── local/ # coloque um RPM de backport 1.3.5 aqui (opcional)
│ └── policy/
│ └── 10-pack2theroot-lab-hardened.rules # a correção
└── scripts/
├── exploit-check.sh # verifica versão, polkit, D-Bus, IOCs
├── check-version.sh # veredito VULNERÁVEL vs CORRIGIDO
├── check-preconditions.sh # sanidade pkcon / polkit / D-Bus
├── monitor-ioc.sh # monitora o journal em busca do IOC do advisory
├── compare-env.sh # compara os dois contêineres
└── apply-polkit-mitigation.sh # endurecimento provisório para hosts sem correção
O diretório docs/diagrams/ contém diagramas SVG
mostrando o fluxo do exploit. Abra-os em qualquer navegador:
| Diagrama | Descrição |
|---|---|
01-docker-build.svg | Build Docker em dois estágios — compilando o PackageKit vulnerável |
02-container-startup.svg | Inicialização do contêiner — início do dbus, polkitd, packagekitd |
03-exploit-execution.svg | Saída do exploit passo a passo com fases anotadas |
04-dbus-race-sequence.svg | Diagrama de sequência D-Bus — como BUG 1/2/3 se encadeiam com a prioridade do GLib |
05-attack-overview.svg | Fluxo de ataque de alto nível: atacante vs sistema com linha do tempo |
06-auto-mode-full-run.svg | Terminal completo do modo --auto — do início do contêiner ao shell root |
Consulte docs/CHALLENGE.md. Resumo:
labuser (senha labuser).rpm-build, rpmdevtools estão instalados).pkcon install-local --allow-untrusted.%post é executado como root. Leia /root/flag.txt.Travou? docs/HINTS.md tem dicas cada vez mais
explícitas. Só abra
docs/SOLUTION.md depois de ter resolvido ou
realmente precisar do write-up.
Dentro de qualquer contêiner, como qualquer usuário:
/opt/lab/check-version.sh # veredito VULNERÁVEL ou CORRIGIDO
/opt/lab/check-preconditions.sh # autoverificação de exposição
/opt/lab/exploit-check.sh # verificação de versão + polkit + D-Bus + IOC
/opt/lab/monitor-ioc.sh # monitora o journal em busca do IOC
A partir do host, lado a lado:
./scripts/compare-env.sh
Aplique a mitigação provisória do polkit a um contêiner vulnerável:
docker exec pack2theroot-vuln /opt/lab/apply-polkit-mitigation.sh
# Depois tente o exploit novamente — agora deve falhar.
A imagem patched trata o status da versão do PackageKit com honestidade:
/etc/pack2theroot-banner) informando
se a versão instalada é a correção real ou um placeholder da distribuição.Para compilar uma imagem corrigida com versão completa quando sua distribuição
publicar o backport, coloque o(s) RPM(s) em patched/local/ e recompile:
docker compose build --build-arg USE_LOCAL_RPM=1 patched
--privileged para executar a pilha completa
dbus/polkitd/packagekitd. Execute-o apenas em ambientes isolados.labuser) é intencionalmente fraca. Nunca a reutilize.Fontes primárias:
CVE-2026-41651:
https://nvd.nist.gov/vuln/detail/CVE-2026-4165176cfb675:
https://github.com/PackageKit/PackageKit/commit/76cfb675fb31acc3ad5595d4380bfff56d2a8697Consulte docs/references.md para cobertura secundária
e rastreadores de distribuição.
MIT — consulte LICENSE.