4 个字节拿到 root 权限:Linux 内核漏洞"Copy Fail"与 Cloudflare 的应急处置全记录

先说结论

2026 年 4 月 29 日,一个 Linux 内核本地提权漏洞被公开披露,代号"Copy Fail",编号 CVE-2026-31431。Cloudflare 的安全团队和工程团队在漏洞披露后立即开始评估。最终结论是:Cloudflare 环境未受任何影响,客户数据没有风险,服务没有中断。

这篇博客的价值,在于完整记录了从漏洞披露到全面防护,48 小时内发生的所有事情------既包括漏洞本身的技术细节,也包括应急响应的每一个决策节点。


漏洞背景:内核加密模块里藏了 9 年的定时炸弹

Cloudflare 的内核更新节奏

Cloudflare 运营着遍布全球 330 个城市的 Linux 服务器基础设施,维护基于 Linux 长期支持(LTS)版本的自定义内核。社区定期合并安全和稳定性更新,这会触发一个自动化任务,大约每周生成一个新的内部内核构建版本。构建完成后,经过预生产数据中心测试,再通过"边缘重启发布(ERR)"流水线,按四周为一个周期对边缘基础设施进行系统性更新和重启。

通常情况下,当一个 CVE 被公开披露时,所需的修复补丁已经在稳定的 Linux LTS 版本中集成了数周,Cloudflare 的既有流程已经完成了部署。但"Copy Fail"是个例外------漏洞披露时,主线修复已经存在一个月,但尚未被回移(backport)到 Cloudflare 主要使用的 6.12 LTS 版本。

这意味着:按照正常流程,Cloudflare 大量服务器在漏洞披露的那一刻,仍处于暴露状态。


漏洞原理:一次 4 字节越界写入是如何造成提权的?

这个漏洞的技术链条相当精巧,涉及三个相互独立的内核机制,缺一不可。

第一层:AF_ALG------用户态的内核加密通道

Linux 内核的内部加密 API 管理 kTLS、IPsec 等功能。用户态程序通过 AF_ALG 套接字族访问这套 API,允许非特权进程请求加密或解密操作。algif_aead 模块专门用于处理带关联数据的认证加密(AEAD)算法。

简单来说,就是操作系统提供了一个接口,让普通程序也能使用内核里的加密能力------这个接口,就是这次漏洞的入口。

第二层:页缓存------操作系统的全局文件共享内存

页缓存(Page Cache)是操作系统用于缓存文件内容的共享系统缓存。修改一个属于 setuid 二进制文件的页,实际上就是在为所有用户编辑该程序,直到这个页被驱逐为止。

这意味着:如果某个攻击者能够修改 /usr/bin/su 这类 setuid-root 程序在内存中的缓存副本,那么下一次任何用户运行这个程序时,执行的就是被篡改过的版本。

第三层:越界写入------2017 年优化留下的后门

内核加密 API 使用 scatterlist(一种将多个内存页链接在一起的数据结构)。2017 年,algif_aead 模块为了性能优化,实现了就地操作,把目标页和引用页链接在一起。这个设计缺乏约束,无法阻止算法向预期边界之外写入数据。

当用户调用 recvmsg() 时,内核中的 authencesn 包装器会在合法输出区域之外执行一次 4 字节写入:

c 复制代码
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1);

通过 splice() 系统调用,攻击者可以将目标文件的页缓存页链接到 scatterlist 中。越界写入随后会污染缓存中的文件,攻击者可以控制被修改的文件、偏移量,以及具体写入的 4 个字节------通过 sendmsg() 中的 AAD 字节 4-7 来控制写入的内容。

完整的利用链:五步拿到 root

默认的攻击目标是 /usr/bin/su,这是一个几乎每个 Linux 发行版都有的 setuid-root 二进制文件。

攻击分五步完成:

第一步,填充页缓存 :以只读方式打开 /usr/bin/su 并读取,将其内容载入内核页缓存,再通过 splice() 把这些页缓存引用传入加密的 scatterlist 中。

第二步,建立 AF_ALG 套接字 :创建 AF_ALG 套接字,绑定到 authencesn(hmac(sha256),cbc(aes)) 算法,设置密钥,接受请求套接字------全程无需任何特权。

第三步,构造写入内容 :对每 4 字节的 shellcode,通过 sendmsg() 控制写入内容,通过 splice() 控制写入位置。

