
Детектор + PoC для уязвимостей записи в page-cache Linux: Copy Fail (CVE-2026-31431) и Dirty Frag (CVE-2026-43284/43500). Только для авторизованных исследований безопасности.
Унифицированный детектор и набор PoC для семейств уязвимостей записи в кэш страниц Linux Copy Fail и Dirty Frag.``` ██████╗ ██╗██████╗ ████████╗██╗ ██╗███████╗ █████╗ ██╗██╗ ██╔══██╗██║██╔══██╗╚══██╔══╝╚██╗ ██╔╝██╔════╝██╔══██╗██║██║ ██║ ██║██║██████╔╝ ██║ ╚████╔╝ █████╗ ███████║██║██║ ██║ ██║██║██╔══██╗ ██║ ╚██╔╝ ██╔══╝ ██╔══██║██║██║ ██████╔╝██║██║ ██║ ██║ ██║ ██║ ██║ ██║██║███████╗ ╚═════╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝╚══════╝
DIRTYFAIL — это небольшая, хорошо документированная утилита на C для исследователей безопасности.
Она определяет, уязвим ли хост под управлением Linux к трём CVE из этого
семейства, и — после явного подтверждения вводом — запускает реальный
proof-of-concept, который помещает пользователя в рутовую оболочку на
уязвимой системе.
| CVE / вариант | Название | Покрытие DIRTYFAIL |
|---|---|---|
| **CVE-2026-31431** | Copy Fail (запись в page-cache через algif_aead `authencesn`) | Обнаружение + полный PoC |
| **CVE-2026-43284 v4** | Dirty Frag — IPv4 xfrm-ESP запись в page-cache | Обнаружение + полный PoC |
| **CVE-2026-43284 v6** | Dirty Frag — IPv6 xfrm-ESP запись в page-cache (`esp6`) | Обнаружение + полный PoC |
| **CVE-2026-43500** | Dirty Frag — RxRPC запись в page-cache | Обнаружение + полный PoC |
| Copy Fail GCM вариант | xfrm-ESP `rfc4106(gcm(aes))` запись в page-cache | Обнаружение + полный PoC |
**Дополнительные режимы:**
- **`--scan --active`** — sentinel-STORE активные пробы. По умолчанию `--scan`
сообщает о предусловиях для каждого CVE (ядро, модули, состояние LSM), а также
выполняет активную проверку примитива Copy Fail. Добавление `--active` расширяет
проверку sentinel-файла STORE на все четыре остальных примитива (ESP v4,
ESP v6, RxRPC, GCM): каждый запускает триггер ядра против sentinel'а в `/tmp`
и сообщает VULNERABLE только если байты-маркеры действительно записываются.
Это единственный способ отличить ядро с бэкпортированным патчем (предусловия
говорят «уязвимо», но проба показывает «нетронуто») от незапатченного без запуска
полного эксплоита. `/etc/passwd` никогда не затрагивается. Автоматически калибрует
смещение STORE для V6 в зависимости от сборки ядра.
- **`--exploit-backdoor`** — постоянный бэкдор с uid-0: запись с совпадением длины,
заменяющая строку `nologin`/`false`/`sync` в `/etc/passwd` на
`dirtyfail::0:0:<заполнитель>:/:/bin/bash`. Сохраняется после выхода из оболочки,
пока страница не будет вытеснена. Состояние сохраняется в `/var/tmp/.dirtyfail.state`
для `--cleanup-backdoor`. Имя пользователя `dirtyfail` намеренно совпадает с
названием проекта, чтобы его можно было мгновенно опознать в любом аудите —
измените `NEW_USER` в `src/backdoor.c`, если вам нужен другой идентификатор
для авторизованной красной команды.
- **Обход AppArmor** — обходит политику Ubuntu
`apparmor_restrict_unprivileged_userns=1` с помощью одношагового
`change_onexec("crun")` повторного выполнения в неограниченный профиль,
который сохраняет возможности userns. Каждый режим эксплоита обрабатывает это
внутренне через fork: родитель остаётся в пространстве имён init, дочерний
процесс выполняет обход, родитель читает глобальный page-cache и запускает `su`
для получения РЕАЛЬНОГО root в init-ns. Устаревший флаг `--aa-bypass` всё ещё
существует для отладки механики обхода в изоляции. См. [§8.5 Архитектура](#85-architecture-outerinner-fork-based-bypass).
## Проверено на работоспособность
DIRTYFAIL был **эмпирически проверен от начала до конца** на нескольких
дистрибутивах и версиях ядра. Таблица ниже отражает результаты тестов для каждого
режима `--exploit-*` на свежей установке каждого дистрибутива.
| Дистрибутив | Ядро | LSM | Copy Fail | xfrm-ESP v4 | xfrm-ESP v6 | RxRPC | GCM | Бэкдор | SU shellcode |
|---|---|---|---|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| Ubuntu 24.04 LTS | `6.8.0-111-generic` | AppArmor | 🛡² | ✅ | ✅ | ✅ | ✅¹ | ✅¹ | (не тестировалось) |
| Debian 13.4 | `6.12.86+deb13` | none | 🛡 | 🛡 | 🛡 | 🛡 | 🛡 | 🛡 | 🛡⁵ |
| AlmaLinux 10.1 | `6.12.0-124.8.1.el10_1` | SELinux | ✅ | ✅ | ✅ | ⏭³ | ✅ | ✅ | ✅ |
| Fedora 44 (Server) | `6.19.10-300.fc44` | SELinux | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Ubuntu 26.04 LTS | `7.0.0-15-generic` | AppArmor (усиленный) | 🛡 | 🛡⁴ | 🛡⁴ | 🛡⁴ | 🛡⁴ | 🛡⁴ | 🛡⁵ |
**Легенда:** ✅ эксплоит сработал и дал реальный root в init-ns · 🛡 защищено — эксплоит не может достичь ошибки ядра (ядро пропатчено ИЛИ LSM блокирует непривилегированный путь) · ⏭ не применимо (отсутствует предусловие)
### Проверка активной пробы (`--scan --active`)
Флаг `--active` добавляет для каждого CVE sentinel-файл STORE при
обнаружении. Мы проверили результаты проб на тех же 4 дистрибутивах
выше (Debian, Fedora, AlmaLinux, Ubuntu 26.04) — таблица ниже показывает
результат пробы для каждого режима, который полностью соответствует
полноценному эксплоиту один к одному:
| Дистрибутив | Проба Copy Fail | Проба ESP v4 | Проба ESP v6 | Проба RxRPC | Проба GCM |
|---|:-:|:-:|:-:|:-:|:-:|
| Debian 13.4 | нетронут 🛡 | нетронут 🛡 | нетронут 🛡 | нетронут 🛡 | нетронут 🛡 |
| Fedora 44 | маркер @0 ✅ | STORE @0 ✅ | STORE @8 ✅ | изменение байта ✅ | sentinel[0] 0x41→0x27 ✅ |
| AlmaLinux 10.1 | маркер @0 ✅ | STORE @0 ✅ | STORE @8 ✅ | предусловия ⏭ | sentinel изменён ✅ |
| Ubuntu 26.04 | нетронут 🛡 | заблокирован LSM 🛡 | заблокирован LSM 🛡 | заблокирован LSM 🛡 | заблокирован LSM 🛡 |
Смещение записи STORE в пробе V6 (8 на Fedora и Alma) соответствует
эмпирическому `V6_STORE_SHIFT`, который `calibrate_v6_shift()` обнаруживает
во время выполнения — это подтверждает, что авто-калибровка правильно заменяет
ранее жёстко заданную константу в разных сборках ядра.
¹ GCM и Бэкдор требуют, чтобы `algif_aead` был загружаем. Ubuntu 24.04
поставляется с `/etc/modprobe.d/disable-algif_aead.conf`, который заносит его
в чёрный список как меру защиты от Copy Fail. При удалении чёрного списка
(например, на ядре, предшествующем этой мере защиты), оба режима работают
от начала до конца.
² Путь Copy Fail через algif_aead защищён чёрным списком modprobe;
базовый примитив CVE в ядре тот же, независимо от того, доступен ли
`authencesn`. xfrm-ESP, RxRPC и вариант GCM все попадают на то же ядро,
потому что не используют algif_aead.
³ Пакет `kernel-modules-extra` в AlmaLinux 10 не установлен по умолчанию
на минимальной установке, поэтому `rxrpc.ko` отсутствует на диске.
Установка `kernel-modules-extra-$(uname -r)` из EPEL или репозитория
AlmaLinux extras восстанавливает модуль; на стандартной минимальной
установке RxRPC недоступен.
⁴ **Ubuntu 26.04 LTS всесторонне блокирует непривилегированную эксплуатацию.**
Поставляемое ядро `7.0.0-15.15` (выпущено 2026-04-22) **младше патча
основной ветки `f4c50a4034e6` (слит 2026-05-07) примерно на 2 недели** —
следовательно, ошибка ВСЁ ЕЩЁ присутствует в ядре. Защита Ubuntu —
**глубинная оборона через усиление AppArmor**, а не патч ядра:
- `apparmor_restrict_unprivileged_userns=1` включён по умолчанию.
- При `unshare(CLONE_NEWUSER)` принудительное выполнение AppArmor на уровне ядра
автоматически переводит ЛЮБОЙ профиль (включая помеченные `(unconfined)`
такие как `crun`, `chrome`, стандартный `unconfined`) в
подпрофиль `<profile>//&unprivileged_userns (mixed)`, у которого
есть `audit deny capability`. uid 0 внутри нового userns не получает никаких caps.
- `change_onexec` в другой профиль не помогает — даже профиль `crun` (который имеет явное
разрешение `userns,` и `flags=(unconfined)`) автоматически переходит при unshare.
Проверено через `aa-exec -p crun bash -c 'unshare -U -n cat /proc/self/attr/current'`
→ `crun//&unprivileged_userns (mixed)`.
- `newuidmap`/`newgidmap` (setuid root) успешно записывают uid_map,
но `setresuid(0)` затем выполняется успешно, тогда как `ioctl(SIOCSIFFLAGS)` и
каждый другой системный вызов, требующий CAP_NET_ADMIN, возвращает EPERM, потому что
запрет capability является покаталоговым, а не по-uid.