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())绕过了 。它使用页缓存页同时作为源和目标执行。攻击者同时控制位置(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 实验环境截图:

.
├── 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 告警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 均匹配)。重启后它再次静默。这证明磁盘上的文件从未被修改。
刷新不会禁用漏洞利用程序。它只会清除被污染的页缓存。您必须单独禁用相关模块(请参阅缓解措施)。在已被利用的主机上移除已加载的模块需要重启。
Dirty Frag 对文件完整性监控不可见。检测聚焦于攻击链必须使用的系统调用原语。
detection/dirtyfrag.rules)# /etc/audit/rules.d/dirtyfrag.rules
-a always,exit -F arch=b64 -S socket -F a0=38 -F uid!=0 -k dirtyfrag_af_alg
-a always,exit -F arch=b64 -S socket -F a0=33 -F uid!=0 -k dirtyfrag_rxrpc
-a always,exit -F arch=b64 -S splice -F uid!=0 -k dirtyfrag_splice
-a always,exit -F arch=b64 -S unshare -F uid!=0 -k dirtyfrag_namespace
-w /usr/bin/su -p r -k dirtyfrag_suid_read
注意:在 Linux 上
AF_ALG = 38,AF_RXRPC = 33(参见/usr/include/bits/socket.h)。早期草稿使用了a0=21。该值不正确。AF_RXRPC 是 33,不是 21。
部署并验证:
sudo cp detection/dirtyfrag.rules /etc/audit/rules.d/
sudo systemctl restart auditd # 或:sudo auditctl -D && sudo auditctl -R /etc/audit/rules.d/dirtyfrag.rules
sudo auditctl -l
重新运行漏洞利用程序后预期的告警(按 PID 关联):
ausearch -k dirtyfrag_af_alg
ausearch -k dirtyfrag_rxrpc
ausearch -k dirtyfrag_splice
ausearch -k dirtyfrag_namespace
所有五条规则均已加载(auditctl -R,每条 CONFIG_CHANGE 的 res=1)。规则捕获了漏洞利用程序的命名空间设置:
time->Wed Aug 5 08:26:37 2026
type=PROCTITLE msg=audit(1785932797.328:592): proctitle="./exp"
type=SYSCALL msg=audit(1785932797.328:592): arch=c000003e syscall=272 success=yes exit=0 a0=50000000 a1=0 a2=0 a3=0 items=0 ppid=5198 pid=5199 auid=1000 uid=1001 gid=1001 euid=1001 suid=1001 fsuid=1001 egid=1001 sgid=1001 fsgid=1001 tty=pts2 ses=2 comm="exp" exe="/home/testuser/dirtyfrag/exp" subj=unconfined key="dirtyfrag_namespace"
解码:syscall=272(unshare),a0=50000000 等于 CLONE_NEWUSER | CLONE_NEWNET,uid=1001(非特权 testuser),comm="exp"。完整日志位于 detection/ausearch_dirtyfrag_observed.txt。
截图:ausearch 输出显示规则加载和漏洞利用事件。

完整剧本位于 reports/incident-dirtyfrag.md:执行摘要、时间线、入侵指标(IoCs)、MITRE ATT&CK 映射、遏制、根除、恢复和经验教训。
即时运行时缓解措施。对于已加载的模块,重启后不会保持生效(请参阅下方说明):
sudo mitigation/dirtyfrag_mitigation.sh
该脚本执行以下操作:
/etc/modprobe.d/dirtyfrag.conf 以阻止 esp4、esp6 和 rxrpc。它包含 blacklist 和 alias … off 行。简单的单行命令会遗漏这些行(否则按别名自动加载仍然有效)。影响: 禁用这些模块会使 IPsec VPN(ESP)和 AFS 文件系统(RxRPC)功能停止工作。
永久修复:升级到包含上游补丁的内核。或者在启动时对模块进行黑名单处理(initcall_blacklist=esp4,esp6,rxrpc)。
本仓库仅用于授权的防御性安全研究和培训。
请参阅 LICENSE。本实验仅用于您自己的隔离环境中的教育用途。请勿在未经授权测试的系统上运行 PoC。
skb_cow_data()crypto_authenc_esn_decrypt() 发出一个对 ESN 高 32 位的 STORE 操作。该值为 replay_esn->seq_hi。攻击者在 SA 注册时通过 XFRMA_REPLAY_ESN_VAL netlink 属性选择该值。| 组件 | 详情 |
|---|
| 虚拟机管理程序 | VirtualBox |
| 目标虚拟机 | Kali Linux 2026.1(快照已恢复到易受攻击状态) |
| 内核 | 6.18.9+kali‑amd64(早于 2026 年 5 月的修复版本) |
| 漏洞利用 PoC | V4bel/dirtyfrag(单个 C 文件) |
| 检测 | auditd(规则位于 detection/dirtyfrag.rules) |
reports/incident-dirtyfrag.md| 层 | 能检测到什么 | 状态 |
|---|
| auditd | AF_ALG 和 AF_RXRPC 套接字、splice、unshare、SUID 读取 | 是。已部署并验证(规则文件 detection/dirtyfrag.rules) |
| Sigma | 用于 SIEM 的系统调用模式 | 是。规则已就绪(detection/sigma/dirty_frag_exploit.yml) |
| YARA | 磁盘或内存中的 PoC 代码 | 是。规则已就绪(detection/yara/dirty_frag_exploit.yar) |
| FIM(AIDE/Tripwire) | 文件更改 | 否。盲区,因为不涉及磁盘写入 |
| 症状 | 可能原因 | 修复方法 |
|---|
./exp 打印 failed / post-write verify failed | 内核已修补(2026 年 5 月或之后) | 启动旧内核或恢复更新前的快照。使用 poc/check_vulnerable.py 重新检查 |
unshare(CLONE_NEWUSER) 返回 EPERM | 非特权用户命名空间被禁用(AppArmor 或 sysctl) | 检查 sysctl kernel.unprivileged_userns_clone。在 Ubuntu 上检查 AppArmor。Kali 默认允许 |
esp4/esp6/rxrpc 未加载 | 模块不可用 | sudo modprobe esp4 esp6 rxrpc(RxRPC 会随 socket(AF_RXRPC) 自动加载) |
su 二进制文件"已修补"但没有 root shell | drop_caches 已运行,或页缓存被进程固定 | 重新运行漏洞利用程序。如果卡住,重启虚拟机 |
| 漏洞利用已运行,但缓解后仍可获得 root | 页缓存未刷新,或模块在黑名单之前已加载 | echo 3 > /proc/sys/vm/drop_caches。彻底停止需要重启 |