第四步,触发越界写入 :调用 recvmsg() 触发解密操作。authencesn 将其暂存数据写入 /usr/bin/su 在页缓存中的目标偏移位置。虽然函数返回 -EBADMSG,但 4 字节已经写入全局页缓存。

第五步,执行 :运行 execve("/usr/bin/su") 加载被污染的页缓存。由于这个二进制文件是 setuid-root 的,注入的 shellcode 以 root 权限执行。


Cloudflare 的应急响应:五条工作线并行推进

漏洞披露后,Cloudflare 的安全和工程团队立即启动了多条并行工作线:评估暴露范围、验证检测覆盖、主动溯源威胁狩猎、工程缓解,以及继续推进软件更新。

工作线一:验证现有检测能否识别这次攻击

安全团队做的第一件事,是确认现有的端点检测能否捕获这个漏洞的利用行为。Cloudflare 的服务器运行行为检测系统,持续监控进程执行模式------它不依赖已知漏洞的签名,而是基于整个机队的行为模式判断异常。

当工程师在内部授权的验证测试中复现漏洞时,检测平台在几分钟内就发出了告警。系统完整地还原了整个执行链------从脚本解释器开始,经过内核加密子系统,到特权提升二进制文件,基于机队范围的行为模式将其标记为恶意行为。

这个过程没有更新签名,没有修改规则,也没有人工干预。这一确认至关重要------在编写任何针对这个漏洞的专项规则之前,团队就已经有了检测覆盖能力。

工作线二:溯源狩猎------证明"未被利用"

Cloudflare 对严重漏洞的处理原则是:在能够证明无影响之前,假设已被攻击。

团队在集中日志基础设施中搜索漏洞利用的特征痕迹,覆盖漏洞公开披露前 48 小时的数据。随后拉取受影响系统的访问日志,重建所有连接、时间和执行命令的完整记录。同时核验系统二进制文件未被篡改,通过密码学哈希与已知良好的软件包清单比对,检查持久化机制,审计网络连接。最终,一切均无异常。

工作线三:寻找无需重启的缓解方案

内核补丁的正常更新流程需要数周,而漏洞已经公开。团队开始同步寻找不依赖重启的运行时缓解方案。


缓解方案选型:为什么最简单的那个不能用?

方案一:卸载 algif_aead 模块(被否)

漏洞在 algif_aead 模块里,最直接的做法是卸载它:

bash 复制代码
echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif.conf
rmmod algif_aead 2>/dev/null || true

这正是"Copy Fail"漏洞研究人员在披露文章中推荐的缓解方式。

但 Cloudflare 测试后发现,卸载模块会影响依赖内核加密 API 的软件。这意味着需要找到一种更精准的缓解方式。第一次尝试将缓解推送到预生产数据中心时,暴露了一个依赖冲突,变更被回滚------好在这发生在内部测试环境,没有影响任何生产系统。

方案二:bpf-lsm 精准封堵(采用)

Cloudflare 此前已经为类似场景开发并部署过 bpf-lsm 这个工具。它不卸载模块,而是通过 BPF Linux Security Module 程序,在 socket_bind LSM 钩子上拒绝未授权进程的绑定请求,让合法用户继续正常使用,同时对其他所有人关闭前门。

程序逻辑很清晰:

每次 socket_bind 调用发生时:若套接字族不是 AF_ALG,直接放行;若是 AF_ALG,则检查调用方二进制文件的路径是否在白名单上;若在白名单,放行,否则拒绝。


部署 bpf-lsm:先看清楚,再动手

这里有一个工程细节值得单独讲。

在启用 bpf-lsm 的拦截之前,团队需要先确认整个机队里到底有哪些程序在合法使用 AF_ALG 接口------如果白名单不完整,防护会误伤正常服务。

团队使用 prometheus-ebpf-exporter 钩住 socket() 系统调用,按二进制文件追踪整个机队的 AF_ALG 使用情况。这不需要任何内核变更,在数小时内就从数十万台服务器收集到了汇总数据。结果确认,只有一个已知的内部服务是唯一合法的 AF_ALG 使用者。

有了这个可见性数据,bpf-lsm 的部署分两步走:

第一步,先建立可见性 :推送 ebpf-exporter 配置,在指标层确认已知服务确实是唯一创建 AF_ALG 套接字的进程。第二步,再执行拦截:将 bpf-lsm 程序推送到独立的执行闸门后面。

这个"先看清楚、再动手"的顺序,避免了因为白名单不完整而导致的误操作。


