Xint Code 披露了 CVE-2026-31431,一个存在于 Linux 内核认证加密子系统中的严重漏洞。它让无特权用户只需运行一个小小的 Python 脚本,就能在所有主流 Linux 发行版上拿到 Root。
这个漏洞之所以与众不同,在于它不需要任何竞态条件或时序技巧,是一个"直线型逻辑缺陷"——同一份未经修改的利用脚本,可以不加任何适配地直接跑在 Ubuntu、Amazon Linux、RHEL 和 SUSE 上。
漏洞背景
与 Dirty Cow、Dirty Pipe 的区别
过去十年里,Dirty Cow(2016)和 Dirty Pipe(2022)是 Linux 提权漏洞里最广为人知的两个名字。它们都依赖竞态条件:攻击者需要精确抢占内核执行窗口,成功率受环境影响,复现也更复杂。
CVE-2026-31431 走的是另一条路。它是一个确定性逻辑漏洞,不依赖时序,不需要反复重试,每次执行路径都是一样的。这直接决定了它的利用脚本可以做到极度精简,同时兼容多个发行版。
受影响版本
在以下环境验证可成功利用:
| 发行版 | 内核版本 |
|---|---|
| Ubuntu 24.04 LTS | 6.17.0 |
| Amazon Linux 2023 | 6.18.8 |
| RHEL 10.1 | 6.12.0 |
| SUSE 16 | 6.12.0 |
根因:AF_ALG + splice + authencesn
漏洞的核心在于三个内核机制的组合:AF_ALG socket、splice() 和 authencesn AEAD 算法。
AF_ALG 是什么
AF_ALG 是 Linux 内核提供的一种特殊 socket 类型,作用是把内核的加密函数暴露给用户空间。应用程序可以通过它调用硬件加速加密,而不用把数据拷贝到用户态再处理。
splice() 的语义
splice() 的设计目标是在两个文件描述符之间零拷贝传输数据。它传递的是页缓存页面的引用,而不是数据副本。正是这个"传引用"的设计,把问题引了进来。
authencesn 的 scratch 写入
authencesn 是一种 AEAD(认证加密)算法,在解密过程中需要一块临时工作区。它会把 4 个字节写入目标缓冲区偏移 assoclen + cryptlen 的位置,用作中间计算的暂存空间。
2017 年,内核引入了一项优化,让 AEAD 操作可以原地进行(in-place)——即源缓冲区与目标缓冲区共用同一块内存,省去额外拷贝。
三者叠加之后,漏洞路径就打通了:
- 用户通过
splice()把文件(比如/usr/bin/su)的页缓存页面"喂"给 AF_ALG socket - 由于原地优化,这些页缓存页面直接落入 authencesn 的可写目标 scatterlist
- 解密触发时,authencesn 把 4 字节的 scratch 数据写进了真实的页缓存
- HMAC 校验失败,操作报错,但那 4 字节已经写进去了
- 关键一点:内核的 writeback 机制从未把这个被改动的页面标记为 dirty,文件完整性检查因此失效
利用路径
攻击流程的核心步骤如下:
1. 打开 AF_ALG socket,绑定到 authencesn 算法
2. 构造 sendmsg() 调用,控制写入的 4 字节内容
(利用 ESN 扩展序列号字段)
3. 用 splice() 把 /usr/bin/su 的页缓存页面作为"密文"传入
4. 触发解密,authencesn 将受控字节写入页缓存
5. 执行被改写后的 su,借助其 setuid 权限获得 Root
整个利用脚本只使用 Python 标准库,体积 732 字节。
为什么"脏页"检测失效
这是这个漏洞最精妙也最危险的地方。
通常,内核会通过 dirty page 标记来追踪哪些页面被改动过,进而决定是否回写到磁盘、是否触发 fsync 相关的完整性检查。Dirty Pipe 也利用过类似机制。
但 CVE-2026-31431 走的路径恰好绕过了这个标记机制:authencesn 的 scratch 写入发生在 AEAD 内部处理流程中,属于"中间计算副作用",内核的 writeback 子系统从未介入,页面始终显示为"干净"。这意味着:
- 文件系统层面看不到改动
- IMA(Integrity Measurement Architecture)等完整性机制可能无法检出
- 被修改的 setuid 二进制正常执行,没有任何异常信号
修复方案
补丁的思路直接针对根因:将 AF_ALG AEAD 操作从原地模式(in-place)回退为非原地模式(out-of-place)。
具体做法是把源 scatterlist 与目标 scatterlist 分离,确保页缓存页面永远不会进入 authencesn 的可写目标 scatterlist,scratch 写入也就不再能触及实际文件内容。
这个修复代价很小——放弃 2017 年那个原地优化——但彻底切断了攻击路径。
临时缓解措施
在内核补丁可用之前,可以采取以下措施降低风险:
- 通过 seccomp 策略阻止
AF_ALGsocket 的创建 - 卸载或禁用
algif_aead内核模块:modprobe -r algif_aead - 限制对
splice()相关系统调用的访问(影响范围较大,需评估)
发现过程
这个漏洞由 Theori 研究员 Taeyang Lee 发现。他判断 AF_ALG + splice() 是一个值得深挖的可疑攻击面,随后借助 Xint Code 的自动化分析能力,重点关注页缓存来源(page cache provenance),在大约一小时内定位到了这个漏洞。
这个漏洞很好地说明了一件事:内核中的性能优化(原地 AEAD)和零拷贝机制(splice 传引用)在组合之后,可能产生任何一方单独都不会引发的安全问题。漏洞不一定藏在复杂的代码里,有时候它就在两个"各自正确"的设计之间的缝隙里。
目前 Xint Code 还预告了 Part 2,将覆盖 Kubernetes 容器逃逸场景,届时攻击面会进一步扩大。
关于
关注我获取更多资讯
原文:Copy Fail: 732 Bytes to Root on Every Major Linux Distribution,作者 Xint Code,本文为编译整理,许可协议 CC BY-SA 4.0。