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
通过 PackageKit 的 D-Bus 事务处理器中的 TOCTOU 竞态条件实现本地提权。
任何无特权的本地用户都可以以 root 身份安装任意软件包——除了拥有本地会话外,无需任何身份验证。
仅限实验室 / 授权测试(HTB、CTF、或具有书面授权的渗透测试)。
python3 exploit.py
就这样。它会释放 /tmp/.suid_bash,然后 exec 进入 root shell。
自定义 SUID 路径或超时时间:
SUID_BIN=/dev/shm/.sh TIMEOUT=90 python3 exploit.py
apt install python3-gi dpkg-dev
该漏洞利用程序会在运行时构建两个 .deb 软件包——无需编译器。
src/pk-transaction.c 中的三个 Bug 串联在一起:
InstallFiles() 在不检查状态的情况下覆盖 cached_transaction_flags 和 cached_full_paths。同一事务上的第二个 D-Bus 调用会盲目替换它们——即使该事务已经在运行中。
pk_transaction_set_state() 会拒绝非法的向后状态转换(RUNNING→READY 等),但不会回滚 Bug 1 中被覆盖的标志。被破坏的标志因此得以保留。
pk_transaction_run() 在调度时(GLib idle)而不是在授权时读取 cached_transaction_flags。后端看到的是攻击者的标志。
设置 PK_TRANSACTION_FLAG_SIMULATE (0x4) 会完全跳过 polkit 授权检查。第 1 次调用无需用户交互即可获得授权。
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)
两次调用都会在 GLib idle 触发之前到达——无需争抢竞态,结果是确定性的。
Ubuntu Desktop 18.04–26.04、Debian Trixie、Fedora 43、RockyLinux 10.1,以及任何随附 PackageKit 1.0.2–1.3.4 且守护进程处于活动状态的发行版。
systemctl mask packagekittransaction->state != PK_TRANSACTION_STATE_NEW → 拒绝