## https://sploitus.com/exploit?id=KITPLOIT:TOOLS-GITHUB-PERCIVALLL-DIRTY-FRAG-KUBERNETES-POC
# Dirty Frag (CVE-2026-43284) — Kubernetes Container Escape PoC
Proof-of-concept, демонстрирующий, как **обычный, непривилегированный Kubernetes Pod** может достичь **выполнения кода на уровне узла** в Amazon EKS, эксплуатируя уязвимость Dirty Frag — повреждение page-cache ядра Linux — через общие слои образов контейнеров.
Основной примитив атаки: **любой привилегированный DaemonSet, разделяющий слои образов с контролируемым атакующим контейнером, может быть использован для побега из контейнера**. Данный PoC использует kube-proxy как один конкретный пример, но техника обобщается на любую привилегированную рабочую нагрузку в кластере.
Проверено на **Amazon EKS** (ядро 6.12.80) — непривилегированный pod записывает `[*] success` в файловую систему хоста через привилегированный DaemonSet kube-proxy:

> **Предупреждение:** Этот репозиторий опубликован исключительно в образовательных и защитных целях. Используйте его только на системах, которыми вы владеете или на тестирование которых у вас есть явное разрешение.
## Предыстория
Dirty Frag (CVE-2026-43284) — это уязвимость повреждения page-cache ядра Linux в пути приёма xfrm/ESP. В затронутом пути `esp_input()` может пропустить `skb_cow_data()` для нелинейного skb без `frag_list`, что позволяет `crypto_authenc_esn_decrypt()` сохранить 4 байта контролируемых атакующим данных в страницу page-cache, доступную через `splice()`.
Файл на диске не изменяется. Повреждённые байты находятся в page-cache ядра и наблюдаются последующими читателями той же закэшированной страницы файла.
Полные подробности об исходной уязвимости см. в V4bel/dirtyfrag.
## Принцип атаки
Атака использует три свойства, которые часто сосуществуют в кластерах Kubernetes:
1. **Повреждение page-cache ядра (CVE-2026-43284)** — непривилегированный процесс (с поддержкой пользовательских пространств имён) может перезаписать закэшированные в памяти страницы любого файла, который он может открыть только для чтения, через гонку xfrm/ESP splice.
2. **Совместное использование слоёв образов** — контейнерные рантаймы (containerd, CRI-O) используют overlay-файловые системы, где идентичные слои образов сопоставляются с одними и теми же страницами page-cache в разных контейнерах.
3. **Привилегированные DaemonSet'ы** — во многих кластерах работают DaemonSet'ы с повышенными привилегиями (`privileged: true`, `hostNetwork: true`, широкие capabilities и т. д.), которые периодически выполняют бинарные файлы из своих образов.
Когда эти условия совпадают, непривилегированный pod может повредить бинарный файл в общем слое образа, а привилегированный DaemonSet на том же узле непреднамеренно выполнит повреждённый бинарный файл со своими повышенными привилегиями — достигая полного выполнения кода на уровне узла.
**Цель уязвимости НЕ ограничивается kube-proxy.** Любой привилегированный DaemonSet (агенты мониторинга, плагины CNI, сборщики логов, агенты безопасности и т. д.), чей образ контейнера разделяет слои с контролируемым атакующим образом, является жизнеспособной целью.
## Отличие от Copy Fail
Этот проект вдохновлён моделью эксплуатации Kubernetes, задокументированной в Copy Fail Kubernetes PoC, но использует другой примитив ядра.
## Как это работает
Цепочка атаки состоит из трёх этапов: **повреждение page-cache** , **распространение между контейнерами** и **привилегированное выполнение**.
### 1\. Патчинг Page-Cache через xfrm/ESP
Бинарный файл PoC выполняет следующую последовательность из непривилегированного контейнера:
1. Входит в новые пользовательское и сетевое пространства имён с помощью `unshare(CLONE_NEWUSER | CLONE_NEWNET)`.
2. Регистрирует множество xfrm Security Associations, чьи старшие поля последовательности кодируют 4-байтовые фрагменты полезной нагрузки.
3. Открывает целевой бинарный файл из общего слоя образа только для чтения.
4. Использует `splice()` и специально сформированный ESP-ввод для запуска уязвимого пути ядра.
5. Повторяет примитив, пока содержимое page-cache целевого бинарного файла не будет содержать встроенную полезную нагрузку.
Права на запись в целевой файл не требуются. Файл на диске не изменяется — повреждается только page-cache в памяти.
### 2\. Распространение между контейнерами через общие слои
Контейнерные рантаймы обслуживают чтение из нижних слоёв overlay через page-cache ядра. Если контейнер PoC и `kube-proxy` разделяют один и тот же файл нижнего слоя, оба наблюдают одни и те же закэшированные страницы.
Образ EKS в этом репозитории построен на основе:
root@kitploit:~
public.ecr.aws/eks-distro-build-tooling/eks-distro-minimal-base-iptables:2026-03-11-1773190710.2023
Эта база выбрана для соответствия слою пользовательского инструментария kube-proxy EKS, используемому в проверенной среде.
### 3\. Привилегированное выполнение через kube-proxy
Когда `kube-proxy` в следующий раз выполняет пропатченный бинарный файл семейства iptables, ядро загружает повреждённые закэшированные страницы. Полезная нагрузка PoC монтирует корневое устройство хоста и записывает файл-маркер в `/root/res`.
Ожидаемое содержимое маркера:
root@kitploit:~
[*] success
### Схема потока атаки
root@kitploit:~
┌──────────────────────────────┐ ┌────────────────────────┐ ┌──────────────────────────┐
│ Pod PoC │ │ Page Cache ядра │ │ DaemonSet kube-proxy │
│ непривилегированный контейнер│ │ │ │ привилегированный контейнер│
│ │ │ │ │ │
│ 1. unshare user+net ns │ │ │ │ │
│ 2. установка xfrm SA │ │ │ │ │
│ 3. splice целевого бинарника│────▶│ бинарник общего слоя │────▶│ выполняет пропатченный │
│ через путь ESP │ │ page cache пропатчен │ │ бинарник, полезная │
│ │ │ │ │ нагрузка работает с │
│ │ │ │ │ привилегиями уровня узла│
└──────────────────────────────┘ └────────────────────────┘ └──────────────────────────┘
## Проверенная среда
### Amazon EKS
### GKE и ACK — протестировано, не эксплуатируется с конфигурацией по умолчанию
Я протестировал это на кластерах GKE и ACK. Все попытки провалились.
Примитив Dirty Frag **требует создания пользовательского пространства имён** (`CLONE_NEWUSER`) для получения `CAP_NET_ADMIN` внутри нового сетевого пространства имён. И ACK, и GKE блокируют это на уровне узла разными механизмами:
* **ACK** : Ограничение на уровне ядра (`user.max_user_namespaces=0`) полностью предотвращает создание непривилегированных пользовательских пространств имён.
* **GKE** : Профиль seccomp по умолчанию (включённый флагом kubelet `--seccomp-default`) блокирует системный вызов `unshare` независимо от лимита пространств имён.
Это ключевое отличие от Copy Fail (CVE-2026-31431), который **не** требует пользовательских пространств имён и успешно эксплуатирует все три платформы.
## kube-proxy как конкретный пример
Предоставленный вариант для EKS патчит следующие бинарные файлы, когда они присутствуют:
root@kitploit:~
/usr/sbin/xtables-legacy-multi
/usr/sbin/xtables-nft-multi
Эти бинарные файлы вызываются инструментарием iptables, используемым `kube-proxy`. Точное время срабатывания зависит от активности согласования узлов и сервисов. В проверенной среде полезная нагрузка была запущена обычным согласованием `kube-proxy`.
**Важные оговорки:**
* kube-proxy вызывает `ipset` только при настройке в режиме **ipvs**. Режим по умолчанию (`iptables`) не использует `ipset`.
* Некоторые управляемые дистрибутивы Kubernetes запускают kube-proxy как **непривилегированный** контейнер, что ограничивает влияние побега.
* PoC нацелен на несколько бинарных файлов (`xtables-legacy-multi`, `xtables-nft-multi`), чтобы покрыть разные режимы прокси, но будут ли они вызваны, зависит от конфигурации кластера.
**Если kube-proxy не привилегирован в вашем кластере, принцип атаки всё равно работает** — вам просто нужно определить другой привилегированный DaemonSet, который разделяет слои образов с базовым образом, который вы можете собрать.
## Структура репозитория
root@kitploit:~
.
├── exploit/
│ └── dirtyfrag.c # писатель page-cache через xfrm/ESP
├── payload/
│ ├── payload-eks.c # полезная нагрузка nolibc, записывающая /root/res на хосте
│ └── nolibc/ # заголовки Linux nolibc
├── deploy/
│ └── poc-eks.yaml # манифест непривилегированного Deployment для EKS
├── scripts/
│ ├── setup-eks.sh # копирование, сборка и импорт образа на узле EKS
│ ├── run-poc.sh # развёртывание и проверка маркера
│ └── cleanup.sh # удаление pod, маркера, закэшированных страниц и локального образа
├── Dockerfile.eks # образ EKS на основе eks-distro-minimal-base-iptables
├── Makefile # цели сборки payload, exploit, Docker и nerdctl
└── .github/workflows/
└── docker-publish.yml # рабочий процесс публикации в GHCR
## Сборка и использование
root@kitploit:~
# Сборка payload + бинарника exploit
make build-eks CC=x86_64-linux-gnu-gcc
# Сборка Docker-образа
make docker-build-eks
# Развёртывание (непривилегированный pod)
kubectl apply -f deploy/poc-eks.yaml
# Проверка логов
kubectl logs deployment/dirtyfrag-poc-eks
# Проверка побега на узле
ssh ec2-user@<node-ip> "sudo cat /root/res"
# Ожидается: [*] success
Рабочий процесс GitHub Actions (`.github/workflows/docker-publish.yml`) публикует образ в GHCR при push в `main` или создании тега. Замените `<owner>` в `deploy/poc-eks.yaml` на пользователя или организацию GitHub, владеющих форком.
### Очистка
root@kitploit:~
kubectl delete -f deploy/poc-eks.yaml --ignore-not-found
ssh ec2-user@<node-ip> "sudo rm -f /root/res"
kubectl delete pod -n kube-system -l k8s-app=kube-proxy --force
## Затронутые версии
* **Ядро Linux** : Все версии до патча CVE-2026-43284 (коммит `f4c50a4034e6`).
* **Kubernetes** : Любая версия, использующая непропатченное ядро узла с включёнными пользовательскими пространствами имён. Уязвимость находится в ядре, а не в самом Kubernetes. Kubernetes лишь предоставляет контекст выполнения (общие слои образов + привилегированные DaemonSet'ы), который повышает воздействие от локального повреждения page-cache до полного побега из контейнера.
## Меры по смягчению
* **Пропатчите ядро.** Обновитесь до ядра, содержащего исправление Dirty Frag, включая коммит `f4c50a4034e6` или бэкпорт от вендора.
* **Отключите неиспользуемые модули ESP.** Заблокируйте `esp4` и `esp6`, если IPsec ESP не требуется на рабочих узлах.
* **Ограничьте пользовательские пространства имён.** Установка `user.max_user_namespaces=0` предотвращает получение этим PoC `CAP_NET_ADMIN` в новом сетевом пространстве имён (это уже значение по умолчанию на ACK).
* **Используйте ограничительные профили seccomp.** RuntimeDefault или пользовательские профили могут блокировать ключевые системные вызовы пространств имён и сети (это уже значение по умолчанию на GKE).
* **Минимизируйте привилегированные DaemonSet'ы.** Избегайте `privileged: true` и широкого доступа к хосту, если это строго не требуется.
* **Уменьшите совместное использование слоёв с привилегированными рабочими нагрузками.** Используйте отдельные базовые образы для привилегированных агентов и контролируйте, где могут выполняться недоверенные рабочие нагрузки.
Пример блока модуля:
root@kitploit:~
printf 'install esp4 /bin/false\ninstall esp6 /bin/false\n' | sudo tee /etc/modprobe.d/dirtyfrag.conf
sudo rmmod esp4 esp6 2>/dev/null || true
## Благодарности
* **Исследование Dirty Frag и оригинальный эксплойт** : V4bel/dirtyfrag
## Ссылки
* Dirty Frag - V4bel/dirtyfrag
* Освещение на LWN
* Обсуждение CVE-2026-43284 xfrm/ESP
* Copy Fail Kubernetes PoC
## Лицензия
Код эксплойта адаптирован из V4bel/dirtyfrag под лицензией MIT.
Код полезной нагрузки получен из tgies/copy-fail-c и распространяется под двойной лицензией **LGPL-2.1-or-later** ИЛИ **MIT**.
Заголовки nolibc взяты из инфраструктуры самотестирования ядра Linux.