针对 DirtyFrag (CVE-2026-43284) 的实验室检测练习 - 通过 xfrm-ESP 页面缓存破坏实现 Linux 内核权限提升。完整文档涵盖漏洞利用执行、检测盲区以及使用 Elastic Stack 修正后的 EQL 规则。
分类: 内部实验室 - CyberLAB
日期: 2026年5月24日
平台: Elastic Stack v9.4.1
状态: 检测已确认
一个受控的利用练习,模拟一个使用 DirtyFrag (CVE-2026-43284)(一个Linux内核权限提升漏洞)的后初始访问攻击者。模拟的攻击者场景:通过钓鱼凭证获得的低权限用户(saskia,uid=1001)试图在内部Linux主机上提权至root。实验室使用了一台故意配置了漏洞的Ubuntu机器(ubuntu-vuln,内核6.0.0-22-generic),与生产网络隔离。
攻击者在实验室环境中获得了完全的root访问权限(uid=0)。Elastic Security检测栈生成了 3条高严重性告警(风险评分73),正确识别了利用链。然而,检测需要手动调整——默认配置存在漏洞,否则会导致告警遗漏。
底线: 运行内核 <= 6.x 的未打补丁的Linux主机存在漏洞。如果攻击者已经拥有低权限立足点,该漏洞利用会悄悄且快速地授予他们完全的root权限,且不会在磁盘上留下文件完整性工具可检测到的痕迹。
auditd规则不会产生任何证据。 如果没有为socket、splice和unshare设置明确的系统调用规则,漏洞利用会静默运行——没有日志,没有告警。默认的Elastic Agent部署不会自动添加这些规则。process.parent.pid作为关联键。在实践中,DirtyFrag会fork中间进程,破坏该关联。修复方法——通过auditd.session进行关联——在本练习中被识别并实施。/etc/shadow,访问了SSH授权密钥,写入了持久化标记(/root/pwned.txt),并通过nc发起了网络侦察。所有这些都发生在初始访问后的30分钟内。目标: 验证家庭实验室SOC中针对DirtyFrag利用的检测覆盖率,识别检测差距,并根据观察到的攻击者行为生成修正后的检测规则。
威胁模型: 模拟一个使用钓鱼凭证获得低权限用户账户(saskia,uid=1001)的后初始访问攻击者。目标:通过DirtyFrag利用xfrm-ESP接收路径实现权限提升至root。实验室执行通过Proxmox控制台进行——功能上等同于SSH后访问。
考虑了两个攻击者能力层级:
本次练习涵盖了普通层级。
DirtyFrag是系列相关Linux内核漏洞中的第三个,它们都利用相同的根本原因:
根本原因: IPv4/IPv6数据报追加路径在skb_splice_from_iter()将页缓存页植入套接字缓冲区(sk_buff)后,未设置SKBFL_SHARED_FRAG。然后ESP输入路径对攻击者控制的页缓存页执行了就地加密,将其视为普通的未克隆的非线性skb。
利用原语: 向页缓存写入4或8字节的控制数据。确定性——不需要竞争条件。
利用链:
/usr/bin/su)读入页缓存splice()构造一个数据包,使文件的页面位于struct sk_buff的frag[0]中xfrm-ESP解密路径execve()——都会返回被篡改的字节关键的规避特性: 磁盘上的文件从未被修改。文件完整性监控工具(AIDE、Tripwire、哈希检查)都报告目标文件是干净的。
已确认受影响的发行版: Ubuntu 24.04.4、RHEL 10.1、AlmaLinux 10、openSUSE Tumbleweed、CentOS Stream 10、Fedora 44。
练习时的活跃遥测:
实验室网络在练习前已隔离。防火墙别名Cyber_escape_door确认已禁用——防止横向移动到其他VLAN或互联网。

