
Lokale Rechteausweitung durch TOCTOU-Race Condition in PackageKits.
CVSS 3.x : 7.8 HIGH
CWE : CWE-367 (Time-of-Check Time-of-Use)
Fix : PackageKit 1.3.5+
Affects : PackageKit 1.0.2 – 1.3.4
Lokale Privilegieneskalation durch eine TOCTOU-Race-Condition im D-Bus-Transaktionshandler von PackageKit.
Jeder unprivilegierte lokale Benutzer kann beliebige Pakete als root installieren — es ist keine Authentifizierung erforderlich, nur eine lokale Sitzung.
Nur für Lab / autorisierte Tests (HTB, CTF, Engagement mit schriftlich festgelegtem Umfang).
python3 exploit.py
Das war's. Erstellt /tmp/.suid_bash und wechselt dann per exec in eine Root-Shell.
Benutzerdefinierter SUID-Pfad oder Timeout:
SUID_BIN=/dev/shm/.sh TIMEOUT=90 python3 exploit.py
apt install python3-gi dpkg-dev
Der Exploit baut zur Laufzeit zwei .deb-Pakete — es wird kein Compiler benötigt.
Drei Bugs in src/pk-transaction.c greifen ineinander:
InstallFiles() überschreibt cached_transaction_flags und cached_full_paths ohne Zustandsprüfung. Ein zweiter D-Bus-Aufruf auf derselben Transaktion ersetzt sie blind — sogar während die Transaktion bereits läuft.
pk_transaction_set_state() lehnt unzulässige Rückwärtsübergänge (RUNNING→READY usw.) ab, ohne die von Bug 1 überschriebenen Flags zurückzusetzen. Die beschädigten Flags bleiben bestehen.
pk_transaction_run() liest cached_transaction_flags zum Dispatch-Zeitpunkt (GLib idle), nicht zum Autorisierungszeitpunkt. Das Backend sieht die Flags des Angreifers.
Das Setzen von PK_TRANSACTION_FLAG_SIMULATE (0x4) überspringt die polkit-Autorisierungsprüfung vollständig. Aufruf 1 wird ohne Benutzerinteraktion autorisiert.
Attacker packagekitd
│ │
│ CreateTransaction() │ state = NEW
│─────────────────────────────────►│
│ │
│ InstallFiles(SIMULATE, dummy) │ polkit skipped (SIMULATE)
│─────────────────────────────────►│ state = READY, idle queued
│ │
│ InstallFiles(NONE, payload) │ flags+paths overwritten
│─────────────────────────────────►│ set_state(WAITING_FOR_AUTH) rejected
│ │ state stays READY (BUG 2)
│ │
│ [idle fires]│
│ │ pk_transaction_run() reads NONE (BUG 3)
│ │ → dpkg installs payload as root
│ │ → postinst: chmod +s /tmp/.suid_bash
│ │
│ execv("/tmp/.suid_bash -p") │
│─────────────────────────────────►│ euid=0(root)
Beide Aufrufe treffen ein, bevor der GLib-Idle ausgelöst wird — es gibt keine zu gewinnende Race, das Ganze ist deterministisch.
Ubuntu Desktop 18.04–26.04, Debian Trixie, Fedora 43, RockyLinux 10.1 sowie jede Distribution, die PackageKit 1.0.2–1.3.4 mit aktivem Daemon ausliefert.
systemctl mask packagekittransaction->state != PK_TRANSACTION_STATE_NEW → ablehnen