0xCyberstan/CVE-2026-31694-POC

GitHub: 0xCyberstan/CVE-2026-31694-POC

针对 Linux 内核 FUSE readdir 缓存越界写入漏洞(CVE-2026-31694)的 PoC 与本地提权利用,通过 page-cache 损坏实现无密码 root 提权。

Stars: 14 | Forks: 2

# CVE-2026-31694:FUSE readdir 缓存越界写入 `fs/fuse/readdir.c:fuse_add_dirent_to_cache()` 中缺少边界检查。一个 FUSE 服务器返回了一个 `namelen = 4095` 的 dirent,它被序列化为一条 4120 字节的记录。内核将其复制到一个仅有 4096 字节的 page-cache 页面中, 并溢出了 24 个由服务器控制的字节,进入到了下一个物理页面。 这个仓库包含一个用于写入原型的标记 PoC,以及一个本地权限提升(LPE)漏洞利用。 它通过精确的内存布局(grooming),将溢出数据定向到 `/etc/passwd` 的 page-cache 副本上, 从而将 root 账户转换为一个无密码账户。 - 受影响版本:Linux 6.15+(将 `FUSE_NAME_MAX` 提升至 `PATH_MAX - 1` 使得 readdir 路径变得可达) - 修复方案:`51a8de6c50bf9` "fuse: reject oversized dirents in page cache"(五个稳定版 回移(backport)补丁之一) - CVE-2026-31694 ## 警告:仅限虚拟机使用,切勿在裸机上运行 这种溢出是内核向 FUSE 缓存页面紧接的下一个物理页面写入数据。漏洞利用通过布局尝试将 写入定向到选定的页面,但这具有概率性。如果偏离目标,这 24 字节可能会命中无关页面: - 其他文件的缓存页面,包括将被写回磁盘的脏页面(dirty pages),这会 破坏真实文件, - 内核数据,可能导致机器 panic 或造成静默数据损坏。 仅在一次性虚拟机中运行它。这里的脚本始终在 QEMU/KVM 内运行漏洞利用, 从不在宿主机上运行。 ## 目录结构 ``` exploit.c the PoC and LPE (single file, static build) Makefile builds ./exploit (static) vm/config.sh all paths and settings (edit KERNEL_TREE) vm/make_rootfs.sh build the Ubuntu 24.04 guest image (run as root) vm/build_vuln_kernel.sh build a vulnerable bzImage from your kernel tree vm/run_vm.sh boot the guest headless vm/provision_guest.sh in-guest setup (runs over ssh) vm/run_in_vm.sh one command: boot, provision, run, verify ``` ## 环境要求 宿主机:带有 KVM 的 Linux(存在 `/dev/kvm`,你的用户属于 `kvm` 组),并且需要: - `qemu-system-x86_64`、`sshpass`、`gcc`、`make` - 运行 `make_rootfs.sh` 还需要:`debootstrap`(以及 root 权限) 你还需要一个 Linux 内核源码树,以便从中构建存在漏洞的内核。 ## 设置说明 1. 编辑 `vm/config.sh`。你必须设置的唯一值是 `KERNEL_TREE`:即 Linux 源码检出路径。请使用修复补丁 `51a8de6c50bf9` 之前的版本 (任何 6.15..7.0 的检出都存在此漏洞)。如果该源码树已经包含了修复补丁, `build_vuln_kernel.sh` 会在构建期间移除该防护检查,并在构建完成后恢复该文件。 其他所有配置(内存、CPU、SSH 端口、镜像路径)都有默认值,你可以直接 保留默认。任何值也可以通过环境变量设置, 例如 `KERNEL_TREE=/path/to/linux vm/run_in_vm.sh`。 2. 构建客户机镜像(Ubuntu 24.04,debootstrap 需要 root 权限): sudo vm/make_rootfs.sh 这将创建一个 `test:test` 的 sudo 用户、一个串行控制台、SSH 密码认证 以及 fuse3。 3. 构建存在漏洞的内核: vm/build_vuln_kernel.sh ## 运行 端到端执行(启动、配置、标记 PoC、LPE、验证 uid 0): ``` vm/run_in_vm.sh ``` 手动执行: ``` vm/run_vm.sh & # boot headless; console goes to vm/serial.log make # build the static exploit # 将 ./exploit 复制到 guest 中,然后以 test 用户身份执行: ./exploit --poc -n 20 # marker test ./exploit # warmup, then LPE ``` 停止虚拟机: ``` pkill -f bzImage-fuse-vuln ``` ## exploit 选项 ``` --poc marker mode only, no /etc/passwd changes -n N number of rounds (no args) 5 warmup rounds, then up to 200 LPE attempts; on success it writes a passwordless root line to /etc/passwd and drops caches ``` ## 预期输出 Marker 模式会打印每轮命中次数和总次数,例如 `20/20 (100.0%)`。 LPE 模式会打印 `Warmup: 5/5`,随后是一行 `LPE n/200 ... HIT!`,并将 `/etc/passwd` 的第一行从 `root:x:0:0:root:/root:/bin/bash` 修改为 `root::0:0:root:/root:/bin/sh`,随后使用空密码执行 `su -s /bin/sh root` 将返回 uid 0。 ## 原理解析 readdir 缓存路径会将每个 dirent 复制到一个 page-cache 页面中。大小检查 仅判断该 dirent 是否适合当前页面的剩余空间;它 从未检查过该 dirent 是否能完整放入一个页面中。当 `namelen = 4095` 时, 记录大小为 4120 字节,因此此次复制会越过一个全新页面的末尾 24 字节。 漏洞利用首先排空每 CPU 页面(PCP)空闲链表,以便分配器从 buddy 分裂中分配 物理上相邻的页面,然后将 readdir 缓存 页面与受害页面安排为相邻页面。对于 LPE,受害页面是 `/etc/passwd` 的 page-cache 副本:这 24 字节的溢出重写了 root 的行,使其密码 字段变为空,并且在 PAM 开启 `nullok`(Ubuntu 默认开启)的情况下,`su root` 随后即可 使用空密码成功登录。 完整分析:[https://cyberstan.co.uk/fuse-readdir-oob/](https://cyberstan.co.uk/fuse-readdir-oob/) ## 漏洞披露 由 Qi Tang 和 Zijun Hu 在上游报告;修复补丁由 Samuel Page 编写。 我独立发现并报告了此漏洞。上游致谢和 CVE-2026-31694 归属于他们。该漏洞已在 主线和稳定版分支中修复。 ## 许可证 MIT,详见 `LICENSE`。仅供教育和授权测试使用。
标签:Cutter, FUSE, Linux内核, PoC, Web报告查看器, 安全渗透, 客户端加密, 暴力破解, 本地提权