KaraZajac/CHARON
GitHub: KaraZajac/CHARON
针对 CVE-2026-46333 Linux 内核 ptrace 漏洞的紧凑无依赖 PoC,通过竞态条件窃取 SUID 进程的文件描述符实现本地提权。
Stars: 0 | Forks: 0
#### CVE-2026-46333 / Linux <= 6.12.89
/ ___|| | | | / \ | _ \ / _ \| \ | |
| | | |_| | / _ \ | |_) | | | | \| |
| |___ | _ |/ ___ \| _ <| |_| | |\ |
\____||_| |_/_/ \_\_| \_\\___/|_| \_|
将 fd 摆渡穿过 exit-mm() 冥河
## 这是什么
这是一个针对 **CVE-2026-46333** 紧凑且无依赖的 PoC:即
Qualys 于 2026-05-15 披露的 `__ptrace_may_access` mm==NULL 绕过漏洞。
Charon 利用 `pidfd_getfd(2)` 与正在消亡的 SUID-root 进程展开竞速,
通过 `do_exit()` 中短暂的 mm-NULL 窗口提取其打开的 `/etc/shadow` 文件描述符。
#### 以非特权用户身份在受影响的机器上运行它;它会将 `/etc/shadow` 的内容输出到标准输出。
$ ./charon
[标准错误输出上的横幅]
[*] lure /usr/bin/chage target /etc/shadow
root:$y$j9T$ztS5H...$hz9W87TlqxEW...:...
daemon:*:20582:0:99999:7:::
bin:*:20582:0:99999:7:::
#### ...
典型命中率:在 4 核虚拟机上不到一秒,冒烟测试中约 **~137 次尝试**。
## 30 秒了解该漏洞
当 `task->mm == NULL` 时,`__ptrace_may_access()` 会短路其可转储性检查。
这个快速路径是为内核线程(如 swapper 等)编写的,它们合法地没有 mm,且永远不应被 ptrace。
但 `do_exit()` 会在 `exit_files()` *之前*运行 `exit_mm()`,
这意味着一个用户空间的 SUID 进程会短暂地具有以下状态:
- `task->mm == NULL`(mm 已被回收)→ 可转储性检查被跳过
- 文件表仍然存在 → fd 仍然可以被获取
- 凭证反映了 `setreuid()` 之后的降级状态 → 访问检查通过
`pidfd_getfd(2)` 信任该访问检查,并将 SUID 进程打开的文件描述符交给攻击者。
#### SUID 进程的打开文件描述符。
do_exit()
├── exit_mm() ← task->mm = NULL
├── ... ← __ptrace_may_access() 现在开始撒谎
#### └── exit_files() ← fd 表被回收
Jann Horn 于 2020 年 10 月在 lore.kernel.org 上指出了这种 FD 盗窃的模型。
该修复在维护者审查阶段停留了约 6 年,直到 Qualys 将其重新带回审查队列的最前面。
**上游修复:** [`31e62c2ebbfd`](https://github.com/torvalds/linux/commit/31e62c2ebbfdc3fe3dbdf5e02c92a9dc67087a3a)
(Linus 2026-05-14)。截至 2026-05-15,该反向移植尚未进入
linux-6.12.y 或 linux-6.6.y 稳定版分支。
## 受影响的内核
| 稳定版分支 | 状态 |
|---|---|
| linux-6.12.y (≤ 6.12.89) | ❌ 易受攻击 |
| linux-6.6.y (修复反向移植前) | ❌ 易受攻击 |
| mainline ≥ 6.15-rc1 | ✅ 已修补 (`31e62c2ebbfd`) |
| 发行版 | 内核 | 状态 (2026-05-15) |
|---|---|---|
| Debian trixie | 6.12.86+deb13 | ❌ |
| AlmaLinux 10.1 | 6.12.0-124.55.3 | ❌ |
| Ubuntu 26.04 | 7.0.0-15 | ⚠️ 需检查 |
| Fedora 44 | 7.0.4-200 | ⚠️ 需检查 |
随着反向移植的落地,PR / 滚动状态表将会更新。
## 构建
```
# 仅 38 KB 的 Tiny 静态二进制文件(推荐)
sudo apt-get install musl-tools
make static
# 或者仅使用标准的 glibc 构建
#### make
Output: a single ELF `./charon`.
## 运行
```sh
./charon # dump /etc/shadow (default)
./charon -q # no banner / progress, just shadow on stdout
./charon -v # show per-hit + final stats
./charon -r 5000 # more patience for slow systems
./charon -t /etc/ssh/ssh_host_ecdsa_key # different target (uses ssh-keysign bait)
./charon -a # auto-discover SUID/SGID baits if built-ins miss
./charon -L # list candidate baits without trying any
#### ./charon --help
### 自动发现
`--auto` walks `/usr/bin`, `/usr/sbin`, `/usr/local/{bin,sbin}`,
`/usr/lib/openssh`, `/usr/libexec`, `/bin`, `/sbin`, finds every
SUID/SGID regular file (excluding interactive baits like `su`,
`sudo`, `newgrp`, `pkexec`), and tries each as a bait against the
requested target. Per-bait budget is tight (5 rounds × 2000 inner)
so a full scan finishes in ~10 seconds even when nothing matches.
`--list-baits` is the read-only version — it enumerates the same
candidates without firing the exploit. Useful for surveying which
distros ship which baits.
### Exit codes
| Code | Meaning |
|---|---|
| 0 | Success — file contents on stdout |
| 1 | No SUID lure on this system opens the requested file |
| 2 | Kernel appears patched (CVE-2026-46333 closed) |
| 3 | Ran out of rounds without a hit (rare; try `-r 5000`) |
| 4 | CLI / IO error |
### Lures
Charon ships with four known SUID lures:
| Binary | File it opens | Distro coverage |
|---|---|---|
| `/usr/bin/chage` (`chage -l `) | `/etc/shadow` | Most Debian, Ubuntu, Fedora |
| `/usr/sbin/chage` | `/etc/shadow` | RHEL / Rocky / Alma family |
| `/usr/bin/passwd` (`passwd -S `) | `/etc/shadow` | Most distros |
| `/usr/lib/openssh/ssh-keysign` | `/etc/ssh/ssh_host_*_key` | Distros with HostbasedAuthentication enabled |
Adding a lure is a 3-line edit to the `lures[]` array in `charon.c`.
## 缓解措施,直到您的发行版发布 backport
- Apply `31e62c2ebbfd` directly.
- Disable `pidfd_getfd(2)` via seccomp on production hosts.
- Remove the setuid bit from `chage` and `passwd` if you do not need
unprivileged users to query password aging.
- For containerized workloads, enabling `no_new_privs` on the host
blocks the primitive entirely — every "SUID" inside the container
becomes inert, leaving Charon with no prey.
## 并非 kernelctf VRP 候选
The Google kernelctf VRP challenge VM runs the player's bash inside
an `nsjail` sandbox with `clone_newuser:true` (uid 0 unmapped),
`chroot:/chroot`, and `no_new_privs:1`. Under `no_new_privs` the
setuid bit is inert, so there are no real SUID prey inside the
sandbox, and `/flag` lives on the host outside the chroot. Charon
therefore cannot win kCTF VRP. It remains a legitimate Linux LPE on
bare-metal Debian / Ubuntu / RHEL family installations.
## 出处
- Bug discovered & disclosed by Qualys → oss-security 2026-05-15.
- Reference PoCs by [@0xdeadbeefnetwork](https://github.com/0xdeadbeefnetwork/ssh-keysign-pwn).
- Charon rewrites the lure-and-race loop into a single hardened
binary, adds CLI ergonomics, patched-kernel auto-detection, and
per-distro lure fallback.
## License
#### 仅供教学和授权防御使用。
⛵ STYX ⛵
╔══════════════════════════════╗
║ do_exit(): ║
║ ├── exit_mm() ← task->mm ║
║ │ = NULL ║
║ ├── ... ← ferry ║
║ └── exit_files() ║
#### ╚══════════════════════════════╝
```
标签:CVE-2026-46333, HTTP工具, Linux内核安全, Linux内核漏洞, meg, pidfd_getfd, PoC, ptrace, SUID, Web报告查看器, 信息安全, 协议分析, 安全渗透, 客户端加密, 影子文件读取, 文件描述符窃取, 暴力破解, 本地提权, 权限提升, 条件竞争, 概念验证代码, 竞态条件, 零依赖