
Proof-of-Concept-Exploit für CVE-2026-41651, eine lokale Privilegieneskalation durch TOCTOU in PackageKit, mit technischer Analyse, Erkennungslogik und Anleitung zur Behebung.
Klassifizierung: Purple-Team-Bewertungsartefakt
Nur für autorisierte Nutzung. Dieses Dokument und das begleitende Testskript sind ausschließlich für interne Sicherheitsvalidierung auf Systemen bestimmt, für die eine schriftliche Genehmigung vorliegt.

| Feld | Wert |
|---|---|
| CVE-ID | CVE-2026-41651 |
| CWE | CWE-367 — Time-of-check Time-of-use (TOCTOU) Race Condition |
| Komponente | PackageKit (packagekitd, D-Bus-Dienst) |
| Betroffen | PackageKit ≤ 1.3.4 |
| Behoben in | PackageKit 1.3.5 |
| Auswirkung | Lokale Rechteausweitung → root |
| Angriffsvektor | Lokal / D-Bus (Sitzung ohne Privilegien) |
| Offengelegt | 2026-04-22 (Deutsche Telekom Red Team) |
| Advisory | GHSA-f55j-vvr9-69xv |
| Fix-Commit | 76cfb675fb31acc3ad5595d4380bfff56d2a8697 |
PackageKit ist eine D-Bus-Abstraktionsschicht für die Systempaketverwaltung, die standardmäßig auf GNOME-basierten Desktops unter Debian, Ubuntu, Fedora, RHEL, SUSE und Arch Linux vorhanden ist. Da es privilegierte Paketoperationen im Namen von Benutzern ohne Privilegien vermittelt, hat ein Fehler in seinem Autorisierungsablauf systemweite Root-Auswirkungen.
pk-transaction.c (vor 1.3.5) erzwang keine Zustandsprüfung bei erneuter Aufrufung von Aktionsmethoden. Ein D-Bus-Client konnte InstallFiles (oder andere Aktionsmethoden) mehrfach auf demselben Transaktionsobjekt aufrufen, nachdem es bereits aus PK_TRANSACTION_STATE_NEW übergegangen war.
Angreifer (ohne Privilegien)
│
├─① CreateTransaction() → PackageKit gibt Objektpfad der Transaktion zurück (tid)
│
├─② InstallFiles(tid, FLAG_SIMULATE=4, [dummy.pkg])
│ PackageKit stellt eine polkit-Autorisierungsprüfung für dummy.pkg in die Warteschlange.
│ Es findet noch keine Installation statt — SIMULATE bedeutet nur Trockenlauf.
│
├─③ InstallFiles(tid, FLAG_NONE=0, [payload.pkg]) ← TOCTOU-Fenster
│ Ruft dasselbe tid erneut auf, bevor die Autorisierung aufgelöst wird.
│ Verwundbare Versionen überschreiben die in der Warteschlange befindlichen Parameter mit payload.pkg.
│
└─④ polkit gewährt Autorisierung (Benutzer genehmigt oder automatisch autorisiert)
packagekitd installiert payload.pkg als root.
payload postinst/post-Skript: install -m 4755 /bin/bash /tmp/.suid_bash
Angreifer führt /tmp/.suid_bash -p aus → Root-Shell.
Die Schritte ② und ③ werden als nicht blockierende asynchrone D-Bus-Aufrufe auf derselben Verbindung gesendet und in einem einzigen Schreibvorgang geleert. Die beiden Nachrichten treffen bei packagekitd ein, bevor es ② verarbeiten und die Zustandsmaschine vorantreiben kann, wodurch das TOCTOU-Fenster offen bleibt. Der Fix in 1.3.5 fügt eine explizite Zustandsprüfung hinzu, die bei jeder erneuten Aufrufung nach PK_TRANSACTION_STATE_NEW PK_TRANSACTION_ERROR_INVALID_STATE zurückgibt.
Datei: cve-2026-41651-purpleteam.py
Sprache: Python 3
Abhängigkeiten: python3-gi (GObject-Introspection / GLib-Gio-Bindungen)
Demonstriert die Ausnutzbarkeit von CVE-2026-41651 auf einem vorbereiteten Testsystem für folgende Zwecke:
| Phase | Aktion |
|---|---|
| Einrichtung | Untersucht /proc/mounts, um ein SUID-/exec-fähiges Ablageverzeichnis auszuwählen, setzt umask(022), wendet explizites chmod auf alle Build-Artefakte an und erstellt dann ein Dummy- und ein Payload-Paket in /tmp |
| Exploit | Öffnet eine System-D-Bus-Verbindung, erstellt eine PackageKit-Transaktion, löst das Zwei-Aufruf-Rennen aus |
| Payload | Das Post-Installationsskript des Pakets kopiert /bin/bash nach <drop_dir>/.suid_bash mit Modus 04755, Besitzer root. Das Ablageverzeichnis wird zur Laufzeit aufgelöst (siehe Unterstützung gehärteter Umgebungen) |
| Ausweitung | Fragt nach der SUID-Binärdatei (90-s-Timeout) und führt dann execl mit -p für eine Root-Shell aus |
| Bereinigung | Entfernt die temporären .deb/.rpm-Dateien beim Beenden (Erfolg oder Fehlschlag) |
Standardmäßig gehärtete Systeme können den Exploit an zwei unabhängigen Punkten blockieren. Das Skript behandelt beide automatisch.
027 / 077)Eine prozessvererbte umask von 027 oder 077 führt dazu, dass mkdir() Verzeichnisse mit 750 oder 700 erzeugt. Sowohl dpkg-deb als auch rpmbuild müssen den gesamten Build-Baum durchlaufen — wenn ein Verzeichnis nicht lesbar ist, schlägt der Build still fehl.
Angewendeter Fix: os.umask(0o022) wird beim Start aufgerufen, bevor eine Datei oder ein Verzeichnis erstellt wird. Zusätzlich erhält jedes Verzeichnis und jede Datei im Build-Baum unmittelbar nach der Erstellung ein explizites chmod (0o755 für Verzeichnisse und Skripte, 0o644 für Datendateien), sodass die korrekten Berechtigungen unabhängig von der geerbten umask garantiert sind.
nosuid / noexec-Mount-Flags auf /tmp| Flag | Auswirkung auf den Exploit |
|---|---|
nosuid | Der Kernel entfernt still das SUID-Bit von jeder Datei, die auf diesem Dateisystem gespeichert ist — die kopierte bash wird nie root |
noexec | Die SUID-Binärdatei kann überhaupt nicht ausgeführt werden |