CVE-2026-31431
Linux娘救援行动 #CVE-2026-31431:Copy Fail——一个潜伏九年的内核级“内伤”
导语
有些漏洞靠竞态条件碰运气,有些漏洞需要精确的内存布局。但这一次,Linux娘的身体里被发现了一处直线逻辑缺陷——不需要竞争、不需要重试、不需要碰运气。一个短短732字节的Python脚本,就能让任何一个本地低权限用户,直接拿下root。
代号“Copy Fail”,编号CVE-2026-31431。它从2017年就潜伏在Linux内核的加密子系统里,静静等了将近九年。
一、急诊接诊:Linux娘怎么了?
2026年4月29日,安全研究团队Theori和Xint Code联合披露了一个高危本地提权漏洞。消息一出,安全圈直接炸锅——因为它的利用门槛实在太低了。
病情速览
| 项目 | 内容 |
|---|---|
| 漏洞编号 | CVE-2026-31431(CNVD-2026-19044) |
| 代号 | Copy Fail |
| CVSS评分 | 7.8(高危) |
| 漏洞类型 | 内核本地权限提升 / 容器逃逸原语 |
| 潜伏期 | 2017年8月至今(将近九年) |
| 触发条件 | 本地低权限用户,无需网络、无需root、无需特殊环境 |
| 利用难度 | 极低——732字节Python脚本,一步到位 |
这不是那种“理论上可被利用”的学术漏洞。漏洞细节和PoC已公开,安天公司已发现在野利用情况。Linux娘这次是真的在流血,不是在撒娇。
二、病因分析:三个合理的设计,拼成一场灾难
根源:2017年的一次性能优化
故事要从2017年8月说起。当时的Linux内核为了提高AEAD(带关联数据的认证加密)操作的性能,在algif_aead.c中引入了一次修改(提交72548b093ee3),让加密操作可以就地(in-place) 进行。
什么叫“就地”?简单说,算法不再把数据复制到临时缓冲区处理,而是直接在用户提供的内存区域上读写。这项优化本身没有错——它为内核省去了一次内存拷贝的开销。
但问题在于,它让页缓存(page cache)的页面直接暴露在了内核可写的路径中。
触发:authencesn的“临时草稿区”
与此同时,内核中还有一个叫authencesn的加密模板。它是为IPsec的扩展序列号(ESN)支持而设计的。在解密过程中,authencesn需要临时存放一组重排后的认证数据字节,它在接收缓冲区偏移assoclen + cryptlen的位置直接写了4个字节——相当于在计算中途随手抓了一张“草稿纸”。
在正常的加密流程中,这4字节写在算法内部的缓冲区里,无伤大雅。但当2017年的就地优化介入后,情况变了。
合体:splice()把页缓存送进了可写区
algif_aead解密时,splice()系统调用可以把数据从文件零拷贝传入内核。零拷贝意味着内核没有复制数据,而是直接在文件的页缓存页面上操作。2017年的优化又让这些页面被链入了可写的输出散列表(scatterlist)。
于是,当authencesn在解密过程中向“草稿区”写入那4个字节时——它实际上写进了被splice链入的页缓存页面。
结果:任意低权限用户,可以向任意可读文件的内核页缓存中,写入受控的4字节数据。
为什么这很可怕?
第一,它不需要竞态条件。Dirty Cow(CVE-2016-5195)需要和内核的写时复制机制赛跑,经常要重试甚至可能导致系统崩溃。Copy Fail是一个确定性的逻辑缺陷——只要你按步骤来,它就一定触发。
第二,它横向可移植。同一份732字节的Python脚本,在Ubuntu、Amazon Linux、RHEL、SUSE上不经任何修改即可运行。
第三,它极其隐蔽。写入发生在页缓存(内存中的文件副本),内核从不把被破坏的页面标记为“脏页”。磁盘上的文件保持原样,所有基于磁盘校验和的完整性检测工具(如AIDE、Tripwire)全部失效。
三、影响范围:你很可能正在发烧
受影响的内核范围
72548b093ee3(2017年8月) ≤ 内核版本 < a664bf3d603d(2026年4月修复)
内核4.14至6.19.11都受影响。不受影响的版本:主线7.0+、稳定版6.18.22+、6.19.12+。
已知受影响的发行版
| 发行版 | 状态 |
|---|---|
| Ubuntu 24.04 LTS / 22.04 LTS / 20.04 LTS / 18.04 LTS | 已确认受影响 |
| Amazon Linux 2023 | 已确认受影响 |
| RHEL 10 / 9 / 8 | 已确认受影响 |
| SUSE 16 | 已确认受影响 |
| Debian / Arch / Fedora / Rocky / Alma / Oracle Linux | 同期内核版本同样受影响 |
高危场景:谁需要立即行动?
| 场景 | 风险 |
|---|---|
| 多用户共享服务器(开发机、跳板机、构建服务器) | 任意普通用户可提权为root |
| Kubernetes/容器集群 | 容器内低权限代码可提权至宿主机root,跨租户逃逸 |
| CI/CD Runner(GitHub Actions自托管、GitLab Runner、Jenkins) | 恶意PR或构建脚本可接管Runner节点 |
| 云端Notebook/代码沙箱 | 租户代码突破隔离边界 |
| PaaS/Serverless执行环境 | 用户提交代码影响宿主节点 |
对于单用户个人笔记本或不对外提供服务的单租户服务器,直接风险相对较低,但若攻击者通过Web漏洞或SSH爆破获得低权限shell,Copy Fail将立即把低权限升级为root。
四、急诊处置:先止血、再治病
Step 1:快速诊断(30秒)
# 1. 检查内核版本
uname -r
# 2. 检查AF_ALG AEAD模块配置状态
grep CONFIG_CRYPTO_USER_API_AEAD /boot/config-$(uname -r)
结果解读:
| 配置值 | 含义 | 风险 | 措施 |
|---|---|---|---|
=n | 彻底关闭,不受影响 | 无风险 | 无需处理 ✅ |
=y | 静态编译进内核,lsmod查不到 | 受影响,无法通过卸载模块缓解! | 必须升级内核 |
=m | 模块方式加载,可动态卸载 | 模块加载即受影响 | 可通过卸载模块临时缓解 |
RHEL/CentOS/Rocky/AlmaLinux 8、9、10三代产品均为=y,静态编译进了内核,这是最麻烦的情况。
Step 2:临时止血——禁用模块(仅适用于=m的情况)
# 卸载已加载的模块
sudo rmmod algif_aead 2>/dev/null
# 阻止模块被重新加载
echo "install algif_aead /bin/false" | sudo tee /etc/modprobe.d/disable-algif-aead.conf
# 验证缓解效果
python3 -c 'import socket; s=socket.socket(38,5,0); (s.bind(("aead", "authencesn(hmac(sha256),cbc(aes))")) or print("未缓解")) if s else None' 2>/dev/null || echo "已缓解"
如果输出“已缓解”,说明止血成功。如果输出“未缓解”,说明你的内核是=y编译的,必须走升级路线。
注意:禁用algif_aead对绝大多数系统没有可感知的影响。该模块主要用于用户态直接调用内核加密接口(如IPsec工具),大部分服务器并不依赖它。
Step 3:容器环境额外加固
容器共享宿主机的内核,一个容器被攻破后可以利用Copy Fail提权到宿主机。在无法立即升级宿主机内核的情况下,通过seccomp阻断容器内AF_ALG socket的创建是最有效的防御:
{
"syscalls": [
{
"names": ["socket"],
"action": "SCMP_ACT_ERRNO",
"args": [
{
"index": 0,
"value": 38,
"op": "SCMP_CMP_EQ"
}
]
}
]
}
将上述配置应用到容器的seccomp profile中,即可在容器层面阻断Copy Fail的利用链,即使宿主机内核未打补丁。
Step 4:根治——升级内核
官方修复补丁已合并入主线(commit a664bf3d603d),各大发行版正在陆续推送更新。
# Ubuntu/Debian
sudo apt update && sudo apt upgrade -y
# RHEL/CentOS/Rocky/AlmaLinux
sudo dnf update -y
# SUSE
sudo zypper patch
# 升级后重启,务必!
sudo reboot
安全版本确认:升级后再次运行诊断命令,确认内核版本。安全版本为包含commit a664bf3d603d的内核。
各发行版安全公告跟踪
- Ubuntu:
https://ubuntu.com/security/CVE-2026-31431 - Debian:
https://security-tracker.debian.org/tracker/CVE-2026-31431 - Red Hat:
https://access.redhat.com/security/cve/cve-2026-31431 - SUSE:
https://www.suse.com/security/cve/CVE-2026-31431.html
五、复盘:为什么这次特别值得记录?
它与Dirty Cow/Dirty Pipe的不同
| 特性 | Dirty Cow (2016) | Dirty Pipe (2022) | Copy Fail (2026) |
|---|---|---|---|
| 需要竞态条件 | 是 | 部分需要 | 否 |
| 跨发行版通用 | 需要调整 | 需要调整 | 是 |
| 利用脚本大小 | 编译型exploit | 编译型exploit | 732字节Python |
| 隐蔽性(绕过磁盘校验) | 一般 | 一般 | 极高 |
| 容器逃逸能力 | 有限 | 有限 | 是 |
三个时间点,同一个内核,同一个页缓存攻击面。每隔几年就有一个“史诗级”漏洞从页缓存这个方向冒出来。这提醒我们,内核在性能优化和数据完整性之间,仍然存在需要持续审视的地带。
AI辅助发现漏洞的时代来了
这次Copy Fail是由Theori研究院Taeyang Lee使用AI安全扫描工具Xint Code发现的。近几个月AI辅助发现的漏洞数量激增,安全防御的节奏正在被AI加速。攻击者在用AI,防御者也要用AI——谁能更快地自动化漏洞发现和修复,谁就能占得先机。
诊断与修复速查卡
| 步骤 | 命令 | 期望结果 |
|---|---|---|
| 1. 查版本 | uname -r | 确认是否在受影响范围 |
| 2. 查配置 | grep CONFIG_CRYPTO_USER_API_AEAD /boot/config-$(uname -r) | =n → 安全;=y → 必须升级;=m → 可临时缓解 |
| 3. 查模块 | lsmod | grep algif | 空 → 模块未加载,低风险 |
| 4a. 临时止血 | sudo rmmod algif_aead | 仅=m有效 |
| 4b. 容器加固 | 配置seccomp阻止family=38的socket | 阻断容器利用路径 |
| 5. 根治 | sudo apt/dnf update && sudo apt/dnf upgrade -y | 升级至包含补丁的内核版本 |
| 6. 重启 | sudo reboot | 新内核加载 |
| 7. 验证 | 重复步骤1,确认内核版本 ≥ 安全版本 | 安全 ✅ |
结语
Linux娘这次的内伤,潜伏了将近九年才被发现。但它也完美印证了我们这个系列的开篇信条:Linux娘从来不无缘无故发脾气。
内核崩溃是出了问题,不崩溃不代表没问题。Copy Fail从2017年引入到2026年被发现,从未触发过一次内核崩溃、从未产生过一行错误日志。它安安静静地躺在加密子系统里,等一个会使用AF_ALG socket的低权限用户来敲门。
这次的教训是多重的:内核的性能优化需要更审慎的安全审查;传统的磁盘完整性校验已不足以检测页缓存层面的篡改;对于多租户环境,及时的安全更新比过去任何时候都更紧迫。
好在Linux娘不会藏私——漏洞详情公开、补丁公开、PoC公开(供防御方验证用)。每一条通往修复的路都被清清楚楚地标了出来。她总是这样,把病因写在病历里,只要你愿意读。
下一章见。
《Linux娘救援行动》是一个专门收录奇奇怪怪Linux故障的急诊记录系列。每一次翻车、每一次报红、每一次看似不讲道理的罢工,都藏着一个清晰的原因和一条通往救赎的路径。