在ubuntu-vuln上确认了有漏洞的内核和低权限账户:```
saskia@ubuntu-vuln:$ uname -r
6.0.0-22-generic
saskia@ubuntu-vuln:$ whoami
saskia
saskia@ubuntu-vuln:~$ id
uid=1001(saskia) gid=1001(saskia) groups=1001(saskia),27(sudo),100(users)

#### 4.3 栈健康检查
**Suricata:正在运行并捕获流量(systemctl status)**

**Kibana/Elasticsearch:绿色/健康(API 检查)**

**在变更前拍摄的虚拟机快照**



#### 4.4 网络捕获
在 Suricata 主机上启动 tcpdump(`emp6s19`,抓包长度 262144 字节),用于完整捕获 `172.66.66.27` 的流量。


---
### 5. 第二阶段 - 漏洞利用执行
#### 5.1 暂存
来自 V4bel/dirtyfrag PoC 的漏洞利用源码(`exp.c`)已暂存到受害者主机上。```bash
ubuntu-vuln@ubuntu-vuln:~/dirtyfrag$ ls
exp exp.c README.md
ubuntu-vuln@ubuntu-vuln:~/dirtyfrag$ cp exp.c /tmp/exp/
右侧终端显示了用户 saskia 可见的暂存副本。

通过 sudo gcc 以 root 身份编译(用户 saskia 在 sudoers 中):```
saskia@ubuntu-vuln:$ sudo gcc -o /tmp/exp/clean_frag /tmp/exp/exp.c
saskia@ubuntu-vuln:$ ls -la /tmp/exp/
-rwxr-xr-x 1 root root 62320 May 24 12:18 clean_frag
-rw-rw-r-- 1 ubuntu-vuln ubuntu-vuln 67803 May 24 12:13 exp.c
saskia@ubuntu-vuln:~$ id
uid=1001(saskia) gid=1001(saskia) groups=1001(saskia),27(sudo),100(users)
二进制:ELF 64位LSB可执行文件,x86-64,动态链接。

#### 5.3 执行 - 获取Root权限
漏洞以 `saskia`(uid=1001)身份执行。进程(`clean_frag`,pid=4326)打开了 `AF_RXRPC` 和 `AF_ALG` 套接字,然后调用 `splice()` 将页面缓存页植入网络缓冲区。ESP路径上的原位加密将攻击者控制的字节写入页面缓存。子进程(pid=4327)调用 `unshare`,参数 `a0=50000000`(`CLONE_NEWUSER | CLONE_NEWNET`),以获取命名空间级能力。```
saskia@ubuntu-vuln:~$ /tmp/exp/clean_frag
...
root@ubuntu-vuln:~# id
uid=0(root) gid=0(root) groups=0(root)
root@ubuntu-vuln:~# ls
在 12:22 CEST (10:22 UTC), 2026年5月24日 获得完整的root shell。
捕获的Auditd系统调用序列(UTC):
所有事件共享 auditd.session=2。

所有操作均以 root 身份在 ubuntu-vuln 上执行,从 ~12:22 CEST 开始。
root@ubuntu-vuln:# echo "Dirty Frag PoC executed at $(date)" > /root/pwned.txt
root@ubuntu-vuln:# cat /root/pwned.txt
Dirty Frag PoC executed at Sun May 24 12:28:05 PM CEST 2026

#### 6.2 凭据访问```bash
root@ubuntu-vuln:~# cat /etc/shadow | head -2
root:*:19823:0:99999:7:::
daemon:*:19823:0:99999:7:::
root@ubuntu-vuln:~# cat /home/ubuntu-vuln/.ssh/authorized_keys
ssh-ed25519 AAAA[...]
shadow文件和SSH授权密钥被访问。在实际入侵中,这将导致离线密码破解和持久的SSH后门访问。

root@ubuntu-vuln:~# nc -vz 172.66.66.1 100-8000
对实验网关(`172.66.66.1`,端口100-8000)的端口扫描,于12:51 CEST从root上下文执行。这展示了横向移动能力以及从提权会话进行的网络映射。

