CopyFail本地提权漏洞影响主流Linux系统最新版(CVE-2026-31431)

admin 2026-05-02 06:25:13 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: CVE-2026-31431(CopyFail)是Linux内核高危本地提权漏洞,源于2017年AEAD优化与authencesn模块4字节越界写的组合利用,允许普通用户对系统可读文件页缓存进行可控4字节写入,进而通过修改setuid二进制提权。影响Linux4.14至7.0间所有版本,PoC已公开且可在Ubuntu、RHEL等主流发行版直接提权。修复方案需升级内核至6.18.22/6.19.12/7.0或临时禁用algif_aead模块。 综合评分: 88 文章分类: 漏洞分析,漏洞预警,解决方案,Linux安全,应急响应


cover_image

CopyFail本地提权漏洞影响主流Linux系统最新版(CVE-2026-31431)

原创

安全实验室 安全实验室

墨菲安全实验室

2026年4月30日 11:55 北京

在小说阅读器读本章

去阅读

简述

2026 年 4 月 29 日,安全研究团队 Xint Code 通过copy.fail与公司博客公开了 Linux 内核本地提权漏洞 CVE-2026-31431(代号Copy Fail)的完整技术分析,并在 GitHub 放出 732 字节的 Python PoC。该 CVE 编号实际上在 4 月 22 日已悄悄登记到 NVD,对应的主线修复 commita664bf3d603d早在大约一个月前就已合入内核,但当时并未以”本地提权漏洞”的口径对外披露。4 月 29 日 oss-security 邮件列表跟进转发后,漏洞开始大范围扩散。

PoC 在 Ubuntu 24.04 LTS、Amazon Linux 2023、RHEL 10.1、SUSE 16 等主流发行版上均直接拿到 root。

漏洞根源是 2017 年加进crypto/algif\_aead.c的一处「就地 AEAD 操作」优化(commit72548b093ee3),这条九年前的优化和早就存在于crypto/authencesn.c里的一处 4 字节越界 scratch 写互相串联,让一个普通用户能够:对系统中任何可读文件的页缓存(page cache),发起一次确定性的、可控偏移、可控内容的 4 字节写入。

页缓存被污染后,任何后续 mmap/read 这些文件的进程都会读到被改过的内容——典型攻击路径就是改写 setuid 二进制的代码段以提权。

漏洞从 4.14 内核引入,Linux 7.0 主线(commita664bf3d603d)和 6.19.12、6.18.22 两个稳定分支已修复。

图 1:copy.fail 漏洞披露页

漏洞基本信息

| 项 | 值 | | — | — | | 漏洞编号 | CVE-2026-31431 | | 别称 | Copy Fail | | 漏洞类型 | CWE-669 资源在不同领域之间的不当传输 | | CVSS 3.1 | 7.8(高危) AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H | | 漏洞等级 | 高危 | | 处置建议 | 立刻修复 | | 利用所需权限 | 本地普通用户 | | 利用条件 | 内核未禁用AF\_ALGalgif\_aead模块可加载 | | 利用成本 | 低(PoC 已公开,732 字节) | | 影响范围 | Linux 内核 4.14 起的全部版本,至 7.0 / 6.19.12 / 6.18.22 之前 | | POC | 已公开(GitHub:theori-io/copy-fail-CVE-2026-31431) | | 复现时间 | 2026.4.29 |

漏洞详细分析

这个漏洞之所以具备研究价值,是因为它由两个本身都看起来没问题的 bug 拼成。单独看每一个,maintainer 都不会认为是漏洞;放在一起就构成了一个稳定的页缓存写原语。

  1. authencesn 模板的 4 字节 scratch 写

authencesn是内核 crypto 子系统里给 IPsec 扩展序列号(ESN)用的 AEAD 包装算法。它做解密时需要把 32 位的高位序列号塞进 IV 计算,于是在crypto/authencesn.c里有一处 scratch-pad 操作:

// crypto/authencesn.c crypto_authencesn_decrypt() (节选)
// [1] 算出 tag 区域起点:assoclen + cryptlen
// [2] 把序列号低 4 字节临时写进 dst 缓冲,作为 hash 计算的一部分
scatterwalk_map_and_copy(tmp +1, dst,
assoclen + cryptlen,4,1);
// [3] 用临时拼好的数据计算 hash 并比对 tag
// [4] 验证完成后……并未把这 4 字节恢复回去

也就是说:无论解密成功还是失败,dst 缓冲区中assoclen + cryptlen偏移处的 4 字节会被永久改写为seqnolo的内容*,而seqno*lo完全由用户态可控。

这个行为本身在 IPsec 的正常调用路径里没有问题——dst 是内核临时申请的缓冲,写就写了。问题出在第二个 bug 让 dst 不再是内核临时缓冲。

  1. 2017 年那一处「就地 AEAD」优化

