
CVE-2026-31431(Copy Fail):一个 Python 脚本就能拿 root,Linux 内核的 9 年沉疴
2026 年 4 月 29 日,安全研究团队 Theori 公开了一个 Linux 内核漏洞,代号 Copy Fail,编号 CVE-2026-31431,CVSS 评分 7.8(高危)。
但这个漏洞真正让人不安的不是评分——而是三个事实:
- 影响范围极广:从 2017 年引入至今,几乎涵盖了所有主流 Linux 发行版——Ubuntu、Debian、RHEL、Rocky、SUSE、Amazon Linux……无一幸免
- 利用门槛极低:732 字节的 Python 脚本,普通用户运行后直接获得 root shell,不需要任何竞争条件,不需要多次尝试
- 还能容器逃逸:如果你在容器里拿到一个普通用户的权限,可以直接逃逸到宿主机
这是一个让人后背发凉的漏洞。
一句话理解 Copy Fail
要理解这个漏洞,不需要懂内核源码,只需要知道一个简单的机制:
Linux 内核里有一个叫 页缓存(page cache) 的东西。当你读一个文件时,内核把文件内容缓存到内存里。后续的读写操作直接操作内存中的缓存,不需要重新读磁盘。
Copy Fail 利用了加密子系统 AF\_ALG 的一个代码缺陷,通过 splice() 系统调用,把目标文件(比如 /usr/bin/su)的页缓存页面链入加密操作的数据链表中。加密过程中的一次越界写入,会直接修改这个页缓存。
关键点:这个修改只会发生在内存中,不会触发磁盘回写。 所以普通的文件完整性检查工具(比如 sha256sum)查不出问题——磁盘上的文件是完好的,但内存中的执行映像已经被篡改。
攻击者把 /usr/bin/su 这类 setuid 程序改掉一两个字节,下次执行时就直接变成 root 了。
漏洞时间线
- 2017 年:提交
72548b093ee3被合入内核主线。这是一个优化:AF\_ALG 的 AEAD 解密路径改成「就地操作(in-place)」,把用户传入的页面直接链入散列表,避免额外的内存拷贝。 - 2017–2026 年(9 年):这个优化一直存在于内核中,没有被发现有问题。
- 2026 年 4 月 22 日:Greg Kroah-Hartman 提交修复补丁
a664bf3d603d,标题是「crypto: algif\_aead – Revert to operating out-of-place」——回退到非就地模式,承认 in-place 优化带来的复杂性不值得。 - 2026 年 4 月 29 日:Theori 公开漏洞详情和 PoC。
- 2026 年 4 月 29–30 日:各大发行版紧急发布安全更新。
影响版本
漏洞从内核提交 72548b093ee3 开始引入,到修复 a664bf3d603d 结束。
具体的受影响内核版本范围:
| 分支 | 受影响版本 | 安全版本 |
|---|---|---|
| 4.14–5.10 | < 5.10.254 | >= 5.10.254 |
| 5.11–5.15 | < 5.15.204 | >= 5.15.204 |
| 5.16–6.1 | < 6.1.170 | >= 6.1.170 |
| 6.2–6.6 | < 6.6.137 | >= 6.6.137 |
| 6.7–6.12 | < 6.12.85 | >= 6.12.85 |
| 6.13–6.18 | < 6.18.22 | >= 6.18.22 |
| 6.19 | < 6.19.12 | >= 6.19.12 |
| 7.0-rc | <= rc6 | >= rc7 |
受影响的主流发行版:
| 发行版 | 受影响版本 | 安全版本 |
|---|---|---|
| Ubuntu 24.04 LTS | < 6.8.0-117.117 | >= 6.8.0-117.117 |
| Ubuntu 22.04 LTS | < 5.15.0-179.189 | >= 5.15.0-179.189 |
| Ubuntu 20.04 LTS | < 5.4.0-230.250 | >= 5.4.0-230.250 |
| Debian 12 | < 6.1.170-1 | >= 6.1.170-1 |
| RHEL 9 | < 5.14.0-611.54.1 | >= 5.14.0-611.54.1 |
| RHEL 8 | < 4.18.0-553.123.1 | >= 4.18.0-553.123.1 |
几乎每一个主流发行版的 LTS 版本都在射程内。
为什么叫 Copy Fail
这个名字来自漏洞的本质:内核在复制数据时出了错。
in-place 操作的本意是「不复制数据,直接操作原页面」。但在 authencesn 加密模板的特殊实现中,它错误地把输出缓冲区后面的页面也当成了自己的临时存储空间。
说白了就是——该复制的时候没复制,不该写的地方写了。
漏洞的实际利用
Theori 公开的 PoC 代码不到 100 行,用 Python 编写。
攻击过程大致如下:
- 创建一个 AF\_ALG 类型的 socket,选择
authencesn(hmac(sha256),cbc(aes))算法 - 以只读方式打开目标文件(比如
/usr/bin/su) - 通过
splice()系统调用把文件页缓存直接链入加密操作的输入散列表 - 触发解密操作,AEAD 解密路径中的越界写入覆盖了
/usr/bin/su的页缓存 - 写入的 4 字节数据经过精心构造,把 su 的某些字节改为特定值
- 执行
/usr/bin/su,此时它已经被篡改,直接以 root 权限执行攻击者的代码
整个过程不需要竞争条件、不需要重试、不需要特殊的系统配置。一次执行,稳定提权。
演示视频中,攻击者在 Ubuntu 24.04、22.04、RHEL 9、Debian 12 四个系统上运行同一个脚本,全都秒获 root。
为什么 9 年没人发现
有几个原因:
- 代码路径非常特殊。它要求 AF\_ALG + AEAD + authencesn + splice() 四个组件同时配合。这不是普通人日常使用的路径。
- splice() 和 AF\_ALG 的组合很少被审计。这两者分别是文件系统和加密子系统的接口,属于跨子系统交互,容易成为安全审查的盲区。
-
in-place 优化看起来很自然。2017 年引入时,提交信息写的理由很有道理:源和目标来自不同的内存映射,没必要复制。这个推理本身没错,但忽略了 authencesn 算法的一个特殊行为——它在解密过程中会额外写入 4 字节。
-
越界写入非常隐蔽。4 字节的偏移量,恰好跨越了一个边界,不会触发常规的内存越界检测。
影响远不止本地提权
对于云环境和容器平台来说,这个漏洞的杀伤力更大。
因为 Copy Fail 操作的是页缓存——页缓存在容器和宿主机之间是共享的。 这意味着:如果你在容器里有一个普通用户权限,也可能利用这个漏洞篡改宿主机的 setuid 文件,实现容器逃逸。
多家安全厂商的报告中都明确提到了 Kubernetes 节点的风险。
写在最后
Copy Fail 不是那种需要特殊硬件、特定配置、复杂操作才能触发的漏洞。一个普通的 Linux 用户登录到系统上,运行一段不到 100 行的 Python 代码,就能拿走 root。
如果你是服务器管理员,第一件事就是检查你的内核版本是否在受影响范围内,然后尽快更新。下一篇文章我会讲具体的排查方法和修复步骤。
评论