CVE-2026-31431 — “Copy Fail“ 深度拆解
一句话定调:这是近几年 Linux 内核最干净利落、最让人后背发凉的本地提权漏洞之一——732 字节纯 Python 标准库脚本,无需编译,无需竞态,跨所有主流发行版,确定性拿到 root。
1. 基本档案卡
|
项目 |
内容 |
|---|---|
|
CVE |
CVE-2026-31431 |
|
代号 |
Copy Fail |
|
发现者 |
Taeyang Lee(Theori / Xint Code),2026 年 3 月 23 日报送,4 月 29 日公开披露 |
|
CVSS |
7.8(High) — AV:L / AC:L / PR:L / UI:N |
|
漏洞类型 |
本地权限提升(LPE)/ 容器逃逸原语 |
|
触发前提 |
你只需要一个非特权本地用户 shell(或容器内代码执行) |
|
远程? |
❌ 不远程直接利用,但凡是有"先有个低权限执行点"的场景——Web RCE、SSH 弱口令、CI Runner、恶意包、容器 foothold——立刻变成 root |
|
PoC 状态 |
✅ 已公开,约 732 字节 Python 脚本,无需第三方库 |
|
修复提交 |
主线 |
2. 漏洞到底藏在哪?——三个"各自合理"的改动,凑出了灾难
Copy Fail 最精妙(也最可怕)的地方在于:它不是一段明显傻掉的代码,而是三个来自不同时期、各自看似合理的设计决策,在特定交汇点产生的逻辑缺陷。
🧩 三块拼图
|
# |
组件 |
引入时间 |
单独看没问题,但…… |
|---|---|---|---|
|
① |
|
2011 年 |
它假设输出缓冲是自己专属的,不应该被别人共享 |
|
② |
AF_ALG 接口获得 |
2015 年 |
|
|
③ |
|
2017 年 |
这意味着:从 splice 来的 page cache 页被放进了可写输出的 scatterlist 中 |
致命交汇 = ② 把 su 的 page cache 页以引用方式喂入 → ③ 让它进可写 scatterlist → ① 对着它做了 4 字节越界 scratch 写
结果:无特权用户精准地向 /usr/bin/su的 in-memory 页缓存写了 4 个自己控制的字节——而磁盘上的文件纹丝不动。
🔑 为什么是"恰好 4 字节"就够了?
你可能会想:"才 4 个字节能干什么?"
答案是——足够把 setuid(0)的机器码 shellcode(或其等效跳转/gadget)写进 su的内存映像的关键偏移,或者更常见的利用手法:
-
通过多次迭代(约 ~40 次 splice→触发→写入循环),逐步逐页覆写目标 setuid 二进制的关键字节
-
最终让
execve("/usr/bin/su")时内核映射的已被污染的页缓存执行你注入的代码路径 -
由于页缓存在宿主机与所有容器间共享,容器内也能污染宿主机的
su页缓存 → 容器逃逸
3. 攻击链全景图(概念级)
攻击者(普通用户 alice)
│
├─ 1. 打开 /usr/bin/su(只读 fd)← 这是 setuid(root) 二进制
│
├─ 2. 创建 AF_ALG 套接字(socket(AF_ALG, ...))
│ 绑定 aead / authencesn 算法
│
├─ 3. 用 pipe + splice(),把 su 的 fd 的页缓存页
│ 零拷贝喂入 AF_ALG 的 scatterlist
│ ── 此时 su 的 page cache 页被链入"可写"输出散列表
│
├─ 4. 触发 authencesn 解密路径
│ → 4 字节受控数据写入 su 的 page cache 页
│
├─ 5. 重复若干轮,完成 payload 植入
│
└─ 6. execve("/usr/bin/su") → 内核加载被污染的页缓存页
→ 以 root 身份执行注入代码 → 🎉 get root shell
关键属性:
-
确定性:不靠 race condition,每次都能打中
-
隐蔽:只改内存页缓存,不改磁盘 →
sha256sum /usr/bin/su看着完全正常 -
便携:纯 Python 标准库,732 字节,同脚本通吃 Ubuntu / RHEL / SUSE / Amazon Linux / Arch……
-
容器可见:页缓存跨容器共享 → 容器内打宿主机
su
4. 影响范围——"几乎一切"
|
维度 |
详情 |
|---|---|
|
内核 commit 区间 |
引入: |
|
不受影响的版本 |
主线 ≥ 7.0 / 稳定 ≥ 6.18.22 / 6.19.12+;Ubuntu 26.04 LTS(Resolute) 不受影响;RHEL 6/7 因内核基线不同不受影响 |
|
仍在影响的长线 |
6.12 所有、6.6 所有、6.1 所有、5.15 所有、5.10 所有——意味着大量 LTS / 云定制内核在 2026 年 4-5 月仍裸奔 |
|
发行版 |
Ubuntu 18.04/20.04/22.04/24.04、RHEL 8/9/10、Debian 10/11/12、Amazon Linux 2/2023、SUSE 12~16、Rocky/Alma/Oracle/openEuler……几乎全覆盖 |
|
高危场景 |
多租户共享主机、CI/CD Runner(GitHub Actions / GitLab Runner 沙boxes)、容器宿主机/K8s Node、Serverless 执行环境 |
5. 怎么排查?(两分钟内知道你中没中)
Step 1 — 内核版本
uname -r
uname -a
对照原则:如果你的内核 git log 落在 72548b093ee3之后、a664bf3d603d之前 → 理论上有风险。快速经验法则:
-
内核版本号在
4.14以上且未确认包含修复提交 → 假定受影响,继续查 -
已升级到发行版标注"修复"的 kernel pkg → 相对安全
Step 2 — 模块是否加载 / 可加载
# 是否已加载
lsmod | grep algif
# 或者看有没有 AF_ALG 活跃 fd
lsof 2>/dev/null | grep -i AF_ALG
# 看你能否打开 AF_ALG(普通用户就能试)
python3 -c "
import socket
try:
s = socket.socket(38, socket.SOCK_SEQPACKET, 0) # AF_ALG=38
print('AF_ALG 可用 → 潜在触发路径存在')
except Exception as e:
print('AF_ALG 不可用:', e)
"
如果
algif_aead压根没加载 + AF_ALG socket 创建被 seccomp 拦了 → 攻击面显著收窄(但仍建议按修复方案处理)
6. 修复 & 临时缓解(优先级:升级 > 缓解 > 忽视)
✅ 首选:升级内核(需重启)
# Ubuntu / Debian
apt update && apt upgrade linux-image-$(uname -r)
# 或直接升级所有内核相关
apt full-upgrade
# RHEL / Rocky / Alma
dnf update kernel
reboot
# Amazon Linux
yum update kernel
reboot
⚠️ 截至 2026 年 4 月 30 日左右,Debian 和 Ubuntu 多数在支版本尚未推完修复包,SUSE 也有部分版本待更——所以如果
apt/dnf告诉你 kernel 已经是最新但uname -r还没跳进安全区间,你需要用下面的临时缓解先顶住。
🛡️ 临时缓解方案 A:禁用 algif_aead模块(推荐)
# 阻止未来加载
echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif-aead.conf
# 尝试卸载(如果已加载)
rmmod algif_aead 2>/dev/null || echo "(algif_aead 未加载或 builtin,跳过)"
# 清页缓存(把可能被篡改的脏缓存刷掉——虽然 Copy Fail 的写入不标脏,但稳妥起见)
sync && echo 3 > /proc/sys/vm/drop_caches
注意:某些发行版(如 Rocky 8)把
algif_aead编进了内核本体(builtin),不能用rmmod卸——此时需要用方案 B。
🛡️ 临时缓解方案 B:Grub 内核参数(builtin 场景)
# 编辑 /etc/default/grub
# 在 GRUB_CMDLINE_LINUX 里追加:
# initcall_blacklist=algif_aead_init
# 然后重新生成 grub cfg
grub2-mkconfig -o /boot/grub2/grub.cfg # 或 /boot/efi/EFI/... 视引导方式而定
reboot
🛡️ 容器环境:Seccomp 封 AF_ALG
不管宿主机修没修,给容器加 Seccomp Profile 直接拦 socket(AF_ALG, ...) 是最有效的额外防线:
// 在你的 seccomp profile 的 "syscalls" 里加:
{
"names": ["socket"],
"action": "SCMP_ACT_ERRNO",
"args": [
{ "index": 0, "value": 38, "op": "SCMP_CMP_EQ" }
]
}
Docker 默认 profile 没有拦 AF_ALG —— 这就是很多人在评估时踩坑的点。
7. 检测思路(蓝队 / SOC 角度)
|
层次 |
做法 |
|---|---|
|
AuditD |
监控非 root 用户创建 address family 38(AF_ALG)socket: |
|
行为异常 |
普通用户短时间内反复 |
|
后验猎疑 |
找 ruid≠0 但进程 uid=0 的异常 shell、/tmp 或 /dev/shm 中新出现的可执行、非预期 ssh key 写入 |
|
文件完整性 |
⚠️ Copy Fail 不改磁盘 → 传统 HIDS 文件哈希检查看不到 → 必须用行为检测补位 |
8. 为什么这个漏洞值得你在意(不只是又一个 CVE)
Copy Fail 之所以在 2026 年 4 月底炸出这么大的回响,是因为它击穿了一条所有人默认可信的安全假设:
"我只是读一个 setuid 文件(只读 fd),就算把它 splice 到一个内核接口去'处理',也不应该让它的内容在内存里被改写。"
而 Linux 的页缓存共享模型 + 零拷贝的"高效"哲学 + 加密子系统的 in-place 优化——三个优秀工程的叠加——恰好让这条假设崩塌了。
这也是为什么它被拿来和历史上的 Dirty COW(CVE-2016-5195) 类比,但更恶劣:Dirty COW 还要抢竞态窗口、可能 crash;Copy Fail 是直线逻辑路径,稳定、静默、可脚本化。
⚠️ 最后再强调一遍
本文对 CVE-2026-31431 的分析仅供安全研究、防御加固、授权渗透测试场景使用。如果你在自己的服务器上复现——请确保那是你自己的机器或你有书面授权。这个东西的利用门槛实在太低了(一个 Python 脚本、一个普通账号、几秒出 root),拿它碰不属于你的系统 = 刑事风险。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)