
Отчёт о Dirty Frag — цепочке уязвимостей локального повышения привилегий (LPE) в Linux, которая позволяет непривилегированному пользователю получить root-доступ.
Лабораторная работа по воспроизведению и обнаружению эксплойта для локального повышения привилегий в ядре Linux.
Статус: ПОДТВЕРЖДЕНО. Я выполнил воспроизведение, проверку без изменений на диске и обнаружение на уровне системных вызовов в лабораторной среде (ядро 6.18.9+kali-amd64). Этот документ — журнал лабораторной работы. Каждое утверждение ниже было зафиксировано в ходе воспроизведения. Скриншоты и артефакты — реальные снимки из виртуальной машины.
Dirty Frag объединяет две детерминированные логические ошибки в ядре Linux. Эти ошибки позволяют непривилегированному локальному пользователю перезаписать страничный кэш файлов, доступных только для чтения (например, /usr/bin/su), и получить root-оболочку:
| Вариант | CVE | Слабое место | Путь срабатывания | Требует непривилегированного userns |
|---|---|---|---|---|
| Запись в страничный кэш через xfrm‑ESP | CVE‑2026‑43284 | crypto_authenc_esn_decrypt() в esp_input() | socket(AF_INET) с UDP‑encap, затем xfrm_input() | Да (CAP_NET_ADMIN) |
| Запись в страничный кэш через RxRPC | CVE‑2026‑43500 | rxkad_verify_packet_1() (pcbc(fcrypt)) | socket(AF_RXRPC) | Нет |
Оба варианта используют тот же базовый шаблон, что и Dirty Pipe и Copy Fail. Системный вызов splice(2) помещает ссылку на страницу страничного кэша файла в слот frag в sk_buff на стороне отправителя. Атакующий может только читать этот файл. Затем код на принимающей стороне выполняет криптографическую операцию STORE на месте поверх этого frag. Это изменяет страничный кэш в оперативной памяти. Записи на диск не происходит, поэтому системы мониторинга целостности файлов (AIDE, Tripwire) не могут это обнаружить. Атака детерминирована. В ней нет гонки и нет паники ядра при сбое.
cac2661c53f3 (01.2017) до f4c50a4034e6 (исправлено 05.05.2026)2dc334f1a63a (06.2023) до aa54b1d27fe0 (исправлено 10.05.2026)CVE-2026-43284 = 8.8 (высокая), CVE-2026-43500 = 7.8 (высокая)Dirty Frag — это LPE без изменений на диске. Он повреждает страничный кэш в памяти, а не файл на диске. Традиционный мониторинг целостности файлов не может этого увидеть. Обнаружение должно происходить на уровне системных вызовов. Цепочка использует следующие примитивы системных вызовов: socket(AF_ALG)/socket(AF_RXRPC), splice и unshare(CLONE_NEWUSER|CLONE_NEWNET). Путь ESP также создаёт UDP-сокеты AF_INET и netlink-сокеты. Этот уровень является основным фокусом инженерии обнаружения в данном репозитории.
Оба варианта используют одно и то же слабое место: криптографию на месте, которая выполняет STORE байтов на страницу страничного кэша, которую атакующий размещает с помощью splice(2).
UDP_ENCAP_ESPINUDP.vmsplice, затем 16 байт из /usr/bin/su по целевому смещению файла с помощью splice.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() выполняет STORE старших 32 бит ESN. Это значение — replay_esn->seq_hi. Атакующий выбирает это значение при регистрации SA с помощью атрибута netlink XFRMA_REPLAY_ESN_VAL.Атакующий контролирует и местоположение (смещение splice), и значение (4 байта). Проверка подлинности выполняется после операции записи, поэтому криптографический уровень никогда не помечает эту запись. Этот вариант требует CAP_NET_ADMIN и использует unshare(CLONE_NEWUSER|CLONE_NEWNET).
rxkad_verify_packet_1() выполняет расшифровку одного блока pcbc(fcrypt) непосредственно на frag, закреплённом через splice в skb. Он не копирует данные предварительно. Атакующий выбирает сеансовый ключ (add_key("rxrpc", …)) так, чтобы decrypt(ciphertext) равнялся desired_plaintext. Это создаёт STORE размером 8 байт. Этот вариант нацелен на /etc/passwd. Ему не требуется пользовательское пространство имён. Он требует модуль rxrpc.ko (загружается по умолчанию в Ubuntu).
Публичный PoC нацелен на /usr/bin/su. Он записывает 48 ESP-операций STORE по 4 байта каждая (192 байта по смещению файла 0). Он заменяет первые байты страничного кэша статическим ELF-файлом root-оболочки. Точка входа ELF выполняет setgid(0); setuid(0); setgroups(0,NULL); execve("/bin/sh", …). Один вызов execve("/usr/bin/su") затем даёт root-оболочку.
Патч ESP (mainline f4c50a4034e6) помечает страничные frag, поступающие через splice(), флагом SKBFL_SHARED_FRAG. Ветвь skip_cow в esp_input() теперь также проверяет этот флаг. Skb с общими frag проходят через skb_cow_data() перед расшифровкой AEAD на месте.
Патч RxRPC (mainline aa54b1d27fe0) добавляет проверку skb->data_len рядом с существующей проверкой skb_cloned(). Ядро копирует нелинейный skb с разбитыми на страницы данными перед расшифровкой pcbc(fcrypt) на месте.
| Компонент | Детали |
|---|---|
| Гипервизор | VirtualBox |
| Целевая ВМ | Kali Linux 2026.1 (снимок восстановлен до уязвимого состояния) |
| Ядро | 6.18.9+kali‑amd64 (старше исправлений мая 2026 года) |
| PoC эксплойта | V4bel/dirtyfrag (один C-файл) |
| Обнаружение | auditd (правила в detection/dirtyfrag.rules) |
Скриншот лабораторной настройки VirtualBox:
