
# CTF-Docker-Lab für CVE-2026-41651 (Pack2TheRoot): Lokale Privilegienerweiterung durch permissives Polkit in PackageKit
Ein Dockerisiertes, CTF-artiges Labor für lokale Privilegieneskalation, das um die
Pack2TheRoot-Advisory (CVE-2026-41651) aufgebaut ist, einen 12 Jahre alten Fehler im
PackageKit-Daemon, der vom
Red Team der Deutschen Telekom am 22. April 2026 offengelegt wurde.
Das Labor umfasst drei Container: eine permissive-polkit CTF-Herausforderung, ein gehärtetes Vergleichsziel und eine vollständige TOCTOU-Exploit-Reproduktion, die das verwundbare PackageKit aus dem Quellcode baut und den tatsächlichen CVE-2026-41651-Exploit der Grundursache ausführt.
| Container | Port | Rolle | Exploit-Ergebnis |
|---|
pack2theroot-vuln | tcp/2222 (ssh) | PackageKit ≤ 1.3.4 + permissive polkit-Regel | Root über manipuliertes RPM |
pack2theroot-patched | tcp/2223 (ssh) | Gleich, aber polkit gehärtet | Exploit schlägt fehl |
pack2theroot-exploit | — | Verwundbares PackageKit 1.3.4 aus dem Quellcode gebaut | Root über TOCTOU-D-Bus-Race |
Zusätzlich:
docs/CHALLENGE.md)docs/HINTS.md)docs/SOLUTION.md)docs/diagrams/)| Feld | Wert |
|---|---|
| CVE | CVE-2026-41651 |
| Name | Pack2TheRoot |
| Klasse | Lokale Privilegieneskalation (TOCTOU / CWE-367) |
| Komponente | PackageKit-Daemon (pk-transaction.c) |
| Verwundbarer Bereich | >= 1.0.2 und <= 1.3.4 (12 Jahre Releases) |
| Behoben in | PackageKit 1.3.5 (Commit 76cfb675, veröffentlicht 2026-04-22) |
| CVSS 3.1 | 8.8 (HOCH) — AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H |
| Voraussetzungen | Lokale unprivilegierte Shell auf einem Host mit PackageKit |
| Entdecker | Deutsche Telekom Security GmbH — Red Team |
pk-transaction.c| Fehler | Ort | Wirkung |
|---|---|---|
| FEHLER 1 | InstallFiles() (~Zeile 4036) | Überschreibt cached_transaction_flags und cached_full_paths bedingungslos — keine Zustandsprüfung |
| FEHLER 2 | pk_transaction_set_state() (~Zeilen 876–881) | Verwirft rückwärtsgerichtete Zustandsübergänge stillschweigend statt einen Fehler zu melden — Flags bereits vergiftet |
| FEHLER 3 | pk_transaction_run() (~Zeilen 2273–2277) | Liest cached_transaction_flags zur Dispatch-Zeit, nicht zur Autorisierungszeit |
| Umgehung | SIMULATE-Flag (~Zeilen 2893–2900) | PK_TRANSACTION_FLAG_SIMULATE (0x4) umgeht polkit vollständig |
Der Exploit sendet zwei asynchrone D-Bus-InstallFiles()-Aufrufe auf derselben
Transaktion: zuerst mit SIMULATE (umgeht polkit, stellt einen GLib-Idle-Callback
in die Warteschlange), dann sofort mit NONE + dem bösartigen Paket (überschreibt
die gecachten Flags/Pfade, bevor der Idle feuert). Die Prioritätsreihenfolge von GLib
garantiert, dass beide D-Bus-Nachrichten vor dem Idle-Callback zugestellt werden —
das macht dies deterministisch, kein Timing-Race.
Bekannter IOC (aus der 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 # Passwort: labuser
# dann docs/CHALLENGE.md durcharbeiten
Die Flag befindet sich unter /root/flag.txt (Modus 0400 root:root). Format:
PACK2THEROOT{...}
# Bauen und ausführen — Auto-Modus führt den Exploit sofort aus:
docker compose run --rm exploit
# Oder manueller Modus:
docker compose run --rm --entrypoint /entrypoint.sh exploit
# Dann innerhalb des Containers:
su - victim -c /exploit/cve-2026-41651
Der Exploit baut zwei .deb-Pakete in C (keine externen Werkzeuge nötig),
sendet das Zwei-Aufruf-D-Bus-Race und erstellt eine SUID-bash unter
/tmp/.suid_bash. Siehe docs/SOLUTION.md für die
vollständige technische Komplettlösung.
Abbau:
docker compose down -v
pack2theroot-lab/
├── README.md
├── docker-compose.yml
├── docs/
│ ├── CHALLENGE.md # Spielerbeschreibung
│ ├── HINTS.md # progressive Hinweise (beide Pfade)
│ ├── SOLUTION.md # vollständige Komplettlösung + Flag
│ ├── references.md # primäre und sekundäre Quellen
│ ├── threat-model.md # Angreifer/Verteidiger-Annahmen
│ └── diagrams/ # SVG-Diagramme des Exploit-Ablaufs
│ ├── 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 # baut verwundbares PackageKit 1.3.4 aus dem Quellcode
│ ├── entrypoint.sh # startet dbus + polkitd + packagekitd
│ ├── Makefile
│ └── src/
│ └── cve-2026-41651.c # der TOCTOU-Exploit (öffentlicher PoC)
├── vulnerable/
│ ├── Dockerfile
│ ├── entrypoint.sh
│ └── policy/
│ └── 10-pack2theroot-lab-misconfig.rules # CTF-Herausforderung
├── patched/
│ ├── Dockerfile
│ ├── entrypoint.sh
│ ├── local/ # hier ein 1.3.5-Backport-RPM ablegen (optional)
│ └── policy/
│ └── 10-pack2theroot-lab-hardened.rules # die Behebung
└── scripts/
├── exploit-check.sh # prüft Version, polkit, D-Bus, IOCs
├── check-version.sh # VERWUNDBAR vs. GEPATCHT-Urteil
├── check-preconditions.sh # pkcon / polkit / D-Bus-Sanity-Check
├── monitor-ioc.sh # Journal für den Advisory-IOC überwachen
├── compare-env.sh # beide Container vergleichen
└── apply-polkit-mitigation.sh # interimistische Härtung für ungepatchte Hosts
Das Verzeichnis docs/diagrams/ enthält SVG-Diagramme,
die den Exploit-Ablauf zeigen. Öffnen Sie sie in einem beliebigen Browser:
| Diagramm | Beschreibung |
|---|---|
01-docker-build.svg | Zwei-Stufen-Docker-Build — Kompilieren des verwundbaren PackageKit |
02-container-startup.svg | Container-Start — dbus-, polkitd-, packagekitd-Start |
03-exploit-execution.svg | Schritt-für-Schritt-Exploit-Ausgabe mit annotierten Phasen |
04-dbus-race-sequence.svg | D-Bus-Sequenzdiagramm — wie FEHLER 1/2/3 mit GLib-Priorität verkettet sind |
05-attack-overview.svg | Hochrangiger Angriffsablauf: Angreifer vs. System mit Zeitachse |
06-auto-mode-full-run.svg | Vollständiges --auto-Modus-Terminal — Container-Start bis Root-Shell |
Siehe docs/CHALLENGE.md. Kurzfassung:
labuser anmelden (Passwort labuser).rpm-build, rpmdevtools sind installiert).pkcon install-local --allow-untrusted installieren.%post-Skriptlet läuft als root. /root/flag.txt lesen.Festgefahren? docs/HINTS.md enthält zunehmend
explizitere Hinweise. Öffnen Sie
docs/SOLUTION.md erst, nachdem Sie es gelöst haben oder
die Dokumentation wirklich benötigen.
In beiden Containern, als beliebiger Benutzer:
/opt/lab/check-version.sh # VERWUNDBAR- oder GEPATCHT-Urteil
/opt/lab/check-preconditions.sh # Selbstprüfung der Exposition
/opt/lab/exploit-check.sh # Versions- + polkit- + D-Bus- + IOC-Prüfung
/opt/lab/monitor-ioc.sh # Journal auf den IOC überwachen
Vom Host aus, nebeneinander:
./scripts/compare-env.sh
Die interimistische polkit-Mitigation auf einen verwundbaren Container anwenden:
docker exec pack2theroot-vuln /opt/lab/apply-polkit-mitigation.sh
# Dann den Exploit erneut versuchen — sollte jetzt fehlschlagen.
Das patched-Image behandelt den PackageKit-Versionsstatus ehrlich:
/etc/pack2theroot-banner), das angibt,
ob die installierte Version der echte Patch oder ein Distributions-Platzhalter ist.Um ein versionsvollständiges gepatchtes Image zu bauen, sobald Ihre Distribution
den Backport veröffentlicht, legen Sie die RPM(s) in patched/local/ ab und bauen neu:
docker compose build --build-arg USE_LOCAL_RPM=1 patched
--privileged, um den vollständigen
dbus/polkitd/packagekitd-Stack auszuführen. Führen Sie ihn nur in isolierten Umgebungen aus.labuser) ist absichtlich schwach. Verwenden Sie es niemals wieder.Primärquellen:
CVE-2026-41651:
https://nvd.nist.gov/vuln/detail/CVE-2026-4165176cfb675:
https://github.com/PackageKit/PackageKit/commit/76cfb675fb31acc3ad5595d4380bfff56d2a8697Siehe docs/references.md für sekundäre Berichterstattung
und Distributions-Tracker.
MIT — siehe LICENSE.