前阵子,有人发现了一个 Linux 的大漏洞:一个很小的 Python 脚本,能让普通用户直接拿到 root。这个漏洞叫 Copy Fail,不知道大家有没有刷到过。
消息上说它的打击面很广,不少主流发行版都在影响范围里。更令人吃惊的是,它的触发门槛很低:只需要一个普通用户权限,既不用猜内核偏移,也不用反复赌时机。
我起初是半信半疑的。因为安全漏洞的标题总喜欢把“一个脚本”“秒变 root”写得很大声,真落到自己的机器上,往往还有一串前提。
是骡子是马,拉出来溜溜。我的 Linux 内核是6.8.0-110-generic,在影响范围内,所以我直接把测试脚本拉了下来执行:
python3 copy_fail_exp.py但是报错无法执行,我一查发现问题是没有加载algif_aead这个问题模块,而没有加载的原因是当前系统已经对这个漏洞进行了规避:
disable-algif_aead.conf:Disable algif_aead module due to CVE-2026-31431 (AKA copy.fail)
但这不是正式修复,因为我还没有升级内核,algif_aead 只是暂时被禁用了,所以我把 disable-algif_aead.conf 临时移动一下,就可以正常加载algif_aead了。
确认加载后,继续测试:
root@lab-vm:/home/ubuntu#哇哦,还真直接进 root 了!有点意思。
那它到底是怎么从普通用户变成 root 的?
简单说,脚本先找一个普通用户本来就能读取、但执行时会提权的程序,比如 /usr/bin/su。然后脚本不去改磁盘上的它,而是想办法改掉内存里那份副本。下一次有人执行 su 时,内核加载的是已经被动过手脚的内存内容;而 su 又带着 root 权限运行,于是普通用户就跨到了 root。
想知道脚本为什么能做到这个,需要先了解以下几个事情:
AF_ALG 是 Linux 给用户态开的一个 socket 接口,普通程序可以通过它请求内核帮忙做加密、解密。2015 年,AF_ALG 加上了 splice 零拷贝支持,它让文件的页缓存可以原封不动地进入 AF_ALG 的加密流程。
algif_aead 是 AF_ALG 里专门处理 AEAD 加密/解密请求的模块。2017 年,有人给 algif_aead 合入了一个 in-place 优化,让输入输出共享同一个 scatterlist。
authencesn 是 2011 年加入这套加密系统里的一种算法模板。它有个特殊动作:解密快结束时,会在输出数据后面额外写入 4 个字节。
至此,所有拼图都具备了,命运的齿轮开始转动:

脚本先通过 AF_ALG 发起一次解密请求,并指定使用 authencesn。AF_ALG 里的 algif_aead 模块负责把这次请求的输入和输出区域准备好,再交给 authencesn 处理。
正常情况下,authencesn 写的 4 个字节只会写进一块专门准备好的输出缓冲区。但脚本借助 splice() 把 /usr/bin/su 的页缓存直接送进了加密流程,in-place 优化则最终导致 authencesn 输出的那 4 个字节写进了 /usr/bin/su 的页缓存。
这一通绕,堪比破案。感觉就像把 3 张不相干的地图重叠在一起,在阳光下竟然出现了一条新的路线。

这个漏洞确实足够复杂,以至于我可以理解为什么整整 9 年都没有被发现。那这次是怎么发现的呢?答案是人 + AI。
Theori 团队的研究员 Taeyang Lee 凭经验锁定了攻击面(AF_ALG 加密套接字接口 + splice 零拷贝的组合),然后把扫描工作交给了自研的 AI 平台 Xint Code。AI 用了一个小时,完成了跨文件、跨子系统的语义关联分析,定位到了这个微妙的逻辑缺陷。
以后这估计是常态了,人负责提出“这里可能有问题”,AI 则负责检查这句怀疑背后的成千上万行代码。
今天的分享就到这里啦,最后提醒大家记得更新~
推荐:来玩打砖块