2017 年内核为了减少一次内存拷贝,在crypto/algif*aead.c里加了 commit72548b093ee3——当用户通过AF*ALG套接字发起 AEAD 解密时,把源 scatterlist 和目的 scatterlist 拼到一起,让算法就地处理:

// crypto/algif_aead.c _aead_recvmsg() 优化路径(简化)
// [1] AAD + 密文从发送 SGL 拷到接收缓冲
// [2] tag 页通过引用直接挂进 SGL,没有拷贝
sg_chain(rsgl, ..., tsgl);// 把 TX 的 tag 页链到 RX 上
// [3] 关键一步:让 src 与 dst 指向同一条链
req->src = req->dst;
// [4] 调下层 AEAD 算法做就地解密

正常思路下,src 和 dst 来自同一个用户进程的内存映射,就地操作是安全的。但AF\_ALG套接字可以接收来自splice()的输入——也就是说用户能用splice把任意可读文件的页缓存页直接拼进发送 SGL,而不经过拷贝:

[文件 /usr/bin/passwd 的 page cache 页]
│  splice(file_fd, pipe)
▼
[pipe buffer 持有 page cache 页的引用]
│  splice(pipe, alg_fd)
▼
[AF_ALG TX SGL 直接持有 page cache 页]
│  sg_chain → req->dst
▼
[内核把页缓存页放进了"可写目的"链表]

到这一步,内核已经把系统中任意一个可读文件的页缓存页当成了 AEAD 的可写目的缓冲。

  1. 两个 bug 的串联

接下来authencesn的解密路径被触发,它在 dst 偏移assoclen + cryptlen处写下 4 字节——而 dst 这条链的对应位置正是某个文件的页缓存页。攻击者通过控制assoclencryptlen字段决定写在哪一页的哪一位,通过控制扩展序列号决定写什么 4 字节内容。

更糟的是这次写入发生在 tag 校验之前——也就是即便后续 AEAD 校验失败、recvmsg()返回-EBADMSG,那 4 字节也已经被永久写进了页缓存。攻击者完全不需要构造合法的密文/tag。

得到的原语:对系统上任意一个本进程可读的文件,发起一次确定性的、偏移可控、内容可控的 4 字节页缓存写。

  1. 从 4 字节页缓存写到 root

页缓存写有一个特殊属性:它绕过文件权限模型。普通用户对/usr/bin/passwd没有写权限,但只要它能read()该文件,对应的物理页就已经在自己的进程里通过页缓存可达;而页缓存是全局共享的——一旦内核改写了这块物理页,之后任何进程mmap()read()同一文件时,读到的都是被污染后的内容。

攻击者只要选一个 root 拥有的 setuid 二进制(系统里有的是:/usr/bin/passwd/usr/bin/sudo/usr/bin/su等),定位到一条无害指令的偏移,用 4 字节写改成跳到自己控制的 shellcode,然后调用该 setuid 程序——内核执行的是被污染的页缓存内容,进程拥有 root 权限。

PoC 的全部代码长度是732 字节。Xint Code 在 Ubuntu 24.04 LTS(6.17.0-1007-aws)、Amazon Linux 2023(6.18.8-9.213)、RHEL 10.1(6.12.0-124.45.1.el10\_1)、SUSE 16(6.12.0-160000.9-default)上均成功提权。

修复方案

主线在 commita664bf3d603d中直接 revert 了 2017 年的就地优化,恢复成 out-of-place 操作:AAD 与密文从 TX SGL 拷贝到 RX 缓冲,src 与 dst 各自独立。这意味着即便authencesn那 4 字节越界写依然存在,目的缓冲也不会再是来自splice()的页缓存页。

// 修复后:req->src 与 req->dst 完全分离
req->src = areq->tsgl;// TX SGL:用户发来的密文
req->dst = areq->first_rsgl.sgl.sgl;// RX SGL:内核独立缓冲

修复合并到三个分支:

| 分支 | 修复 commit | 起始可用版本 | | — | — | — | | 主线 7.0+ | a664bf3d603dc3bdcf9ae47cc21e0daec706d7a5 | Linux 7.0 | | 6.19.y | ce42ee423e58dffa5ec03524054c9d8bfd4f6237 | 6.19.12 | | 6.18.y | fafe0fa2995a0f7073c1c358d7d3145bcc9aedd8 | 6.18.22 |

注意authencesn.c那个根因 4 字节 scratch 写仍未单独修复。社区认为该 scratch 写在没有 page-cache-attack 表面的前提下不算独立漏洞,但这意味着如果将来再有别的 AEAD 路径让用户态可控页面进入 dst SGL,同样的事情会重演。

影响分析

