Статья Bulkhead: автообнаружение path traversal при container escape через семантический анализ

Рука в синей перчатке держит логический щуп над платой с перепутанными шлейфами. Диагностический терминал отображает коды уязвимостей зелёным мерцающим текстом.


За последнее десятилетие в контейнерных рантаймах и тулкитах накопилось порядка 27 CVE, связанных с path traversal (цифра из исследования Bulkhead, независимо не верифицирована). И темп растёт. В 2024-2025 годах прилетело сразу по всем ключевым компонентам: NVIDIA Container Toolkit (CVE-2024-0132, CVSS 9.0 CRITICAL), runc (CVE-2025-31133, CVSS 7.3 HIGH), containerd. Каждый - уязвим к одному и тому же классу ошибок. Причём это не привычный web path traversal с ../../../etc/passwd в URL. Это кросс-граничное разрешение путей на стыке контейнер-хост - PaTra-уязвимости. Атакующий через symlink-подмену или race condition заставляет привилегированный хостовой процесс рантайма обратиться к произвольному месту хостовой ФС вместо контейнерного. Результат - полноценный container escape (T1611, Privilege Escalation): от чтения /etc/shadow хоста до перезаписи бинарников с получением root.

Фреймворк Bulkhead, описанный в исследовательской работе 2025 года (концептуальный подход; публичный репозиторий и независимая верификация на момент написания не подтверждены), предлагает автоматическое container escape обнаружение и ремедиацию PaTra через семантический анализ кода мультиагентной LLM-системой с формальной верификацией патчей. Разбираю архитектуру, механику, результаты и ограничения - и то, что из этого реально применить к runtime-детекции уже сейчас.

PaTra-уязвимости: path traversal container escape на границе контейнер-хост​

1784153232519.webp

PaTra в контейнерном контексте - совсем не та path traversal, которую ищут в веб-приложениях. В классическом веб-сценарии атакующий подставляет ../ в пользовательский ввод, чтобы добраться до файлов за пределами webroot. В контейнерных рантаймах уязвимый код работает с привилегиями хоста, обрабатывает пути, пересекающие границу контейнер-хост, и должен корректно разрешать символические ссылки там, где файловые системы контейнера и хоста сосуществуют через mount namespace.

Два корневых механизма PaTra​

Исследование Bulkhead выделяет два корневых механизма PaTra-уязвимостей:

Отсутствие проверок безопасности. Код, обрабатывающий cross-boundary пути (при docker cp, монтировании GPU-библиотек, инициализации workspace), не проверяет, что разрешённый путь действительно попадает внутрь ожидаемой области файловой системы. Атакующий размещает symlink в контейнере, указывающий на произвольный путь хоста. Когда привилегированный процесс разрешает этот symlink - он лезет в хостовую ФС, а не в контейнерную. CWE-61 (UNIX Symbolic Link Following) - это про него.

TOCTOU (Time-of-Check to Time-of-Use). Проверка безопасности формально есть, но между моментом проверки и моментом использования пути - временное окно. Атакующий эксплуатирует race condition: подменяет файл или symlink между проверкой и фактическим обращением. CWE-367 и CWE-362 - характерные классификаторы. Для автообнаружения path traversal этот класс принципиально сложнее: статический анализ видит корректную проверку, а уязвимость возникает только в runtime при определённом тайминге. По-настоящему это ощущаешь, когда пытаешься воспроизвести race condition на стенде - окно может быть в микросекунды.

Эволюция PaTra: от docker cp до container escape GPU workloads​

Эволюция PaTra-уязвимостей хорошо показывает, почему точечные патчи не решают проблему:

CVE-2018-15664 (CWE-362) - API-эндпоинты за командой docker cp уязвимы к symlink-exchange атаке с directory traversal. Атакующий получает произвольный read-write доступ к хостовой ФС с правами root. Причина: daemon/archive.go не выполняет архивные операции на "замороженной" файловой системе и не использует chroot. Сообщество выпустило патч, закрывающий базовый symlink traversal.

