Привет, Хабр!
Меня зовут Рустем Галиев, я Senior DevOps Engineer в IBM.
В последние годы контейнеризация стала неотъемлемой частью инфраструктуры для современных приложений. Технологии контейнеризации, такие как Docker и Kubernetes, предоставляют удобный способ упаковки, развёртывания и масштабирования приложений, а также обеспечивают лёгкость миграции и управление зависимостями. Но, как и любая другая технология, контейнеры имеют свои уязвимости. Ошибки в конфигурации, слабые политики безопасности и недостаточная изоляция контейнеров могут превратить их в привлекательные цели для злоумышленников.
Эта статья расскажет, как искать и эксплуатировать уязвимости в контейнеризированных средах, рассматривая ключевые аспекты контейнерной безопасности, включая распространенные уязвимости, ошибки в конфигурации, а также методы для их выявления и эксплуатации. Мы обсудим примеры практических атак, таких как контейнерный брейкаут, межконтейнерные атаки, перехват данных и несанкционированное использование секретов, а также дадим рекомендации по предотвращению этих угроз.
Статью разделил на три части, ссылки на вторую и третью добавлю, после того как выложу.
Эксплуатация устаревших библиотек и эскалация привилегий
С развитием контейнеризации и популярностью платформ вроде Docker и Kubernetes использование контейнеров стало стандартом для развертывания приложений. Контейнеры помогают изолировать приложения и их зависимости, что упрощает разработку и доставку программного обеспечения. Однако контейнеры также имеют свои уязвимости, особенно если в них содержатся устаревшие или уязвимые версии библиотек. Эти уязвимости могут быть использованы злоумышленниками для получения доступа к контейнеру и последующей эскалации привилегий.
Проблема устаревших библиотек в контейнерах
Контейнеры, как правило, создаются на основе базовых образов, таких как Ubuntu, Debian, Alpine и т.д., которые содержат в себе определенный набор системных библиотек. Когда приложение собирается с использованием образа, библиотеки, которые были актуальны на момент создания контейнера, могут устареть и содержать уязвимости.
Разработчики часто не обновляют контейнеры после их сборки, так как предполагается, что контейнер — это неизменяемая сущность. Однако если контейнер эксплуатируется в течение долгого времени, то уязвимости могут быть обнаружены в его зависимостях, делая его потенциальной мишенью для атак.
Как уязвимости в библиотеках могут быть использованы для атак
Когда контейнер содержит уязвимую версию какой-либо библиотеки, злоумышленник может попытаться использовать известную уязвимость для выполнения кода или повышения привилегий. Рассмотрим процесс на примере реальной уязвимости.
Пример: Уязвимость в библиотеке OpenSSL
Предположим, что контейнерное приложение использует библиотеку OpenSSL для шифрования и дешифрования данных, но в контейнере используется устаревшая версия этой библиотеки. OpenSSL подвергалась критическим уязвимостям, одна из которых — Heartbleed (CVE-2014-0160). Heartbleed позволяет злоумышленнику считывать содержимое памяти сервера, в том числе конфиденциальную информацию, такую как ключи шифрования и пароли.
— Эксплуатация уязвимости: Злоумышленник отправляет специально сформированный пакет на сервер, использующий уязвимую версию OpenSSL, и получает доступ к области памяти контейнера, которая содержит конфиденциальные данные.
— Получение доступов: Используя полученные данные, злоумышленник может получить доступ к сессионным токенам, паролям или ключам. С их помощью он может войти в систему под видом авторизованного пользователя.
— Эскалация привилегий: Если контейнер работает с повышенными привилегиями (например, с правами root внутри контейнера), злоумышленник может попытаться использовать дополнительные техники, чтобы выйти за пределы контейнера и получить доступ к хост-системе.
В некоторых случаях злоумышленник может использовать уязвимости для выхода за пределы контейнера. Это возможно, если контейнер работает с повышенными привилегиями или если хост-система также уязвима. Примером может служить CVE-2019-5736 — уязвимость в Docker, которая позволяла злоумышленнику выйти из контейнера и получить доступ к файловой системе хоста.
Методы защиты контейнеров
— Регулярные обновления и патчи — следите за обновлениями образов контейнеров и используемых библиотек. Периодическое обновление поможет устранить известные уязвимости.
— Сканирование уязвимостей — использование специализированных инструментов, таких как Trivy, Clair или Anchore, для анализа контейнерных образов на наличие уязвимостей в пакетах.
— Меньше привилегий для контейнеров — запускайте контейнеры с минимальными привилегиями (не от имени root). Это снизит последствия потенциальной атаки.
— Использование минималистичных базовых образов — используйте минималистичные образы, такие как Alpine, которые содержат меньше библиотек, и, соответственно, меньше потенциальных уязвимостей.
— Политики безопасности Kubernetes и Docker — настройка политик безопасности (PodSecurityPolicies в Kubernetes или seccomp в Docker) позволит ограничить возможности контейнеров и предотвратить их влияние на хост-систему.
Устаревшие библиотеки в контейнерах представляют собой значительную угрозу безопасности. При разработке и эксплуатации контейнерных приложений важно учитывать возможные риски и своевременно устранять уязвимости, чтобы минимизировать вероятность атаки. Регулярное сканирование контейнеров и следование лучшим практикам безопасности поможет сохранить контейнерные среды в безопасности и предотвратить несанкционированный доступ или эскалацию привилегий.
Неправильная конфигурация контейнеров
Неправильная конфигурация контейнеров действительно может привести к так называемому контейнерному брейкауту (от англ. container breakout) — ситуации, когда злоумышленник выходит за пределы контейнера и получает доступ к хост-системе. Контейнерный брейкаут особенно опасен, если хост-система запускает контейнеры с повышенными привилегиями или не настроена должным образом для изоляции.
Как неправильная конфигурация может привести к брейкауту?
Основные уязвимости, которые могут привести к брейкауту, часто связаны с конфигурацией безопасности и прав доступа. Вот ключевые ошибки конфигурации, которые повышают риск контейнерного брейкаута:
— Запуск контейнеров с правами суперпользователя (root): Контейнеры, запущенные с правами root, имеют доступ к большему числу системных ресурсов хоста. Это делает возможной эксплуатацию уязвимостей для получения доступа к хосту. Например, если злоумышленник получает root-доступ в контейнере, он может потенциально использовать уязвимости в драйверах или ядре, чтобы выйти за пределы контейнера.
— Привилегированные контейнеры: Контейнеры, запущенные с флагом --privileged, получают прямой доступ к ресурсам хост-системы, включая устройства, файлы и т.д. Этот режим практически снимает изоляцию контейнера, что делает его крайне уязвимым.
— Монтирование сокета Docker: Если контейнеру предоставлен доступ к сокету Docker (например, /var/run/docker.sock), злоумышленник может использовать его для управления другими контейнерами и даже для запуска новых контейнеров на хосте. Сокет Docker предоставляет API для управления контейнерами, и, обладая доступом к нему, злоумышленник может выполнить команды на уровне хост-системы.
— Монтирование файловой системы хоста: Разрешение контейнеру монтировать критические файлы и директории хоста, такие как /etc или /root, предоставляет злоумышленнику доступ к конфиденциальным данным и настройкам. Например, если контейнер может монтировать /proc или /sys, злоумышленник может получить доступ к информации о процессах хост-системы и даже к некоторым интерфейсам управления ядром.
— Отсутствие ограничений на системные вызовы: Политики безопасности, такие как seccomp (Security Computing Mode), позволяют ограничить доступ контейнеров к системным вызовам ядра. Без seccomp и подобных политик злоумышленник может использовать уязвимые системные вызовы для выхода за пределы контейнера и доступа к хосту.
Примеры контейнерных брейкаутов
CVE-2019-5736: Уязвимость в runc
Эта уязвимость была обнаружена в контейнерном runtime-инструменте runc, который является базой для Docker и Kubernetes. Злоумышленник мог воспользоваться уязвимостью, чтобы подменить бинарный файл runc внутри контейнера и выполнить произвольный код на уровне хост-системы. Для эксплуатации этой уязвимости злоумышленнику нужно было иметь возможность запускать контейнеры или монтировать определенные директории.
— Как это происходит: Злоумышленник изменяет бинарный файл runc, используемый контейнером. При следующем запуске контейнера система выполняет подмененный runc, что позволяет злоумышленнику выполнять команды от имени хост-системы.
— Защита: Обновление до защищенной версии runc, запуск контейнеров с минимальными привилегиями и ограничение доступа к сокету Docker.
Монтирование Docker сокета
Контейнеры, которым предоставлен доступ к /var/run/docker.sock, могут выполнять команды Docker на хосте, что позволяет злоумышленнику запускать свои собственные контейнеры с привилегиями на хосте или управлять существующими контейнерами.
— Как это происходит: Злоумышленник запускает команду docker внутри контейнера, подключенного к сокету Docker. Получив доступ, он может, например, запустить привилегированный контейнер, который получит полный доступ к файловой системе хоста.
— Защита: Не предоставлять контейнерам доступ к Docker сокету, если это не абсолютно необходимо.
Рекомендации по безопасности для предотвращения брейкаута
— Запуск контейнеров с минимальными привилегиями: По возможности, избегайте запуска контейнеров с правами root. Используйте флаги --user или специальные политики безопасности для ограничения прав внутри контейнера.
— Ограничение прав доступа с помощью seccomp и AppArmor: Настройка профилей безопасности seccomp и AppArmor позволяет изолировать контейнеры от потенциально опасных системных вызовов.
— Использование сетевых пространств имен (Namespaces): Используйте различные пространства имен, такие как user namespace, которые создают дополнительный уровень изоляции, ограничивая видимость процессов и ресурсов на уровне хост-системы.
— Сканирование образов на наличие уязвимостей: Проводите регулярное сканирование образов с помощью инструментов, таких как Trivy и Clair, чтобы вовремя обнаружить уязвимые версии библиотек и зависимостей.
— Регулярное обновление и тестирование контейнерных образов: Убедитесь, что базовые образы и используемые библиотеки всегда обновлены до последних безопасных версий.
Контейнерный брейкаут — это одна из самых опасных угроз для контейнеризированных сред. Неправильная конфигурация, запуск контейнеров с привилегиями и слабая политика безопасности — все это повышает риск выхода контейнера за пределы изоляции и компрометации хост-системы. Системные администраторы и разработчики должны учитывать лучшие практики и регулярно пересматривать конфигурации контейнеров, чтобы минимизировать эти риски.
Стартовый курс для администраторов и инженеров, которые хотят освоить основы работы с k8s — «Kubernetes База»
Продвинутый курс для тех, кто уже работал с k8s и хочет повысить компетенции с точки зрения развертывания и сопровождения кластеров K8s — «Kubernetes Мега»
amarkevich
базой должно быть понимание того, что благодаря CRI в K8S Docker не является рантаймом по умолчанию, и большинство упомянутых уязвимостей не будет актуально при использовании другого рантайма