几乎所有在用的 Linux 内核都受影响。algif\_aead是绝大多数发行版默认编译进内核的模块,且 9 年间从未被任何加固方案默认关闭。

云上影响尤其大。Xint Code 的成功验证清单覆盖:

  • Ubuntu 全系(14.04 LTS 至 26.04 LTS),含linux-awslinux-azurelinux-gcplinux-gkelinux-oraclelinux-ibm等所有云厂商定制内核

  • Amazon Linux 2 / 2023

  • Red Hat Enterprise Linux 7 / 8 / 9 / 10

  • SUSE Linux Enterprise Server 12 SP5 至 16.1

  • openSUSE Leap 15.x

凡是允许多租户共用同一台 Linux 实例(共享 CI runner、Kubernetes 多租 Pod、PaaS 容器宿主、跳板机、研发用沙箱)的场景,都需要按高优先级处置——一个普通用户拿到 shell 就等于拿到 root。

容器边界并不能挡住这个漏洞。默认的 Docker / containerd 配置里AF*ALG套接字是允许的,algif*aead模块也是宿主机上加载好的;除非显式用 seccomp 拒绝socket(AF\_ALG, ...),否则容器内拿到 root 等价于宿主机内核里写一次页缓存——而页缓存是全宿主共享的,会把宿主机上的 setuid 二进制污染掉。这是典型的容器逃逸路径。

对开发者:本地开发机若运行了不受信第三方代码(构建脚本、npm install钩子、跑别人的 Docker 镜像、远程 VS Code 调试一段陌生代码),都已具备触发条件。

对安全运营团队:传统的 EDR、HIDS 通常不会把AF\_ALG套接字调用作为可疑行为告警,需要在 PoC 公开后的窗口期内主动做行为补盲。

排查与处置建议

  1. 优先升级内核

按发行版升级到包含 commita664bf3d603d/ce42ee423e58df/fafe0fa2995a0f的版本:

# Ubuntu / Debian
apt-getupdate&&apt-getinstall--only-upgradelinux-image-$(uname-r|sed's/-generic//')-generic
# Amazon Linux 2023
dnfupdatekernel
# RHEL / Rocky / Alma
dnfupdatekernel
# SUSE
zypperpatch

升级完重启,并校验:

uname-r# 确认到了已修复版本
  1. 来不及打补丁时的临时缓解

algif\_aead模块加入黑名单并卸载:

echo"blacklist algif_aead">/etc/modprobe.d/blacklist-algif_aead.conf
echo"install algif_aead /bin/false">>/etc/modprobe.d/blacklist-algif_aead.conf
modprobe-ralgif_aead

如果业务确认不依赖AF\_ALG,更彻底的做法是用 seccomp 在容器/沙箱层面直接拒绝该协议族:

# Docker / Kubernetes seccomp profile 片段
{
"syscalls": [
{
"names": ["socket"],
"action":"SCMP_ACT_ERRNO",
"args": [
{"index":0,"value":38,"op":"SCMP_CMP_EQ"}
]
}
]
}
# 38 = AF_ALG
  1. 排查是否已被利用

PoC 不会留下日志——但页缓存被污染的副作用会在重启后消失(页会被重新从磁盘读入)。因此对 7 × 24 长跑的服务器,建议:

# 检查 setuid 程序文件 hash 是否与发行版包对应
rpm-Va|grep'^..5'# RHEL 系
debsums-c# Debian 系
# 列出当前加载了 algif_aead 的进程(异常环境下应为 0)
lsof/dev/null|grep-ialg# 粗筛
  1. 长期加固

云厂商 / 自建 K8s 平台应把「禁用AF*ALG协议族」作为默认 seccomp baseline 的一部分,与禁用userfaultfdio*uring等历史多发的内核攻击面同步处理。

参考链接

  • 漏洞披露页:https://copy.fail/

  • 技术深度分析(Xint):https://xint.io/blog/copy-fail-linux-distributions

  • PoC 仓库:https://github.com/theori-io/copy-fail-CVE-2026-31431

  • NVD 条目:https://nvd.nist.gov/vuln/detail/CVE-2026-31431

  • 主线修复 commit:https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a664bf3d603dc3bdcf9ae47cc21e0daec706d7a5

  • 引入问题的旧 commit(2017):https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=72548b093ee3

  • oss-security 公告:https://seclists.org/oss-sec/2026/q2/281

  • Ubuntu 安全跟踪:https://ubuntu.com/security/CVE-2026-31431

  • SUSE 安全跟踪:https://www.suse.com/security/cve/CVE-2026-31431.html


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:墨菲安全实验室 安全实验室 安全实验室《CopyFail本地提权漏洞影响主流Linux系统最新版(CVE-2026-31431)》

评论:0   参与:  0