CVE-2019-14271 (CWE-665; CVSS 9.8 CRITICAL, вектор CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H) - через год после исправления CVE-2018-15664 обнаружилась инъекция кода в Docker 19.03.x: nsswitch динамически загружает библиотеку внутри chroot, содержащего файлы контейнера. Патч для предыдущей CVE не устранил корневую проблему - использование chroot с контейнерным контентом. Атакующий подкладывает вредоносный libnss_*.so в контейнер, и nsswitch внутри chroot динамически загружает его с привилегиями хостового процесса (CWE-665, Improper Initialization). Классический пример: исправили симптом, не разобравшись в семантике взаимодействия, и создали ложное чувство безопасности.

CVE-2024-0132 (CWE-367; CVSS 9.0 CRITICAL, вектор CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H) - TOCTOU-уязвимость в NVIDIA Container Toolkit 1.16.1 и ранее. Тулкит не выполняет безопасное разрешение символических ссылок при обработке container-provided library paths во время инициализации. Атакующий размещает вредоносный symlink в образе контейнера, заставляя привилегированный хостовой тулкит обращаться к чувствительным локациям хостовой ФС. Scope:Changed в CVSS-векторе - это выход за границы изоляции. Уязвимость не затрагивает сценарии с CDI. Затронуты NVIDIA Container Toolkit и NVIDIA GPU Operator.

CVE-2025-31133 (CWE-61, CWE-363; CVSS 4.0 base score 7.3 HIGH, вектор CVSS:4.0/AV:L/AC:L/AT:P/PR:L/UI:A/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H) - runc версий 1.2.7 и ниже, 1.3.0-rc.1 через 1.3.1 включительно, 1.4.0-rc.1 и 1.4.0-rc.2 (требуется локальный доступ и активное участие пользователя) не выполняет достаточную верификацию того, что источник bind-mount - реальный inode /dev/null при маскировке. Результат - arbitrary mount gadget, ведущий к раскрытию информации хоста.

