一、漏洞概述
CVE-2026-31431,代号 Copy Fail,是 Linux 内核加密子系统中的一个逻辑缺陷漏洞,由韩国安全公司 Theori 旗下 Xint Code 团队研究员 Taeyang Lee 借助 AI 安全扫描工具 Xint Code 发现,并于 2026 年 4 月 29 日公开披露。该漏洞存在于 algif_aead 加密模板的 authencesn 解密路径中,攻击者无需竞争条件即可稳定触发 4 字节受控页缓存写入,从而篡改 setuid 二进制文件(如 /usr/bin/su)的内存副本,实现本地权限提升。
核心特性:
| 属性 | 说明 |
|---|---|
| CVSS 3.1 评分 | 7.8(高危) |
| 影响范围 | 2017 年以来几乎所有主流 Linux 发行版 |
| 利用条件 | 本地非特权用户(或容器内代码执行权限) |
| 是否需要竞争条件 | 否 |
| 是否为内存破坏型漏洞 | 否,属于直线型逻辑错误(straight-line logic bug) |
| 公开 PoC | 732 字节 Python 脚本,仅使用标准库模块 |
受影响的发行版包括:Ubuntu、Amazon Linux、Red Hat Enterprise Linux、SUSE、Debian、Arch Linux、Fedora、Rocky Linux、Alma Linux、Oracle Linux 等。
二、漏洞根本原因
该漏洞的根源在于 三个独立的内核变更的交叉组合,每个变更加单独来看均无问题,但三者结合即产生可利用条件:
- 2017 年的性能优化(commit
72548b093ee3):algif_aead.c将 AEAD 解密操作从 out-of-place 切换为 in-place,即req->src = req->dst,使输入和输出共用同一 scatterlist。当用户通过splice()将文件数据导入 AF_ALG 套接字时,该 scatterlist 持有对内核页缓存(page cache)的直接引用,而非私有副本。 authencesn加密模板的 scratch space 行为:crypto_authenc_esn_decrypt()在检测到src == dst时,将目标缓冲区当作就地缓冲区处理,并于解密过程中在dst[assoclen + cryptlen]处写入 4 字节 scratch 数据(用于 ESN 字节重排),写入位置超出正式声明的输出边界。此写入发生在标签验证(返回-EBADMSG)之前,因此即使解密失败,页缓存已遭破坏。- AF_ALG 套接字接口与
splice()系统调用:非特权用户可通过socket(AF_ALG, ...)创建加密套接字,再通过splice()将任意可读文件的页面零拷贝导入套接字的发送 scatterlist,从而实现攻击者可控的 4 字节页缓存写入原语。
三、漏洞复现方法
(1)目标系统要求
- Linux 发行版:2017 年后发布的主流版本(建议直接在某验证版本的发行版上测试,例如 Ubuntu 24.04 LTS、Amazon Linux 2023、RHEL 14.3、SUSE 16 等);
- 内核版本:commit
72548b093ee3≤ commit <a664bf3d603d(即 kernel 4.14 至 7.0-rc7 之前的版本); - 内核需启用
CONFIG_CRYPTO_USER_API_AEAD(默认多数发行版均已启用,可正常加载algif_aead模块); - 允许非特权用户创建 AF_ALG 套接字。
(2)环境确认命令
# 检查内核版本
uname -r
# 检查 algif_aead 模块是否可用
lsmod | grep algif_aead || modinfo algif_aead
# 确认 AF_ALG 套接字可创建
python3 -c "import socket; s = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0); print('AF_ALG OK')"(3)准备测试环境
创建普通用户账号进行测试:
sudo user add -m testuser
sudo su - testuser
id # 确认当前为普通用户,uid 非 0
(4)获取执行 PoC 脚本
PoC 已由 Theori 官方公开在 GitHub:
git clone https://github.com/theori-io/copy-fail-CVE-2026-31431.gitcd copy-fail-CVE-2026-31431
chmod +x copy_fail_exp.pypython3 copy_fail_exp.py
预期结果:脚本执行完毕后弹出 root shell(# 提示符)。可通过 id 命令确认已提权。
四、修复建议
4.1 根本修复:升级内核
官方主线内核已于 commit a664bf3d603d 中完成修复,核心措施为撤销 2017 年的 in-place 优化(即 commit 72548b093ee3),将 algif_aead 回退到 out-of-place 操作模式。各发行版的安全版本如下:
| 发行版 | 修复状态 | 安全版本/补丁 |
|---|---|---|
| Debian (forky) | 已修复 | 6.19.13-1 |
| Debian (sid) | 已修复 | 6.19.14-1 |
| Ubuntu | 已发布安全更新 | 参照 Ubuntu Security |
| RHEL 8/9/10 | 修复推迟中 | 见 Red Hat 安全公告 |
| SUSE | 受影响 | 安全更新待发布 |
| Amazon Linux | 修复待定 | 关注 AWS 安全公告 |
内核升级执行示例:
# Debian/Ubuntu
sudo apt update &&sudo apt upgrade
# RHEL/CentOS
sudo yum update kernel
# 手动编译主线内核
git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
git checkout a664bf3d603d
升级完成后必须重启系统以加载新内核。
4.2 临时缓解措施
在无法立即升级内核的场景下,可采用以下临时缓解方案,按优先级排列:
方案一:禁用 algif_aead 内核模块(推荐)
# 立即卸载模块
sudo rmmod algif_aead
# 持久化禁用(创建黑名单配置文件)
echo "blacklist algif_aead" | sudo tee /etc/modprobe.d/blacklist-algif_aead.conf
# 更新 initramfs 使配置在重启后生效
sudo update-initramfs -u
Theori 团队明确指出,禁用 algif_aead 模块对绝大多数系统不会产生可测量的功能影响。
方案二:阻断非特权用户创建 AF_ALG 套接字
通过 seccomp 过滤器限制非特权进程对 socket(AF_ALG, ...) 的访问:
# 使用 seccomp 限制(通过容器运行时或 systemd 单元配置)
# Docker 示例 —— 在容器启动时添加 seccomp 配置文件:
docker run --security-opt seccomp=af_alg_deny.json ...
其中 af_alg_deny.json 需对 socket 系统调用添加 AF_ALG(family=38)的拒绝规则。
方案三:容器/沙箱环境额外加固
- 在 Kubernetes 中通过 PodSecurityPolicy 或 seccomp 限制 AF_ALG 套接字创建;
- 在容器运行时层面屏蔽
splice()与 AF_ALG 的组合使用; - CI/CD 构建环境、多租户平台及沙箱执行环境中务必限制不受信任代码的内核子系统交互权限。
4.3 风险场景优先级
以下场景应立即排查并优先修复:
| 风险场景 | 风险说明 |
|---|---|
| Kubernetes / 容器平台 | 容器内代码可通过共享页缓存逃逸至宿主机,突破容器隔离边界 |
| 自托管 CI Runner | 恶意 Pull Request、构建脚本、依赖投毒可转化为 Runner 节点完全接管 |
| 多用户 Linux 主机 | 任意普通用户可提升为 root |
| 云端 Notebook / 代码沙箱 | 租户代码可能突破隔离边界 |
| PaaS / Serverless 执行环境 | 用户提交代码可影响宿主节点 |
| 堡垒机 / 跳板机 / 开发机 | 低权限账号失陷后可扩大至系统完全控制 |

JiaXu's Blog