#### 6.4 Suricata网络可见性
Suricata在整个练习窗口中捕获了与`172.66.66.27`相关的**105个事件**(88个mdns,17个flow)。在截图拍摄时(约为12:53 CEST的nc扫描期间),仪表板中可见29个事件。
DirtyFrag漏洞本身是内核内部的,不产生网络签名——该提权原语不会在线路上产生异常流量。启用Suricata是为了收集利用后流量和枚举尝试的pcap,而不是为了检测漏洞本身。
| 事件类型 | 计数 |
| ---------- | ----- |
| mdns | 88 |
| flow | 17 |
| **总计** | **105** |
flow事件集中在nc端口扫描窗口期间(10:50-11:10 UTC / 12:50-13:10 CEST)。

---
### 7. 阶段4 - 检测工程
#### 7.1 已部署的检测规则
基于Elastic Security Labs的文章,在Kibana检测引擎中创建了两条EQL序列规则。
**规则1 - AF_RXRPC或AF_ALG套接字使用splice后跟执行**(未触发——见下文差距)```eql
sequence with maxspan=60s
[any where host.os.type == "linux" and
(
(event.category == "process" and auditd.data.syscall == "socket"
and auditd.data.a0 in ("26", "21")) or
(event.category == "process" and auditd.data.syscall == "splice") or
(event.category == "network" and event.action == "bound-socket"
and data_stream.dataset == "auditd_manager.auditd"
and auditd.data.socket.family == "38")
)
and user.id != "0"] by process.pid, host.id, user.id with runs=10
[process where host.os.type == "linux" and event.action == "executed" and
(
(user.effective.id == "0" and user.id != "0") or
(process.name in ("bash", "sh", "zsh", "dash", "fish", "ksh", "busybox")
and process.args in ("-c", "--command", "-ic", "-ci", "-cl", "-lc",
"-bash", "-sh", "-zsh", "-dash", "-fish", "-ksh"))
)] by process.parent.pid, host.id, user.id
规则 2 - 命名空间操纵后权限提升 (在修复后触发)```eql sequence by host.id, auditd.session with maxspan=30s [process where host.os.type == "linux" and auditd.data.syscall == "unshare" and auditd.data.a0 in ("10000000", "50000000", "70000000", "10020000", "50020000", "70020000") and user.id != "0" and user.id != null] [process where host.os.type == "linux" and user.id == "0" and user.id != null and (process.name in ("bash", "sh", "zsh", "dash", "fish", "ksh", "su", "sudo", "pkexec", "busybox", "mksh") or process.name like ("python*", "perl*", "ruby*", "php*", "lua*"))]
#### 7.2 初始检测缺口 - 缺失的系统调用覆盖
规则1返回零结果。`ubuntu-vuln`上的默认auditd配置仅捕获了:`write`、`bpf`、`openat`、`unshare`。
缺失:`socket`、`splice`、`bind`——核心利用原语。
**补救措施:** 已添加到 `/etc/audit/rules.d/dirtyfrag.rules`:```
-a always,exit -F arch=b64 -S socket -k socket_syscall
-a always,exit -F arch=b32 -S socketcall -k socket_syscall
-a always,exit -F arch=b64 -S splice -k splice-syscall
-a always,exit -F arch=b32 -S splice -k splice-syscall
-a always,exit -F arch=b64 -S unshare -k unshare-syscall
-a always,exit -F arch=b32 -S unshare -k unshare-syscall
272 个新的 auditd 事件在漏洞利用运行后的几秒内就出现在 Elasticsearch 中。
尽管事件被捕获,规则 2 仍返回 0 个匹配。
根本原因 - 实际进程树 (来自 Elasticsearch):
原始规则通过 process.parent.pid 进行关联。unshare 事件的 ppid=4326,但 root shell 具有不同的父进程——DirtyFrag 分叉了中间进程,破坏了关联。
修复: 通过 auditd.session 进行关联。漏洞利用链中的所有事件共享 session=2,正确连接了序列,无论分叉深度如何。
3 个高严重性告警,风险评分 73,位于 Kibana Security - Alerts,时间 2026-05-24T10:25:57Z UTC(12:25:57 CEST)。
| 告警 | 时间戳 (UTC) | 信号 |
|---|---|---|
| 序列匹配 - unshare 事件 | 10:25:57.869 | process=clean_frag, user=saskia (uid=1001) |
| 序列匹配 - root shell | 10:25:57.881 | process=bash, user=root (uid=0) |
| 复合序列告警 | 10:25:57.893 | host=ubuntu-vuln |
DirtyFrag - Namespace Manipulation Followed by Privilege Escalationubuntu-vuln

| 战术 | 技术 |
|---|
所有与 dirtyfrag 相关的 auditd 事件:```kql data_stream.dataset: "auditd_manager.auditd" and auditd.summary.how: dirtyfrag
**非root用户的命名空间操作:**```kql
data_stream.dataset: "auditd_manager.auditd" and auditd.data.syscall: "unshare" and auditd.data.a0: "50000000"
同一会话中提权后的root活动:```kql data_stream.dataset: "auditd_manager.auditd" and user.id: "0" and auditd.session: "2"
**漏洞利用窗口期间的所有auditd事件:**```kql
data_stream.dataset: "auditd_manager.auditd" and @timestamp >= "2026-05-24T10:20:00Z" and @timestamp <= "2026-05-24T10:30:00Z"
来自利用进程的套接字和拼接系统调用:```kql data_stream.dataset: "auditd_manager.auditd" and auditd.summary.how: "/tmp/exp/clean_frag"
---
### 9. 关键发现总结
| # | 发现 | 严重性 | 修复状态 |
| - | ---- | ------ | -------- |
| 1 | 默认的 auditd 规则遗漏了 `socket`、`splice`、`unshare`——没有明确规则就没有证据 | 严重 | 是 - 已将自定义规则部署到 `/etc/audit/rules.d/dirtyfrag.rules` |
| 2 | 通过 `process.parent.pid` 进行的 EQL 关联在分叉的利用链中失败 | 高 | 是 - 已更改为 `auditd.session` |
| 3 | 文件完整性监控对 DirtyFrag 盲视——磁盘上的文件全程未改变 | 高 | 否,在范围内未修复 - 修复方法是修补内核 |
| 4 | 后渗透:影子文件、SSH 密钥和网络侦察均在警报驱动响应之前以 root 身份执行 | 高 | 通过 auditd 日志检测到;未触发针对凭据访问或侦察阶段的专用规则 |
---
### 10. 参考文献
- Elastic Security Labs: [Copy Fail and DirtyFrag: Linux Page Bugs in the Wild](https://www.elastic.co/security-labs/copy-fail-dirtyfrag-linux-page-bugs-in-the-wild)
- 公开 PoC: [V4bel/dirtyfrag on GitHub](https://github.com/V4bel/dirtyfrag)
- MITRE ATT&CK: [T1068 - Exploitation for Privilege Escalation](https://attack.mitre.org/techniques/T1068/)
- MITRE ATT&CK: [TA0004 - Privilege Escalation](https://attack.mitre.org/tactics/TA0004/)
- MITRE ATT&CK: [T1003.008 - /etc/passwd and /etc/shadow](https://attack.mitre.org/techniques/T1003/008/)
| 项目 | 详情 |
|---|
| 漏洞 | DirtyFrag - CVE-2026-43284 (xfrm-ESP路径), CVE-2026-43500 (RxRPC路径) |
| CVSS影响 | 完全本地权限提升至root |
| 受影响的内核 | Linux内核 >= 2017年1月 (9年生命期) |
| 受影响的发行版 | Ubuntu 24.04.4, RHEL 10.1, AlmaLinux 10, openSUSE, CentOS Stream 10, Fedora 44 |
| 文件完整性绕过 | 磁盘文件不变 - AIDE、Tripwire、哈希监控均报告干净 |
| 公开PoC | 可用 (GitHub上的V4bel/dirtyfrag) |
| 提权时间 | 从低权限立足点 < 10分钟 |
| 优先级 | 操作 |
|---|
| 立即 | 在所有主机上将Linux内核修补到已修复版本。应用Ubuntu、RHEL、AlmaLinux、openSUSE、CentOS、Fedora的供应商安全公告。 |
| 短期 | 在所有由Elastic Agent监控的Linux主机上为socket、splice和unshare部署明确的auditd系统调用规则。 |
| 短期 | 更新EQL检测规则,对于命名空间操作序列,使用auditd.session而非process.parent.pid进行关联。 |
| 持续 | 将风险评分 >= 73的权限提升告警视为高优先级分类。当前规则在提权后数秒内触发。 |
| CVE | 昵称 | 引入时间 | 路径 |
|---|
| CVE-2022-0847 | Dirty Pipe | - | pipe |
| CVE-2026-31431 | Copy Fail | - | splice |
| CVE-2026-43284 | DirtyFrag | 2017年1月 (提交 cac2661c53f3) | xfrm-ESP |
| CVE-2026-43500 | DirtyFrag | 2023年6月 (提交 2dc334f1a63a) | RxRPC |
| 组件 | 详情 |
|---|
| Fleet Server / ELK主机 | ubuntu-tm / elk-docker - 172.66.66.30 (实验室内部) |
| Elastic Stack | v9.4.1 (Elasticsearch, Kibana, Logstash - Docker) |
| 目标(受害)主机 | ubuntu-vuln - 172.66.66.27 |
| 受害内核 | 6.0.0-22-generic (有漏洞) |
| 受害用户 | saskia - uid=1001, groups=1001(saskia),27(sudo),100(users) |
| Elastic Agent | v9.4.1 with auditbeat |
| 网络IDS | Suricata 8.0.5 on dedicated sensor |
| Kibana | http://172.66.66.30:5601 (实验室内部) |
| 数据集 | 占比 |
|---|
suricata.eve | 75.2% |
elastic_agent.fleet_server | 10.8% |
elastic_agent | 9.1% |
elastic_agent.filebeat | 1.9% |
elastic_agent.auditbeat | 1.4% |
auditd_manager.auditd | 0.5% |
system.auth | 0.2% |
system.syslog | 0.1% |
| 时间戳 (UTC) | 系统调用 | 参数 | 进程 (pid) | 用户 |
|---|
| 10:21:11.054 | unshare | a0=50000000 | clean_frag (4327) | saskia (1001) |
| 10:21:11.055 | socket | a0=21 (AF_RXRPC) | clean_frag (4326) | saskia (1001) |
| 10:21:17.403 | socket | a0=26 (AF_ALG) | clean_frag (4326) | saskia (1001) |
| 10:21:17.419 | splice | a0=4 | clean_frag (4326) | saskia (1001) |
| 10:21:17.419 | splice | a0=7 | clean_frag (4326) | saskia (1001) |
| 进程 | PID | PPID | UID | auditd.session |
|---|
| shell(saskia) | 4182 | - | 1001 | 2 |
clean_frag(主进程) | 4326 | 4182 | 1001 | 2 |
clean_frag(unshare 子进程) | 4327 | 4326 | 1001 | 2 |
bash(root) | - | 4451 | 0 | 2 |
| ID |
|---|
| 权限提升 | 利用漏洞进行权限提升 | T1068 |
| 权限提升 | 逃逸至主机 | T1611 |
| 凭据访问 | 操作系统凭据转储:/etc/passwd 和 /etc/shadow | T1003.008 |
| 发现 | 网络服务发现 | T1046 |
| 系统调用 | 参数 | 含义 |
|---|
unshare | a0=50000000 | CLONE_NEWUSER | CLONE_NEWNET |
socket | a0=26 | AF_ALG(内核加密子系统) |
socket | a0=21 | AF_RXRPC(RxRPC 路径) |
bind | socket.family=38 | AF_ALG 绑定 |
splice | - | 注入页面到网络缓冲区 |