
Лабораторное упражнение по обнаружению DirtyFrag (CVE-2026-43284) — повышение привилегий в ядре Linux через повреждение кэша страниц xfrm-ESP. Полное описание, охватывающее выполнение эксплойта, пробелы в обнаружении и исправленные правила EQL с использованием Elastic Stack.
Классификация: Внутренняя лаборатория - CyberLAB
Дата: 24 мая 2026 г.
Платформа: Elastic Stack v9.4.1
Статус: Обнаружение подтверждено
Контролируемое упражнение по эксплуатации, моделирующее атакующего после получения начального доступа, использующего DirtyFrag (CVE-2026-43284), уязвимость повышения привилегий в ядре Linux. Сценарий моделируемого атакующего: пользователь с низкими привилегиями (saskia, uid=1001), полученный через скомпрометированные учетные данные, пытается повысить права до root на внутреннем Linux-хосте. В лаборатории использовалась намеренно уязвимая машина Ubuntu (ubuntu-vuln, ядро 6.0.0-22-generic), изолированная от производственных сетей.
Атакующий получил полный доступ root (uid=0) в лабораторной среде. Стек обнаружения Elastic Security сгенерировал 3 оповещения ВЫСОКОЙ степени серьезности (оценка риска 73), корректно идентифицирующих цепочку эксплуатации. Однако для обнаружения потребовалась ручная настройка - конфигурация «из коробки» имела пробелы, которые привели бы к пропущенным оповещениям.
Суть: Незапатченные Linux-хосты с ядром <= 6.x уязвимы. Если атакующий уже имеет точку опоры с низкими привилегиями, этот эксплойт быстро и незаметно дает ему полный root, не оставляя следов на диске, видимых для средств контроля целостности файлов.
auditd по умолчанию не дают никаких доказательств. Без явных правил системных вызовов для socket, splice и unshare эксплойт выполняется незаметно - нет журналов, нет оповещений. Развертывание Elastic Agent по умолчанию не добавляет эти правила автоматически.process.parent.pid в качестве ключа корреляции. На практике DirtyFrag порождает промежуточные процессы, нарушая эту корреляцию. Исправление - корреляция по auditd.session - было выявлено и реализовано в ходе этого упражнения./etc/shadow, получил доступ к SSH-ключам авторизации, записал маркер персистентности (/root/pwned.txt) и инициировал сетевую разведку через nc. Все это произошло в течение 30 минут после первоначального доступа.Цель: Проверить покрытие обнаружения эксплуатации DirtyFrag в домашней лабораторной SOC, выявить пробелы в обнаружении и создать исправленное правило обнаружения, основанное на наблюдаемом поведении атакующего.
Модель угрозы: Моделируемый атакующий после получения начального доступа со скомпрометированными учетными данными для учетной записи пользователя с низкими привилегиями (saskia, uid=1001). Цель: повышение привилегий до root через DirtyFrag с использованием пути приема xfrm-ESP. Выполнение в лаборатории осуществлялось через консоль Proxmox - функционально эквивалентно доступу после SSH.
Рассматривались два уровня возможностей атакующего:
Данное упражнение охватывало обычный уровень.
DirtyFrag является третьим в семействе связанных ошибок ядра Linux, которые все используют одну и ту же первопричину:
Первопричина: Пути добавления дейтаграмм IPv4/IPv6 не устанавливали флаг SKBFL_SHARED_FRAG после того, как skb_splice_from_iter() помещал страницу кэша страниц в буфер сокета (sk_buff). Затем путь ввода ESP выполнял криптографию на месте на страницах кэша страниц, контролируемых атакующим, рассматривая их как обычные не клонированные нелинейные skb.
Примитив эксплойта: Контролируемая запись размером 4 или 8 байт в кэш страниц. Детерминированный - не требуется состояние гонки.
Цепочка эксплойта:
/usr/bin/su) в кэш страницsplice(), чтобы страница файла оказалась в frag[0] структуры struct sk_buffxfrm-ESPexecve() ядра - возвращают поврежденные байтыКритическое свойство уклонения: Файл на диске никогда не изменяется. Средства мониторинга целостности файлов (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 Захват сетевого трафика
tcpdump запущен на хосте Suricata (`emp6s19`, длина снимка 262144 байта) для полного захвата пакетов трафика `172.66.66.27`.


---
### 5. Фаза 2 - Выполнение эксплойта
#### 5.1 Подготовка
Исходный код эксплойта (`exp.c`) из PoC V4bel/dirtyfrag размещён на хосте жертвы.```bash
ubuntu-vuln@ubuntu-vuln:~/dirtyfrag$ ls
exp exp.c README.md
ubuntu-vuln@ubuntu-vuln:~/dirtyfrag$ cp exp.c /tmp/exp/
Правый терминал показывает размещённую копию, видимую пользователю saskia.

Скомпилировано от root через sudo gcc (пользователь 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)
Binary: ELF 64-bit LSB executable, x86-64, динамически скомпонованный.

#### 5.3 Выполнение - Получен root
Exploit выполнен от имени `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
Получена полноценная root-оболочка в 12:22 CEST (10:22 UTC), 24 мая 2026 года.
Последовательность системных вызовов 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
Port scan of the lab gateway (`172.66.66.1`, ports 100-8000) executed from root context at 12:51 CEST. This demonstrates lateral movement capability and network mapping from an escalated session.

#### 6.4 Сетевая видимость Suricata
Suricata captured **105 events** associated with `172.66.66.27` across the exercise window (88 mdns, 17 flow). At the time the screenshot was taken (during the nc scan at ~12:53 CEST), 29 events were visible in the dashboard.
The DirtyFrag exploit itself is kernel-internal and produces no network signature - the escalation primitive generates no anomalous traffic on the wire. Suricata was engaged to collect pcaps of post-exploitation traffic and enumeration attempts rather than to detect the exploit itself.
| Event Type | Count |
| ---------- | ----- |
| mdns | 88 |
| flow | 17 |
| **Total** | **105** |
The flow events cluster around the nc port scan window (10:50-11:10 UTC / 12:50-13:10 CEST).

---
### 7. Фаза 4 - Инженерия обнаружения
#### 7.1 Развернутые правила обнаружения
Two EQL sequence rules were created in the Kibana Detection Engine based on the Elastic Security Labs article.
**Правило 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 вернуло ноль результатов. Настройка auditd по умолчанию на `ubuntu-vuln` захватила: `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, но корневая оболочка имела другой родительский процесс — DirtyFrag порождает промежуточные процессы, нарушая корреляцию.
Исправление: коррелировать по auditd.session. Все события в цепочке эксплойта имели session=2, что правильно связывает последовательность независимо от глубины порождения.
3 оповещения HIGH-серьезности, показатель риска 73, в Kibana Security - Оповещения по времени 2026-05-24T10:25:57Z UTC (12:25:57 CEST).
| Оповещение | Временная метка (UTC) | Сигнал |
|---|---|---|
| Совпадение последовательности — событие unshare | 10:25:57.869 | process=clean_frag, user=saskia (uid=1001) |
| Совпадение последовательности — корневая оболочка |
DirtyFrag - Манипуляции с пространством имен, за которыми следует повышение привилегийubuntu-vuln

Все события auditd, связанные с dirtyfrag:```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"
Системные вызовы socket и splice из процесса эксплойта:```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 | Корреляция EQL по `process.parent.pid` не работает для разветвлённых цепочек эксплойтов | Высокая | Да — изменено на `auditd.session` |
| 3 | Мониторинг целостности файлов слеп к DirtyFrag — файлы на диске остаются неизменными на протяжении всего времени | Высокая | Нет устранения в рамках проекта — исправлением является патч ядра |
| 4 | Пост-эксплуатация: файл shadow, ключи SSH и разведка сети выполняются от root до любой реакции на сигналы тревоги | Высокая | Обнаружено через логи auditd; для доступа к учётным данным или этапа разведки не сработало специальное правило |
---
### 10. Ссылки
- Elastic Security Labs: [Copy Fail и DirtyFrag: ошибки страниц Linux в дикой природе](https://www.elastic.co/security-labs/copy-fail-dirtyfrag-linux-page-bugs-in-the-wild)
- Общедоступный PoC: [V4bel/dirtyfrag на GitHub](https://github.com/V4bel/dirtyfrag)
- MITRE ATT&CK: [T1068 — Эксплуатация для повышения привилегий](https://attack.mitre.org/techniques/T1068/)
- MITRE ATT&CK: [TA0004 — Повышение привилегий](https://attack.mitre.org/tactics/TA0004/)
- MITRE ATT&CK: [T1003.008 — /etc/passwd и /etc/shadow](https://attack.mitre.org/techniques/T1003/008/)
| Пункт | Детали |
|---|
| Уязвимость | DirtyFrag - CVE-2026-43284 (путь xfrm-ESP), CVE-2026-43500 (путь RxRPC) |
| Влияние CVSS | Полное локальное повышение привилегий до root |
| Затронутые ядра | Linux kernel >= Январь 2017 (9-летний срок жизни) |
| Затронутые дистрибутивы | Ubuntu 24.04.4, RHEL 10.1, AlmaLinux 10, openSUSE, CentOS Stream 10, Fedora 44 |
| Обход целостности файлов | Файлы на диске не изменяются - AIDE, Tripwire, мониторинг хешей сообщают о чистоте |
| Общедоступный PoC | Доступен (V4bel/dirtyfrag на GitHub) |
| Время до получения root | < 10 минут от точки опоры с низкими привилегиями |
| Приоритет | Действие |
|---|
| Немедленно | Заплатить ядро Linux до исправленной версии на всех хостах. Применить рекомендации по безопасности от вендоров для Ubuntu, RHEL, AlmaLinux, openSUSE, CentOS, Fedora. |
| Краткосрочно | Развернуть явные правила auditd для системных вызовов socket, splice и unshare на всех Linux-хостах, контролируемых Elastic Agent. |
| Краткосрочно | Обновить правила обнаружения 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 (коммит cac2661c53f3) | xfrm-ESP |
| CVE-2026-43500 | DirtyFrag | Июн 2023 (коммит 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, группы=1001(saskia),27(sudo),100(users) |
| Elastic Agent | v9.4.1 с auditbeat |
| Сетевой IDS | Suricata 8.0.5 на выделенном сенсоре |
| 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% |
| Timestamp (UTC) | Syscall | Argument | Process (pid) | User |
|---|
| 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 |
| 10:25:57.881 |
| process=bash, user=root (uid=0) |
| Составное оповещение последовательности | 10:25:57.893 | host=ubuntu-vuln |
| Тактика | Техника | 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 | - | Внедрение страницы в сетевые буферы |