Naimadx123/cve_2026_31431
GitHub: Naimadx123/cve_2026_31431
针对 Linux 内核 algif_aead 页缓存写入漏洞(CVE-2026-31431)的本地提权(LPE)概念验证与无损检测工具包。
Stars: 0 | Forks: 0
# CVE-2026-31431 ("Copy Fail") 工具包
针对 2026-04-29 披露的 Linux `algif_aead` / `authencesn` 页缓存临时写入漏洞的检测器和本地提权 (LPE) 概念验证。
漏洞披露详情:
## 授权
仅在你拥有或被明确授权评估的主机上使用。该 LPE 会修改内存状态(页缓存),但此技术属于真实的权限提升——在未经授权的系统上运行它在大多数司法管辖区都是违法的。
## 漏洞摘要
`algif_aead` 原地(`req->src == req->dst`)执行 AEAD 操作。当源数据通过 `splice()` 从普通文件输入时,目标散列表包含对该文件页缓存页的引用——即内核将写入这些页面。随后,`authencesn(hmac(sha256), cbc(aes))` 算法会将 AAD 的 `seqno_lo` 字段(由 sendmsg 提供的 AAD 的第 4-7 字节)执行一次 4 字节的“临时”写入到该目标中,从而破坏文件的页缓存副本。
因为磁盘上的文件从未被修改,所以没有磁盘上的痕迹;这种破坏只能被共享页缓存的读取者观察到。`/etc/passwd` 和 `/usr/bin/su` 都是全局可读的,因此无特权的本地用户可以破坏运行中内核对这两者的视图。
受影响系统:包含 commit `72548b093ee3`(原地 AEAD,2017年)但未包含上游回退补丁的内核。该披露确认了 Ubuntu 24.04 LTS、Amazon Linux 2023、RHEL 14.3 和 SUSE 16 受到影响,但其底层原语的存在时间早于上述范围。
## 文件
| 文件 | 用途 |
| --- | --- |
| `test_cve_2026_31431.py` | 非破坏性检测器。在临时目录中的哨兵文件上操作;从不触碰系统二进制文件。 |
| `exploit_cve_2026_31431.py` | LPE。将 `/etc/passwd` 页缓存中当前用户的 UID 翻转为 0,然后调用 `su` 获取 root shell。 |
这两个脚本均为纯 Python 3.10+ 标准库实现。
## 快速开始
```
# 检测
python3 test_cve_2026_31431.py
# 退出码 0 = 不存在漏洞,2 = 存在漏洞,1 = 测试错误
# 利用(交互式 — su 将提示输入你自己的密码)
python3 exploit_cve_2026_31431.py --shell
```
## 检测器用法
```
python3 test_cve_2026_31431.py
```
它的功能:
1. 确认无特权进程可以访问 `AF_ALG` 和 `authencesn(hmac(sha256),cbc(aes))` 算法。
2. 在临时目录中创建一个 4 KiB 的哨兵文件,并将其填充到页缓存中。
3. 通过带有 cmsg 的 `sendmsg` 发送 8 字节的内联 AAD,其中 seqno_lo 设置为标记 `PWND`,然后通过 `os.splice()` 将哨兵文件页缓存页中的 32 字节拼接到 AF_ALG 操作套接字中。
4. 调用 `recv()` 驱动解密。身份验证检查将因 `EBADMSG` 失败;但临时写入仍会触发。
5. 重新读取文件(通过页缓存而非磁盘)并查找该标记。
输出类别:
- `Precondition not met` — `AF_ALG` 或 `authencesn` 不可用。退出码为 0。
- `VULNERABLE to CVE-2026-31431` — 标记 `PWND` 成功写入拼接的页面中。退出码为 2。
- `Page cache MODIFIED via in-place AEAD splice path` — 页面已被写入,但标记未出现在预期位置。请视为存在漏洞。退出码为 2。
- `Page cache intact` — 已修补。退出码为 0。
该检测器从不触碰 `/usr/bin/su`、`/etc/passwd` 或其创建的临时目录之外的任何其他文件,并且该文件在退出时会被删除。
## LPE 用法
```
python3 exploit_cve_2026_31431.py # patch only, print next steps
python3 exploit_cve_2026_31431.py --shell # patch and exec `su `
```
它的功能:
1. 在 `/etc/passwd` 中查找当前用户的 UID 行,并找到 4 字符 UID 字段的字节偏移量。
2. 针对该偏移量发起一次 `write4` 操作,将 UID 替换为 `0000`。
3. 调用 `pwd.getpwnam(user)` 确认 libc 现在报告的 UID 为 0。
4. 使用 `--shell` 参数时,执行 `execvp("su", ["su", user])`。输入你自己的密码。PAM 将针对 `/etc/shadow`(未修改)进行验证,随后 `setuid(getpwnam(user).pw_uid)` 将被设置为 0。
### 要求
- 运行脚本的用户具有 4 位数的 UID (1000–9999)。1 至 3 位的 UID 需要多次写入——请相应地扩展 `write4`。
- 不能有掩盖 `/etc/passwd` 读取的 NSS 缓存守护进程(如 `nscd`、`sssd`、`systemd-userdbd`)。如果在修补后 `getpwnam` 仍然返回真实的 UID,请重启或绕过缓存,或者选择其他用户。
- `/etc/passwd` 页面必须在修补和执行 `su` 之间保留在缓存中。实际上,这在任何具有正常内存压力的系统上都是可靠的。
### 还原
磁盘上的 `/etc/passwd` 未发生改变。
**空运行**(不带 `--shell` 运行 `exploit_cve_2026_31431.py`)会在退出时通过 `POSIX_FADV_DONTNEED` 自动驱逐受损的页面,因此 UID→名称 的查找会立即恢复正常。
**在执行 `--shell` 之后**,该页面将保持受损状态,直到你将其清除。在受损期间,任何将 UID 1000 解析为名称的操作(例如 `ls`、文件管理器、scp/sftp 所有权检查)都将失败或显示数字 ID。清除方法:
```
# 无特权 - 请求对 /etc/passwd 进行 page-cache 驱逐:
python3 -c "import os; fd=os.open('/etc/passwd', os.O_RDONLY); \
os.posix_fadvise(fd, 0, 0, os.POSIX_FADV_DONTNEED); os.close(fd)"
# 从 root shell 中:
echo 3 > /proc/sys/vm/drop_caches
```
重新启动也可以将其清除。
## `write4` 工作原理
```
sendmsg([8-byte AAD], cmsg=[ALG_SET_OP=DECRYPT, ALG_SET_IV, ALG_SET_AEAD_ASSOCLEN=8],
flags=MSG_MORE)
splice(target_fd, pipe_w, 32, offset_src=file_offset)
splice(pipe_r, op_fd, 32)
recv(op_fd) # EBADMSG; scratch write has already landed
```
来自 AAD 位置 4–7 的 4 个字节(`seqno_lo`)由 `authencesn` 写入目标散列表,在此代码路径中,也就是我们从 `target_fd` 拼接而来的页缓存页。在页面中的落点偏移量对应于我们传递给 `splice()` 的 `offset_src`。
## 缓解措施
在修补后的内核到达你的发行版之前:
```
sudo tee /etc/modprobe.d/disable-algif-aead.conf <<<'install algif_aead /bin/false'
sudo rmmod algif_aead 2>/dev/null
```
应用后,`test_cve_2026_31431.py` 应报告 `Precondition not met` 并以退出码 0 退出。
上游修复将原地 AEAD 操作还原为非原地操作,使页缓存页脱离可写散列表。
标签:algif_aead, authencesn, CVE-2026-31431, Linux漏洞, LPE, POC, Python, Web报告查看器, 内存损坏, 内核漏洞, 子域名枚举, 安全渗透, 提权脚本, 数据展示, 无后门, 本地提权, 权限绕过, 系统安全, 红队, 网络安全, 隐私保护, 零日漏洞, 页缓存