完整事件时间线

时间(UTC) 事件
4月29日 16:00 Copy Fail 公开披露
4月29日 ~21:00 安全与工程团队开始评估暴露情况和缓解选项
4月29日 22:52 确认现有行为检测覆盖 Copy Fail 的利用模式,内部验证几分钟内触发告警
4月29日 23:01 行为检测生成高严重性告警,确认对该技术的检测能力
4月29日(晚) 第一次缓解尝试推送至预生产数据中心,发现依赖冲突后回滚,未影响生产系统
4月29日(连夜) 工程师起草 bpf-lsm 缓解程序
4月30日 03:14 正式宣布安全事件,驱动跨团队协作;安全团队完成全机队历史数据威胁狩猎,确认无恶意活动
4月30日(上午) bpf-lsm 缓解程序测试完成,具备生产就绪条件
4月30日 14:25 宣布工程事件,协调缓解程序和内核补丁的推出
4月30日 ~17:00 决策确定:通过重启自动化推送已修复内核;期间依靠 bpf-lsm 提供保护
4月30日(下午) eBPF 可见性管道(追踪 AF_ALG 套接字使用情况)部署至全机队
4月30日(晚) bpf-lsm 缓解程序完成全机队部署;在此前存在漏洞的测试节点上端到端验证,确认漏洞不再可利用
5月4日(上午) 重启自动化以正常速度恢复运行,携带修复后的内核
5月4日起 已完成早期重启的服务器手动重启以获取补丁;其余服务器按正常重启自动化流程更新

事后复盘:三个改进方向

Cloudflare 在事后识别出三个改进方向:更好的内核 API 依赖关系可见性------持续梳理生产服务对内核子系统的使用情况,使后续缓解能够更快做出精准决策而不影响服务;更好的 bpf-lsm 运行时缓解能力------包括更快的部署流程、更完善的操作手册、更好的日志和可见性;以及减少 Linux 内核的攻击面------审计内核配置,主动识别并从构建中移除未使用的模块或功能。


总结

这篇博客表面是一次安全事件的事后复盘,实际上展示了几件更深层的东西。

漏洞本身的技术启示:一个 2017 年为了性能做的内核优化,9 年后变成了一个允许任意用户以 root 身份执行代码的提权路径。漏洞的每一层------AF_ALG 接口、页缓存的全局共享特性、scatterlist 的越界写入------单独看都不是问题,组合在一起就是一条完整的攻击链。这再次说明,安全问题往往不在于单点的错误,而在于机制之间意料之外的交互。

应急响应的方法论:Cloudflare 对关键漏洞的处理原则是"在证明无影响之前假设已被攻击",从这个假设出发系统性地排除,而不是乐观地假设没事。这种"默认担忧"的工作模式,是大规模基础设施安全运营的基本态度。

工具优先于规则:bpf-lsm 在漏洞披露之前就已经存在并且可用,行为检测在漏洞披露之前就已经能够识别利用模式。负责任的披露有效,内核可见性工具的投入在这样的时刻得到了回报,bpf-lsm 仍然是运行时内核缓解最有价值的工具之一。

对于在生产环境中大规模运营 Linux 系统的团队,这篇事件记录是一份不可多得的参考材料。


参考来源:Cloudflare Blog --- "How Cloudflare responded to the 'Copy Fail' Linux vulnerability"

相关推荐
智驭未来掌门人19 小时前
利用FFmpeg快速实现一个RTSP推流服务器
后端
垚垚学技术_聚焦云原生19 小时前
K8s Pod 完整生命周期详解
后端
JavaGuide19 小时前
Github 史诗级故障,与此同时,Cursor 版「GitHub」正式上线!
前端·后端
不一样的少年_19 小时前
修了 Bug、做了重构,为什么老板还是觉得你没产出?
前端·后端·程序员
水深火乐19 小时前
安全地生成验证码、密码和 Token
后端
小强198820 小时前
SQL Server 慢查询怎么定位?一套从“卡”到“快”的完整排查流程
后端
水深火乐20 小时前
interface和any
后端
步行cgn20 小时前
MyBatis Error evaluating expression ‘ids‘. Return value (3) was not iterable 错误详
java·后端
神奇小汤圆20 小时前
Spring Boot + LangChain4j实现RAG——从零搭建企业级知识库问答系统
后端
H_Peak20 小时前
Python运算符与流程控制:if条件判断
后端