一个基于 Docker 的 CTF 风格本地权限提升实验室,围绕 Pack2TheRoot 公告(CVE-2026-41651)构建,这是 PackageKit 守护进程中存在 12 年之久的漏洞,由德国电信红队于 2026 年 4 月 22 日披露。
该实验室包含三个容器:一个宽松 polkit 的 CTF 挑战、一个加固后的对比目标,以及一个完整的 TOCTOU 漏洞利用复现,后者从源码构建存在漏洞的 PackageKit 并运行实际的 CVE-2026-41651 根因利用。
| 容器 | 端口 | 角色 | 利用结果 |
|---|---|---|---|
pack2theroot-vuln | tcp/2222(ssh) | PackageKit ≤ 1.3.4 + 宽松 polkit 规则 | 通过构造的 RPM 获取 Root |
pack2theroot-patched | tcp/2223(ssh) | 相同,但 polkit 已加固 | 利用失败 |
pack2theroot-exploit | — | 从源码构建的存在漏洞的 PackageKit 1.3.4 | 通过 TOCTOU D-Bus 竞态获取 Root |
此外:
docs/CHALLENGE.md)docs/HINTS.md)docs/SOLUTION.md)docs/diagrams/)pk-transaction.c 中的三个连环漏洞该利用在同一事务上发送两次异步 D-Bus InstallFiles() 调用:首先使用 SIMULATE(绕过 polkit,排队一个 GLib idle 回调),然后立即使用 NONE + 恶意包(在 idle 触发前覆盖缓存的标志/路径)。GLib 的优先级排序保证两条 D-Bus 消息在 idle 回调之前完成调度 — 因此这是确定性的,而非时序竞态。
已知 IOC(来自公告):
journalctl --no-pager -u packagekit | grep -iE 'emitted_finished|pk_transaction_finished_emit|pk-transaction\.c:514'
git clone https://github.com/dinosn/pack2theroot-lab.git
cd pack2theroot-lab
docker compose build
docker compose up -d
ssh labuser@localhost -p 2222 # 密码:labuser
# 然后按照 docs/CHALLENGE.md 进行操作
旗标位于 /root/flag.txt(权限 0400 root:root)。格式:
PACK2THEROOT{...}
# 构建并运行 — 自动模式立即执行利用:
docker compose run --rm exploit
# 或手动模式:
docker compose run --rm --entrypoint /entrypoint.sh exploit
# 然后在容器内:
su - victim -c /exploit/cve-2026-41651
该利用用 C 语言构建两个 .deb 包(无需外部工具),发送两次调用的 D-Bus 竞态,并在 /tmp/.suid_bash 创建一个 SUID bash。完整技术演练请参阅 docs/SOLUTION.md。
拆除:
docker compose down -v
pack2theroot-lab/
├── README.md
├── docker-compose.yml
├── docs/
│ ├── CHALLENGE.md # 玩家说明
│ ├── HINTS.md # 渐进式提示(两条路径)
│ ├── SOLUTION.md # 完整演练 + 旗标
│ ├── references.md # 主要和次要来源
│ ├── threat-model.md # 攻击者/防御者假设
│ └── diagrams/ # 利用流程的 SVG 可视化图表
│ ├── 01-docker-build.svg
│ ├── 02-container-startup.svg
│ ├── 03-exploit-execution.svg
│ ├── 04-dbus-race-sequence.svg
│ ├── 05-attack-overview.svg
│ └── 06-auto-mode-full-run.svg
├── exploit/
│ ├── Dockerfile # 从源码构建存在漏洞的 PackageKit 1.3.4
│ ├── entrypoint.sh # 启动 dbus + polkitd + packagekitd
│ ├── Makefile
│ └── src/
│ └── cve-2026-41651.c # TOCTOU 利用(公开 PoC)
├── vulnerable/
│ ├── Dockerfile
│ ├── entrypoint.sh
│ └── policy/
│ └── 10-pack2theroot-lab-misconfig.rules # CTF 挑战
├── patched/
│ ├── Dockerfile
│ ├── entrypoint.sh
│ ├── local/ # 将 1.3.5 反向移植 RPM 放在此处(可选)
│ └── policy/
│ └── 10-pack2theroot-lab-hardened.rules # 修复方案
└── scripts/
├── exploit-check.sh # 检查版本、polkit、D-Bus、IOC
├── check-version.sh # VULNERABLE 与 PATCHED 判定
├── check-preconditions.sh # pkcon / polkit / D-Bus 健全性检查
├── monitor-ioc.sh # 跟踪 journal 中的公告 IOC
├── compare-env.sh # 对比两个容器
└── apply-polkit-mitigation.sh # 针对未修补主机的临时加固
docs/diagrams/ 目录包含展示利用流程的 SVG 图表。可在任意浏览器中打开:
参见 docs/CHALLENGE.md。简要说明:
labuser 身份 SSH 登录(密码 labuser)。rpm-build、rpmdevtools)。pkcon install-local --allow-untrusted 安装。%post 脚本片段以 root 身份运行。读取 /root/flag.txt。卡住了?docs/HINTS.md 提供越来越明确的提示。只有在解决挑战或确实需要解析文档时才打开 docs/SOLUTION.md。
在任一容器内,以任意用户身份:
/opt/lab/check-version.sh # VULNERABLE 或 PATCHED 判定
/opt/lab/check-preconditions.sh # 暴露面自检
/opt/lab/exploit-check.sh # 版本 + polkit + D-Bus + IOC 检查
/opt/lab/monitor-ioc.sh # 跟踪 journal 中的 IOC
从宿主机并排对比:
./scripts/compare-env.sh
对存在漏洞的容器应用临时 polkit 缓解:
docker exec pack2theroot-vuln /opt/lab/apply-polkit-mitigation.sh
# 然后重试利用 — 现在应该失败。
patched 镜像如实处理 PackageKit 版本状态:
/etc/pack2theroot-banner),说明已安装版本是真正的补丁还是发行版占位符。一旦您的发行版发布了反向移植,要构建版本完整的已修补镜像,请将 RPM 放入 patched/local/ 并重新构建:
docker compose build --build-arg USE_LOCAL_RPM=1 patched
--privileged 才能运行完整的 dbus/polkitd/packagekitd 栈。仅在隔离环境中运行。labuser)故意设置得很弱。切勿重复使用。主要来源:
CVE-2026-41651:
https://nvd.nist.gov/vuln/detail/CVE-2026-4165176cfb675:
https://github.com/PackageKit/PackageKit/commit/76cfb675fb31acc3ad5595d4380bfff56d2a8697次要报道和发行版跟踪器请参阅 docs/references.md。
MIT — 参见 LICENSE。
| 字段 | 值 |
|---|
| CVE | CVE-2026-41651 |
| 名称 | Pack2TheRoot |
| 类型 | 本地权限提升(TOCTOU / CWE-367) |
| 组件 | PackageKit 守护进程(pk-transaction.c) |
| 受影响范围 | >= 1.0.2 且 <= 1.3.4(12 年的发布版本) |
| 修复版本 | PackageKit 1.3.5(提交 76cfb675,发布于 2026-04-22) |
| CVSS 3.1 | 8.8(高危) — AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H |
| 前置条件 | 在运行 PackageKit 的主机上拥有本地非特权 shell |
| 发现者 | Deutsche Telekom Security GmbH — 红队 |
| 漏洞 | 位置 | 影响 |
|---|
| 漏洞 1 | InstallFiles()(约第 4036 行) | 无条件覆盖 cached_transaction_flags 和 cached_full_paths — 无状态保护 |
| 漏洞 2 | pk_transaction_set_state()(约第 876–881 行) | 静默丢弃向后状态转换而非报错 — 标志已被污染 |
| 漏洞 3 | pk_transaction_run()(约第 2273–2277 行) | 在调度时而非授权时读取 cached_transaction_flags |
| 绕过 | SIMULATE 标志(约第 2893–2900 行) | PK_TRANSACTION_FLAG_SIMULATE(0x4)完全绕过 polkit |
| 图表 | 描述 |
|---|
01-docker-build.svg | 两阶段 Docker 构建 — 编译存在漏洞的 PackageKit |
02-container-startup.svg | 容器启动 — dbus、polkitd、packagekitd 启动 |
03-exploit-execution.svg | 带注释阶段的逐步利用输出 |
04-dbus-race-sequence.svg | D-Bus 时序图 — 漏洞 1/2/3 如何与 GLib 优先级串联 |
05-attack-overview.svg | 高层攻击流程:带时间线的攻击者与系统对比 |
06-auto-mode-full-run.svg | 完整的 --auto 模式终端 — 从容器启动到 root shell |