Тренд прослеживается чётко: GPU-тулкиты для AI-воркаудов, workspace-контейнеры для autonomous agents (OpenHands и аналоги) - каждый из них экспоненциально расширяет поверхность атаки. Разработчики этих компонентов часто не имеют специализированного контекста безопасности контейнеров для корректной обработки cross-boundary путей. Некоторые рантаймы (Alibaba's Pouch) дошли до радикальных мер - полного отключения follow symlink, - лишь бы избежать path resolution exploits.

Место path traversal container escape в цепочке атаки​

1784153290368.webp

Container escape через PaTra занимает позицию Privilege Escalation (T1611, Escape to Host) в MITRE ATT&CK (тактика privilege-escalation, платформа containers). Полная цепочка:
  1. Initial Access - foothold внутри контейнера через уязвимость приложения, supply chain compromise, скомпрометированный образ или утёкшие credentials.
  2. Privilege Escalation (T1611) - эксплуатация PaTra-уязвимости в рантайме/тулките для выхода на хост. Не требует --privileged или специальных capabilities - достаточно уязвимого кода в самом рантайме, обрабатывающем пути с привилегиями хоста.
  3. Host Access - доступ к хостовой ФС: credentials (/etc/shadow, SSH-ключи, kubeconfig), секреты kubelet, токены service accounts.
  4. Lateral Movement - перемещение на другие ноды кластера через украденные credentials и доступ к Docker/containerd socket или Kubernetes API.
Принципиальное отличие PaTra-escape от escape через misconfiguration (--privileged, mounted docker.sock): PaTra эксплуатирует уязвимость в рантайме при дефолтной конфигурации. Все традиционные рекомендации по container hardening (drop capabilities, seccomp-профили, Pod Security Standards) тут бесполезны.

Sigma-правила для T1611 в SigmaHQ (kubernetes_audit_hostpath_mount.yml, kubernetes_audit_privileged_pod_creation.yml) покрывают сценарии с hostPath mount и privileged pod creation, но не затрагивают PaTra-векторы. Тесты Atomic Red Team для T1611 (Escape to Host, платформа containers) воспроизводят misconfiguration-based escape - PaTra-эксплуатация там не покрыта. Это фундаментальный gap в detection coverage, и его стоит осознавать.

Почему сигнатурные методы container escape обнаружения ломаются на PaTra​

Существующие подходы к cloud container security detection делятся на четыре категории, и каждая спотыкается на PaTra по-своему.

Статический анализ на основе правил и DFA. Инструменты вроде Semgrep или CodeQL обнаруживают вызовы функций, работающих с путями (filepath.Join, os.Readlink, securejoin.SecureJoin). Проблема: они не способны определить, происходит ли cross-boundary взаимодействие контейнер-хост. Вызов filepath.Join в коде, обрабатывающем пути внутри хоста (не в контексте контейнера), - не уязвимость, но статический матчер его зафлагует. Результат - массовые false positives. А TOCTOU чисто статическим анализом вообще не обнаружить: race condition проявляется только в runtime.

Защита на уровне ядра (VFS-модификации). Академические подходы предлагали strict access controls в слое Virtual File System ядра Linux. Модификации слишком глубоко интегрируются в kernel mainline, вызывают нестабильность syscall и чрезмерно специфичны для контейнерных сценариев - нарушают нормальную работу GNU/Linux вне контейнерной среды. Подход последовательно отвергается сообществом ядра. Мейнтейнеры не хотят тащить в ядро костыли под конкретный use case - и их можно понять.

Runtime-мониторинг (Falco, Tetragon, Tracee). eBPF container monitoring отлично ловит anomalous syscall: nsenter, unshare, setns, mount из контейнера, доступ к /proc и /sys. Но PaTra-escape часто не генерирует аномальных syscall из контейнера - уязвимый код работает в привилегированном процессе рантайма на хосте. Falco-правило, детектирующее mount из контейнера, не сработает, если mount выполняет runc по инициативе обработки легитимной операции. Для TOCTOU нужно отслеживать тайминг между проверкой пути и его использованием - задача, которую eBPF теоретически может решить, но на практике нужна instrumentation конкретного кода рантайма, а не generic syscall monitoring.

Ручной аудит. Наиболее точный, наименее масштабируемый подход. На практике - единственный, который реально находит TOCTOU в рантаймах, но стоит это соответственно.

КритерийBulkhead (семантический)Статический анализ (DFA/regex)Kernel VFSRuntime (Falco/Tetragon)
ПреимуществаПонимает семантику cross-boundary взаимодействий, генерирует PoC и патчиСкорость, низкие требования к ресурсамПолная видимость на уровне ядраReal-time, low overhead в продакшне
ОграниченияЗависимость от LLM, не для runtime-детекцииНет семантики, высокий false positive rateОтвергнут Linux mainline, нестабильностьНе видит PaTra в хостовых процессах рантайма
Обнаруживает TOCTOUДа, через анализ call-chainНетДа, но нестабильноТеоретически через eBPF, практически нет
Когда использоватьАудит кодовой базы рантаймов и тулкитовБыстрый скан известных паттерновИсследовательские средыПродакшн-мониторинг misconfiguration-escape
Когда не использоватьRuntime-детекция в продакшнеПоиск TOCTOU и сложных логических ошибокProduction-окруженияАудит исходного кода рантаймов

Архитектура Bulkhead: семантический анализ безопасности контейнеров​

Bulkhead - концептуальный исследовательский фреймворк (описан в препринте 2025 года; публичная реализация и независимая верификация на момент написания не подтверждены), предлагающий интеграцию LLM с формальными методами (model checking) для end-to-end обнаружения и ремедиации PaTra-уязвимостей в кодовых базах контейнерных рантаймов. Фреймворк описывает мультиагентную систему, где каждый агент отвечает за отдельный этап пайплайна.

Ключевая идея: вместо поиска конкретных сигнатур уязвимостей Bulkhead систематически обобщает известные PaTra-уязвимости из нескольких измерений (multi-dimensional knowledge patterns) и использует эти обобщения для управления LLM-агентами. По замыслу авторов, это концептуально иной подход к PaTra detection - не regex по коду, а семантическое понимание того, какие взаимодействия контейнер-хост опасны.

Пайплайн обнаружения PaTra​

Пайплайн состоит из трёх этапов:

Этап 1: Entry Function Identification. Фреймворк применяет high-risk functional patterns - обобщённые шаблоны функций, участвующих в cross-boundary взаимодействиях контейнер-хост. Это не список функций вроде os.Open или filepath.Join. Паттерны учитывают контекст: функция работает с путями, пересекающими mount namespace boundary, или обрабатывает container-provided пути в привилегированном хостовом процессе. LLM-агент анализирует кодовую базу и идентифицирует entry points для потенциально уязвимых cross-boundary interactions. Принципиальное отличие от статического анализа: агент понимает семантику - отличает path-операцию внутри контейнера от path-операции, пересекающей границу изоляции.

Этап 2: Function Call-Chain Extraction. Для каждой идентифицированной entry function фреймворк восстанавливает цепочки вызовов на подходящей глубине. Глубина не фиксирована - она определяется call-chain patterns, обобщёнными из известных CVE. Цепочка покрывает весь путь от получения контейнерного ввода до финального обращения к файловой системе. LLM видит полный контекст: где путь приходит, как трансформируется, какие проверки применяются (или не применяются) и где происходит финальный доступ к ресурсу.

Этап 3: PaTra Vulnerability Detection. LLM-агент анализирует извлечённые call chains в контексте threat model. Он ищет два типа дефектов: (1) отсутствие security checks - путь из контейнера разрешается без валидации; (2) TOCTOU - проверка присутствует, но между ней и использованием пути есть временное окно для подмены. Для каждой обнаруженной уязвимости фреймворк генерирует proof-of-concept exploit. PoC выполняет двойную функцию: валидация обнаружения (уменьшение false positives) и guide для генерации патчей.

Пайплайн ремедиации​

Candidate Patch Synthesis. LLM-агент на основе PoC генерирует кандидаты патчей. Патч устраняет не текущий exploit path, а корневую причину. Для TOCTOU - привязка проверки к фазе использования (security check binding), а не добавление ещё одной проверки перед использованием. Цепочка CVE-2018-15664 -> CVE-2019-14271 наглядно показывает, почему это критично: патч, добавляющий проверку без binding, обходится через тот же race condition.

Pattern-Template Model Checking. Каждый сгенерированный патч проходит assertion-driven верификацию с предопределёнными шаблонами model checking. Формальная проверка гарантирует, что патч не вносит вторичных багов и действительно закрывает уязвимость. Использование формальных методов - принципиальное отличие Bulkhead от подхода "LLM нагенерировал, а дальше - на ревью": LLM генерирует патч, model checker его доказывает.

Ограничения Bulkhead и границы применимости​

Не применим для runtime-детекции. Bulkhead анализирует исходный код рантаймов, а не поведение запущенных контейнеров. Для runtime-защиты нужны другие инструменты.

Зависимость от качества LLM. Семантический анализ выполняется LLM-агентами. Качество обнаружения зависит от способности модели понимать сложную логику container-host взаимодействий. Принципиально новый класс PaTra, не похожий на известные случаи, может быть пропущен. LLM хорошо обобщает то, что видел, но плохо экстраполирует на действительно новое - и это честное ограничение.

Scope ограничен PaTra. Bulkhead не обнаруживает container escape через misconfiguration (--privileged, mounted docker.sock), kernel exploits (Dirty Pipe - CVE-2022-0847, CVSS 7.8, уязвимость из CISA KEV, эксплуатируется in-the-wild), или уязвимости в CRI-плагинах, не связанные с path traversal (CVE-2022-23648 в containerd, CVSS 7.5, CWE-200 Information Exposure). Фреймворк узкоспециализирован - и это нормально, но нужно понимать границы.

Масштабируемость knowledge base. Мультидименсиональные паттерны обобщены из заявленных авторами 27 CVE (список не верифицирован независимо). Фреймворк лучше работает на рантаймах, архитектурно похожих на Docker/containerd/runc, хуже - на экзотике.

Предусловия и требования к окружению​

  • Вход: исходный код контейнерного рантайма или тулкита (Go, C, Rust)
  • LLM-бэкенд: LLM с reasoning-возможностями уровня GPT-4 class (конкретная модель не зафиксирована в исследовании)
  • Формальная верификация: model checker для assertion-driven проверки
  • Применимость: аудит перед релизом, CI/CD security gate, vulnerability research - не runtime protection

Runtime-детекция PaTra: path traversal exploit detection в продакшне​

e7cfdf19d66f19b2dc956736b7b847c622a0eb36-4041x2402.webp

📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
на одном терминале и exploit-скриптом на другом - тогда видно, насколько узкое это окно.

Чеклист аудита контейнерной среды на PaTra-устойчивость​

  1. Проверить версии runc, containerd, Docker Engine - все CVE с CWE-362/CWE-367/CWE-61 должны быть закрыты
  2. Проверить наличие NVIDIA Container Toolkit версии 1.16.1 и ниже - обновить при обнаружении (CVE-2024-0132)
  3. Включить audit-логирование Kubernetes API и применить Sigma-правила для T1611
  4. Развернуть eBPF-мониторинг (Falco/Tetragon) на нодах с фокусом на syscall рантайм-процессов
  5. Проверить, использует ли рантайм openat2 с RESOLVE_NO_SYMLINKS для cross-boundary path операций (strace рантайм-процесса)
  6. Прогнать Atomic Red Team тесты для T1611 (Escape to Host, платформа containers) - они не покрывают PaTra, но валидируют базовую детекцию misconfiguration-escape
  7. Для GPU-воркаудов: включить Container Device Interface (CDI) - CVE-2024-0132 не затрагивает сценарии с CDI
  8. Ограничить mount shared ресурсов (GPU-библиотеки, agent workspaces) минимально необходимым набором путей
  9. Оценить применимость Bulkhead или аналогичного семантического аудита для кастомных container-тулкитов в вашей инфраструктуре
Есть основания полагать, что роль PaTra как вектора container escape будет расти. Причина проста: hardening кластеров дозрел до точки, где --privileged и mounted docker.sock в продакшне встречаются всё реже. Pod Security Standards, admission controllers, seccomp-профили закрывают конфигурационные escape. А вот GPU-тулкиты, AI-агентные workspace-ы и multi-tenant shared mount-ы только набирают обороты, и каждый из них - новый cross-boundary interaction, потенциальный следующий CVE-2024-0132.

Неудобная правда: runtime security containers в текущем виде (Falco, Tetragon) не детектирует PaTra-escape, потому что эти инструменты смотрят на syscall из контейнера, а не на поведение рантайм-процесса на хосте. Kubernetes STIG и Pod Security Admission закрывают конфигурационные gap-ы, но молчат про PaTra. Bulkhead показывает правильное направление для статического аудита кодовых баз рантаймов. Для runtime-детекции аналогичный семантический подход - открытая исследовательская задача и одна из наиболее перспективных для kubernetes container escape prevention. Решение лежит на стыке eBPF-трассировки и семантического понимания context-of-use - какой путь куда ведёт, пересекает ли он boundary. Этого пока нет ни у одного вендора. Попробуйте прогнать strace -f -e trace=openat,readlink,symlink на containerd-shim во время docker cp - и вы увидите, как выглядит тот самый gap между "проверили" и "использовали" путь.
 
Последнее редактирование модератором:
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab

Похожие темы

🚀 Первый раз на Codeby?
Гайд для новичков: что делать в первые 15 минут, ключевые разделы, правила
Начать здесь →
🧭 Навигатор · ИБ 2026
Не знаешь, какой трек твой?
5 направлений ИБ, реальные зарплаты и точка входа для каждого — в одном треде.
JuniorSenior+
100K → 600K+ ₽ /мес
Открыть навигатор →
🔴 Свежие CVE, 0-day и инциденты
То, о чём ChatGPT ещё не знает — обсуждаем в реальном времени
Threat Intel →
💼 Вакансии и заказы в ИБ
Pentest, SOC, DevSecOps, bug bounty — работа и проекты от проверенных компаний
Карьера в ИБ →

HackerLab