Sploitus

Exploit for Dirty-Frag-Kubernetes-PoC

kitploit · 2026-08-27

Exploit Code

MARKDOWN247 lines
## 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:

![EKS PoC](https://assets.kitploit.com/production/public/readmes/51735/158eeeffb2b8f7445e5f934e281c0010a70b145fde66a0330f714685737ed829/1df81d8422bd9e60ada53e721def41cb93c02864aa469c5453e02c52c652bcd3-display-v1.webp)

> **Предупреждение:** Этот репозиторий опубликован исключительно в образовательных и защитных целях. Используйте его только на системах, которыми вы владеете или на тестирование которых у вас есть явное разрешение.

## Предыстория

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.