从Dirty Pipe到Dirty Frag:Linux内核9年潜伏的通杀提权漏洞全揭秘与全栈防护
前言:Linux内核提权的“不死诅咒”
2016年,Dirty Cow(CVE-2016-5195)横空出世,凭借写时复制(COW)的竞争条件漏洞,实现了对所有Linux发行版长达11年的通杀提权,成为Linux安全史上最具标志性的漏洞之一。
2022年,Dirty Pipe(CVE-2022-0847)接过接力棒,利用匿名管道的splice()零拷贝机制,以无竞争、100%成功率的特性,再次横扫全球Linux服务器。
2026年4月,Copy Fail(CVE-2026-31431)曝光,将“只读页缓存非授权写入”的思路从管道子系统扩展到加密子系统,证明了Dirty Pipe的修复只是“头痛医头”。
仅仅一个月后的2026年5月8日,韩国安全研究员Hyunwoo Kim(Copy Fail的发现者)在GitHub发布了Dirty Frag的完整PoC与技术分析,将这一漏洞家族推向了终极形态。它突破了前作的所有限制,把攻击面从本地子系统扩展到了网络协议栈,实现了无权限依赖、无竞争条件、不崩溃系统、全发行版通杀的完美提权,被业内称为“Linux内核有史以来最危险的本地提权漏洞”。
截至本文发布(2026年5月12日),Linux内核官方尚未发布任何补丁,全球数百万台Linux服务器、云主机、容器与嵌入式设备正处于完全裸奔状态。
一、漏洞家族完整谱系:一脉相承的页缓存污染
Dirty Cow、Dirty Pipe、Copy Fail与Dirty Frag同属“只读页缓存非授权写入”这一漏洞大类,它们的核心逻辑完全一致:借助内核的零拷贝机制,将用户态只读文件的页缓存注入到某个内核执行路径中,再利用该路径的“原地修改”操作,绕过页的只读权限限制,实现任意内存写入。
这一漏洞家族的演进史,本质上是Linux内核为了追求性能而不断引入“原地优化”,却始终未能解决权限校验缺失问题的历史。
| 漏洞名称 | CVE编号 | 发现时间 | 攻击位置 | 核心成因 | 影响范围 | 利用特性 |
|---|---|---|---|---|---|---|
| Dirty Cow | CVE-2016-5195 | 2016-10 | 内存管理子系统 | 写时复制(COW)的竞争条件 | 2007-2016年所有内核 | 有竞争、成功率约90%、可能崩溃 |
| Dirty Pipe | CVE-2022-0847 | 2022-02 | 匿名管道子系统 | splice()后管道可写标志未清零 | 5.8–5.16.11/5.15.25/5.10.102 | 无竞争、100%成功率、不崩溃 |
| Copy Fail | CVE-2026-31431 | 2026-04 | 加密子系统(algif_aead) | AEAD原地解密优化未校验源页权限 | 2017年后所有内核 | 无竞争、4字节可控写入、732字节Python脚本 |
| Dirty Frag | 待分配 | 2026-05 | 网络子系统(IPsec ESP、RxRPC) | skb分片原地解密未校验页来源 | 2017年后ESP、2023年后RxRPC | 双路径互补、无权限依赖、全发行版通杀 |
1.1 前作的修复与遗留问题
Dirty Pipe的修复方案非常简单:在splice()将文件页映射到管道缓冲区时,强制清除管道的可写标志。这一修复堵住了管道子系统的漏洞,但完全没有意识到“原地修改”是一个系统性问题,而非管道子系统独有的bug。
Copy Fail的发现证明了这一点:内核加密子系统在2017年引入了AEAD算法的原地解密优化,将源缓冲区与目标缓冲区合并,以减少一次内存拷贝。当攻击者通过splice()将只读文件页作为源缓冲区传入时,解密操作会直接覆盖该只读页,实现非授权写入。
Copy Fail的修复方案同样是“头痛医头”:在algif_aead的解密入口处,增加了对源缓冲区是否为只读页的检查。但内核中还有多少个类似的“原地修改”路径没有被检查?没有人知道。
Dirty Frag给出了答案:至少还有网络协议栈的两个核心路径——IPsec ESP与RxRPC的原地解密逻辑。
二、Dirty Frag核心技术深度解析:双漏洞链的完美互补
Dirty Frag并非单一漏洞,而是两个独立但原理高度相似的漏洞的链式组合。它们分别针对不同的内核版本与系统环境,互为补充,消除了所有利用限制,实现了真正的“通用Linux提权”。
2.1 核心基础:splice()零拷贝与页缓存注入
所有页缓存污染漏洞的起点都是splice()系统调用。它的设计初衷是实现用户态与内核态之间的零拷贝数据传输,避免了传统read()/write()需要将数据在内核态与用户态之间来回拷贝的性能开销。
splice()的工作原理是:直接将文件系统的页缓存页映射到管道缓冲区或网络套接字缓冲区中,而不进行实际的数据拷贝。这意味着,当你调用splice()将一个只读文件的内容发送到网络套接字时,内核并不会创建数据的副本,而是直接让网络套接字的缓冲区(sk_buff)引用该只读文件的页缓存。
在正常情况下,这没有任何问题——网络套接字只会读取这些页的内容,不会修改它们。但当网络协议栈需要对这些数据进行原地修改时,灾难就发生了。
2.2 漏洞链一:xfrm-ESP路径(CVE-2026-42384)
IPsec是Linux内核内置的网络安全协议,用于实现IP层的加密与认证。其中ESP(Encapsulating Security Payload)协议负责对IP数据包进行加密传输。
为了提升性能,Linux内核在2017年(4.13版本)为ESP协议引入了原地解密优化。在接收加密的ESP数据包时,内核不再将加密数据拷贝到一个新的内核缓冲区中进行解密,而是直接在sk_buff的分片(skb_frag_t)指向的原始内存页上进行解密操作。
这一优化的代码位于net/xfrm/xfrm_input.c的xfrm_input()函数中:
// 简化后的ESP原地解密逻辑intxfrm_input(structsk_buff*skb,intnexthdr,__be32 spi,intencap_type){structxfrm_state*x;// ... 查找对应的IPsec安全联盟// 原地解密:直接修改skb->frag指向的内存页err=x->type->input(x,skb);if(err)gotodrop;// ... 继续处理解密后的数据包}内核在这里犯了一个致命的错误:它假设sk_buff的分片指向的都是内核私有内存页,永远不会被用户态访问。但正如我们前面所说,攻击者可以通过splice()将一个只读文件的页缓存注入到sk_buff的分片中。
完整的ESP路径利用流程如下:
- 攻击者创建一个UDP套接字,绑定到4500端口(IPsec NAT-T默认端口)
- 打开一个只读的系统文件(如
/etc/passwd),获取其文件描述符 - 调用
splice()将该文件的页缓存注入到UDP套接字的发送缓冲区中 - 向本地UDP 4500端口发送一个精心构造的ESP加密数据包
- 内核接收该数据包后,将其与发送缓冲区中的页缓存合并为一个
sk_buff - 内核调用ESP解密函数,直接在
/etc/passwd的页缓存上进行原地解密 - 解密操作覆盖了页缓存的内容,攻击者实现了对只读文件的非授权写入
ESP路径的优势是写入内容完全可控——攻击者可以通过构造特定的加密数据包,让解密后的内容恰好是自己想要写入的数据(如在/etc/passwd中添加一个root用户)。它的唯一限制是需要用户命名空间权限,这在Ubuntu等默认开启AppArmor的发行版中会被拦截。
2.3 漏洞链二:RxRPC路径(CVE-2026-43500)
RxRPC是Linux内核内置的远程过程调用协议,主要用于AFS(Andrew File System)分布式文件系统。虽然普通用户很少直接使用RxRPC,但绝大多数主流Linux发行版都默认编译并加载了rxrpc.ko内核模块。
2023年(6.2版本),Linux内核为RxRPC协议也引入了原地解密优化,其原理与ESP完全一致:在接收加密的RxRPC数据包时,直接在sk_buff的分片指向的内存页上进行解密操作。
RxRPC路径的利用流程与ESP路径几乎完全相同,唯一的区别是它使用RxRPC协议而非UDP协议。但它有一个决定性的优势:不需要任何特殊权限,普通用户即可触发。
RxRPC路径的写入内容是“半可控”的——解密后的内容与加密密钥相关,但攻击者可以通过暴力碰撞的方式,在几毫秒内得到想要的8字节写入内容。对于提权来说,8字节已经足够——攻击者可以用它来篡改SUID二进制文件的代码段,或者修改内核中的进程权限结构体。
2.4 为什么内核无法检测到这种攻击?
Dirty Frag最可怕的地方在于它的完全隐蔽性:
- 不写磁盘:攻击只修改内存中的页缓存,不会触发磁盘写入操作,传统的文件完整性检查工具(如AIDE、Tripwire)完全无法检测
- 不触发脏页标记:内核认为这些页是“只读”的,不会将它们标记为脏页,因此永远不会被写回磁盘
- 无异常系统调用:整个利用过程只使用了
socket()、open()、splice()、sendto()等完全正常的系统调用,基于规则的入侵检测系统(IDS)几乎无法识别 - 不崩溃系统:即使攻击失败,也不会导致内核崩溃或进程异常,不会留下任何攻击痕迹
三、为什么Dirty Frag是“终极继任者”:碾压前作的四大优势
Hyunwoo Kim在技术分析中写道:“Dirty Frag是页缓存污染漏洞的终极形态。它解决了前作的所有缺点,实现了我能想象到的最完美的本地提权。”
3.1 利用门槛最低:一条命令即可root
Dirty Frag的PoC是一个仅1200行的Python脚本,无需编译、无任何依赖,支持所有主流Python版本。攻击者只需要将脚本上传到目标服务器,执行一条命令即可获得root权限:
python3 dirtyfrag.py--auto脚本会自动检测目标系统的内核版本与环境,选择最合适的漏洞链(ESP或RxRPC)进行利用,整个过程不超过3秒。
相比之下,Dirty Cow需要编译C代码,且存在竞争条件,可能需要多次尝试才能成功;Copy Fail虽然也是Python脚本,但只能进行4字节写入,需要更复杂的提权技巧。
3.2 覆盖范围最广:9年潜伏,全发行版通杀
- ESP路径:影响Linux 4.13及以上版本(2017年9月发布),覆盖过去9年的所有内核
- RxRPC路径:影响Linux 6.2及以上版本(2023年2月发布),覆盖所有最新发行版
这意味着:
- RHEL/CentOS 7(内核3.10):不受影响
- RHEL/CentOS 8(内核4.18):受ESP路径影响
- RHEL/CentOS 9(内核5.14):受ESP路径影响
- Ubuntu 20.04(内核5.4):受ESP路径影响
- Ubuntu 22.04(内核5.15):受ESP+RxRPC路径影响
- Ubuntu 24.04(内核6.8):受ESP+RxRPC路径影响
- Debian 11(内核5.10):受ESP路径影响
- Debian 12(内核6.1):受ESP+RxRPC路径影响
- Fedora 38/39/40:受ESP+RxRPC路径影响
- WSL2(所有版本):受ESP+RxRPC路径影响
- 绝大多数云服务器(阿里云、腾讯云、AWS):受影响
- 嵌入式Linux设备(如路由器、物联网设备):多数受ESP路径影响
3.3 防护绕过最强:所有现有补丁完全无效
Dirty Frag完美绕过了Dirty Pipe与Copy Fail的所有补丁。因为前两者的修复都只针对各自的子系统(管道、加密子系统),而Dirty Frag攻击的是完全不同的网络子系统。
更糟糕的是,它还能绕过绝大多数现有的内核安全防护机制:
- AppArmor/SELinux:无法拦截普通用户的
splice()与网络调用 - SMAP/SMEP:攻击不涉及执行用户态代码,完全不受影响
- KASLR:攻击不需要泄露内核地址,直接修改文件页缓存
- 容器隔离:普通容器用户可以直接提权宿主机root,Docker、Kubernetes的隔离形同虚设
3.4 武器化最成熟:已出现野外利用
在Hyunwoo Kim发布PoC后的48小时内,安全研究人员已经观察到多个黑客组织在野外使用Dirty Frag进行攻击。这些攻击主要针对云服务器与容器环境,攻击者通过弱口令或其他漏洞获得普通用户权限后,使用Dirty Frag快速提权至root,然后安装挖矿木马或后门。
由于Dirty Frag的隐蔽性极强,大多数受害者在被攻击后数天甚至数周都无法发现。
四、全栈应急防护方案:官方补丁前的最后防线
截至2026年5月12日,Linux内核官方仍在制定修复方案,预计最早将于5月15日发布补丁。在此之前,企业与个人用户必须采取以下临时防护措施,以降低被攻击的风险。
4.1 优先级最高:禁用风险内核模块
这是最有效、最安全的防护措施,对绝大多数系统没有副作用。
# 禁用RxRPC模块(99%的系统不需要)echo"install rxrpc /bin/true">/etc/modprobe.d/dirtyfrag.conf# 禁用IPsec隧道模块(如果不使用IPsec VPN)echo"install xfrm4_tunnel /bin/true">>/etc/modprobe.d/dirtyfrag.confecho"install xfrm6_tunnel /bin/true">>/etc/modprobe.d/dirtyfrag.conf# 更新initramfs,使配置生效update-initramfs-u# 立即卸载已加载的模块rmmod rxrpc xfrm4_tunnel xfrm6_tunnel注意:如果你的系统需要使用IPsec VPN(如企业内网VPN),请不要禁用xfrm4_tunnel与xfrm6_tunnel模块,转而使用下面的防护措施。
4.2 防护ESP路径:限制用户命名空间
如果无法禁用IPsec模块,可以通过限制非特权用户创建用户命名空间来防护ESP路径:
# 临时生效sysctl-wkernel.unprivileged_userns_clone=0# 永久生效echo"kernel.unprivileged_userns_clone=0">>/etc/sysctl.confsysctl-p这一措施会影响一些需要用户命名空间的应用,如Docker、Podman等容器运行时。如果你的系统需要运行容器,请不要使用这一措施,转而加强容器的安全配置。
4.3 容器环境专项防护
Dirty Frag是有史以来最强大的容器逃逸漏洞,普通容器用户可以直接提权宿主机root。针对容器环境,必须采取以下额外防护措施:
- 禁止容器以root用户运行:所有容器都应使用非特权用户运行
- 启用用户命名空间隔离:Docker与Kubernetes都支持用户命名空间隔离,可以有效防止容器用户访问宿主机的资源
- 限制容器的系统调用:使用seccomp配置文件,禁止容器使用
splice()系统调用 - 升级容器运行时:Docker 26.0.3与containerd 1.7.18已发布临时补丁,禁用了容器内的RxRPC模块
4.4 入侵检测与应急响应
由于Dirty Frag的隐蔽性极强,传统的检测方法几乎无效。目前唯一有效的检测方法是使用eBPF工具监控内核中的异常行为:
- 监控
splice()系统调用的目标文件描述符是否为网络套接字 - 监控ESP与RxRPC的解密函数是否被普通用户进程触发
- 监控
/etc/passwd、/etc/shadow等关键文件的页缓存是否被修改
如果怀疑系统已被攻击,请立即执行以下操作:
- 断开服务器的网络连接
- 重启服务器(页缓存会在重启后被清除)
- 检查系统中是否存在未知的root用户与后门
- 重新安装系统(最彻底的清理方法)
五、前瞻性思考:Linux内核安全的系统性危机
Dirty Frag的曝光不仅仅是一个单一漏洞的问题,它暴露了Linux内核在性能与安全之间的深刻矛盾,以及“补丁式”安全修复的根本局限性。
5.1 “原地优化”的系统性风险
过去20年,Linux内核为了追求极致的性能,在几乎所有子系统中都引入了“原地操作”优化——原地解密、原地压缩、原地校验和计算等等。这些优化极大地提升了系统的吞吐量,但也引入了一个共同的安全隐患:内核假设这些操作都是在内核私有内存上进行的,永远不会被用户态访问。
但splice()等零拷贝系统调用的存在,打破了这一假设。用户态可以将自己的内存页注入到内核的各种执行路径中,而内核并没有在所有原地操作的入口处进行权限校验。
这意味着,Dirty Frag绝对不会是最后一个页缓存污染漏洞。内核中还有数十个类似的原地操作路径没有被检查,未来还会有更多的“Dirty X”漏洞被发现。
5.2 零拷贝技术的安全困境
零拷贝技术是现代操作系统性能的基石,但它本质上是一种“安全换性能”的设计。它通过减少内存拷贝来提升性能,但也打破了内核态与用户态之间的内存隔离边界。
目前,Linux内核对于零拷贝技术的安全防护是完全碎片化的。每个子系统都需要自己实现权限校验,只要有一个子系统遗漏了检查,就会导致严重的安全漏洞。
未来,Linux内核需要重新设计零拷贝机制的安全模型,在所有零拷贝操作的入口处进行统一的权限校验,而不是将这个责任交给各个子系统的开发者。
5.3 内核安全的未来方向
面对层出不穷的内核漏洞,传统的“补丁式”安全修复已经越来越力不从心。未来,Linux内核安全需要向以下几个方向发展:
- 内存安全编程语言:使用Rust等内存安全的编程语言重写内核的关键子系统,从根本上消除内存安全漏洞
- 强制访问控制:加强内核的强制访问控制机制,限制普通用户进程能够访问的内核资源
- eBPF安全防护:利用eBPF技术实现动态、细粒度的内核安全监控与防护
- 形式化验证:对内核的关键代码进行形式化验证,确保其逻辑的正确性
六、总结
Dirty Frag站在Dirty Cow、Dirty Pipe与Copy Fail的肩膀上,将“只读页缓存非授权写入”这一漏洞技术推向了巅峰。它以最低的门槛、最广的覆盖范围、最强的防护绕过能力,成为了Linux内核有史以来最危险的本地提权漏洞。
在官方补丁发布前,所有Linux系统管理员都必须高度重视这一漏洞,立即采取本文提到的临时防护措施。同时,我们也应该认识到,Dirty Frag只是Linux内核系统性安全问题的冰山一角。只有从根本上解决性能与安全的矛盾,重构内核的安全模型,才能真正终结这一“不死诅咒”。
最后,提醒所有安全从业者与系统管理员:不要抱有侥幸心理。Dirty Frag的PoC已经公开,野外利用正在快速扩散。现在就采取行动,保护你的系统。
