不久前 Copy Fail 刚刚曝光,Linux 又迎来了一个新的重磅安全漏洞:Dirty Frag。

与 Copy Fail 类似,Dirty Frag 也利用了 零拷贝 的特性来篡改普通用户只有读权限的文件,但它作用的 Linux 模块有所不同。

同样地,如果修改 /usr/bin/su,攻击者就能够获取 root 权限。

几乎所有主流 Linux 发行版都受影响,而且该漏洞从 2017 年就已经存在。

更可怕的是,这次漏洞在官方尚未正式修复之前,就已经被第三方公开披露,这意味着 Linux 社区目前还没有可用的补丁来防护该漏洞。

演示

Dirty Frag 的 PoC 可以在 GitHub 上找到:

https://github.com/V4bel/dirtyfrag

我在 Ubuntu 24.04 上测试了这个 PoC,成功获取了 root 权限:

原理

Dirty Frag 属于与 Dirty Pipe 和 Copy Fail 同一类的漏洞。然而,Dirty Pipe 是覆盖 struct pipe_buffer,而 Dirty Frag 则是覆盖 struct sk_buff 的 frag。

在 Copy Fail 中,攻击者使用 splice(file -> pipe -> AF_ALG_fd) 将一个攻击者固定的 page cache 页植入 TX SGL。
在 recv() 内部,TX SGL 的最后 4 个字节(tag)会被分离到 areq->tsgl 并通过 sg_chain 链接到 RX SGL 的末尾。
调用 aead_request_set_crypt(req, src=RX, dst=RX) 决定使用原地模式(in-place mode),而 scatterwalk_map_and_copy(tmp+1, dst, assoclen+cryptlen, 4, 1) 会执行一次 4 字节的 seqno_lo 临时写操作到 dst 的末尾,作为字节重排的一部分。
在正常的 IPsec 路径下,该位置是 skb 的 tag 区,因此写入是无害的。但当攻击者固定的 page 被放置在该位置时,原有假设就被破坏了。

Dirty Frag 是一种漏洞,其攻击模式可以在源自 splice 的非线性 skb 的 frag 上复现。

xfrm-ESP Page-Cache 写入:esp_input 绕过 skb_cow_data,直接在 frag 上运行 crypto_authenc_esn_decrypt。
RxRPC Page-Cache 写入:rxkad_verify_packet_1 使用 pcbc(fcrypt) 在 frag 上进行原地单块解密。

需要注意的是,Dirty Frag 的触发不依赖于 algif_aead 模块是否可用。换句话说,即使在应用了已知 Copy Fail 缓解措施(如 algif_aead 黑名单)的系统上,你的 Linux 仍然可能受到 Dirty Frag 的攻击。

Page Cache (/usr/bin/su 或 /etc/passwd)skb (frag → page cache)RxRPC SubsystemXFRM/ESP SubsystemLinux KernelNamespace / SyscallsAttacker (User Space)Page Cache (/usr/bin/su 或 /etc/passwd)skb (frag → page cache)RxRPC SubsystemXFRM/ESP SubsystemLinux KernelNamespace / SyscallsAttacker (User Space)创建隔离用户/网络命名空间 🔒攻击者控制加密参数 🗝️将用户文件映射到内核skb 📦skb frag 直接指向目标页缓存 ⚠️内存页面固定,直接修改可能覆盖关键文件 📝原地解密,修改页缓存数据 🔧4-byte STORE 写入控制偏移 → 文件覆盖 💥攻击者控制 RxRPC 会话密钥 🔑解密写入,8-byte STORE 覆盖目标文件 💣alt[ESP Page-Cache 写入变体 (xfrm-esp)][RxRPC Page-Cache 写入变体]重复分块写入重建完整 payload (last-write-wins) 🔄unshare(CLONE_NEWUSER|CLONE_NEWNET)1register XFRM SA (控制 seq_hi、keys、ESN)2vmsplice + splice (file → pipe → socket)3build skb with frag pointing to page cache page P4page cache page pinned into skb frag (无复制)5send UDP packet (ESP over UDP encap)6esp_input()7skip skb_cow_data (非线性 + 无 frag_list)8in-place crypto_authenc_esn_decrypt()9scatterwalk_map_and_copy()10page cache modified (/usr/bin/su ELF 或 /etc/passwd)11add_key(rxrpc, session_key = K)12establish rxrpc connection (handshake)13vmsplice + splice (伪造 rxrpc 包)14skb frag points to page cache page P15send rxrpc DATA packet16rxkad_verify_packet_1()17skb_to_sgvec() (frag 上原地映射 sg)18crypto_skcipher_decrypt(pcbc(fcrypt))19in-place decrypt write20page cache modified (/etc/passwd 或目标文件)21execve("/usr/bin/su")22获得 root shell via 修改 setuid 二进制或 PAM 绕过 🥷23

如何缓解

因为负责任披露(responsible disclosure)的时间表和保密期(embargo)已经被打破,目前任何发行版都不存在补丁。请使用以下命令卸载存在漏洞的模块并清理 page cache。

sh -c "printf 'install esp4 /bin/false\ninstall esp6 /bin/false\ninstall rxrpc /bin/false\n' > /etc/modprobe.d/dirtyfrag.conf; rmmod esp4 esp6 rxrpc 2>/dev/null; echo 3 > /proc/sys/vm/drop_caches; true"

执行了上述命令之后,攻击文件将无法成功执行:

wgxls@server:/tmp/dirtyfrag$ ./exp 
dirtyfrag: failed (rc=1)