Современная безопасность контейнерных приложений
Чем раньше команда задумается о проблеме безопасности, тем лучше. В этой статье обсудим, какие проблемы ИБ есть в стандартном контейнерном приложении, поговорим о безопасности использования Docker, Kubernetes и Terraform и разберём, как можно встроить проверки в стандартный пайплайн деплоя.
Материал написан и дополнен по мотивам выступления Любови Гринкевич и Алексея Миртова из Yandex Cloud на DevOpsConf. Он будет интересен DevOps-инженерам, специалистам по безопасности, владельцам продуктов и всем, кто хочет:
научиться строить безопасный деплой,
автоматизировать проверки безопасности,
понимать проблемы и обсуждать их в команде.
Если вы столкнулись с новыми реалиями и требованиями безопасности и не знаете, с чего начать, эта статья может вам пригодиться. В качестве примеров будем рассматривать продукты и инфраструктуру Yandex Cloud, но большинство рекомендаций универсальны и не привязаны к конкретным сервисам.
Проблемы безопасности и pipeline разработки
Пайплайн и проблема его уязвимости начинается с человека. Разберём по уровням.
Есть разработчик, и он уязвим уже сам по себе. На его рабочей машине стоят различные клиенты, которые можно взломать: Telegram, GitHub-аккаунт, почтовый клиент.
Затем появляется код и его стандартная проблема безопасности — некорректно написанные строки. Такой код по ошибке может содержать секреты, пароль от БД, которые свободно лежат в GitHub.
Далее — Docker-образ. В нём со временем появляются недоступные или уязвимые компоненты. Так происходит, потому что кроме приложения в нём могут появиться дополнительные части: операционная система, бинарники и утилиты. Наконец, сам Docker-файл — это тоже код, который можно легко взломать.
Поскольку мы говорим про контейнерную разработку, то от Docker переходим к Kubernetes. Здесь разработчик неизбежно сталкивается с тем, что в кластер нужно положить какие-то секреты. Причём таким способом, чтобы их не было видно каждому. Kubernetes — большая система, в которой много взаимодействующих сервисов, а значит между ними нужно настраивать права. Это нужно сделать аккуратно, как с точки зрения сервиса идентификации и контроля доступа (IAM), так и с точки зрения сетевых доступов.
Следом идёт нода. Если в контейнере могут быть компоненты, за которые мы не отвечаем, то нода в Kubernetes — это набор компонентов, про которые мы можем вообще ничего не знать, но которые могут содержать уязвимости.
Само приложение тоже можно атаковать — путём DDoS или атак со стороны веб.
Когда разработчик всё завернул в Kubernetes, пайплайн не заканчивается. Есть параллельный пайплайн, где какие-то дополнительные части, например, тот же Kubernetes-кластер, разворачиваются через Terraform или другой IAC. Здесь нужно аккуратно работать с Local State и создавать облачные объекты, чтобы в них тоже всё было настроено безопасно.
И завершающая часть — настройка CI/CD. Здесь возникают вопросы, как настроить права, обработать проблему недоступных компонентов, настроить Docker и защитить GitLab или GitHub от DDoS-атак.
Получилась схема, на которой стандартный мир DevOps и его пайплайн соединены с проблемами безопасности.
Важность тех или иных проблем безопасности зависит от конкретного продукта. Обсудим наиболее интересные.
Недоступные компоненты
Есть популярная табличка от Техдирского Клуба о том, какие новые вредоносные программы, шифровальщики и риски отказа в обслуживании появляются в связи с последними событиями.
Если мы хотим защититься от риска, что новые версии пакетов содержат внедрённый код, есть несколько возможностей:
поставить на паузу обновления: не запрещать их вообще, но изучить внимательно и подумать, что в них может содержаться;
зеркалировать репозитории;
проверять обновления перед установкой и держать у себя только доверенную, надёжную версию.
Также важно помнить — нельзя, чтобы сборки зависели от внешних ресурсов. Невозможно полагаться на другого человека, рассчитывая, что он будет поддерживать этот ресурс всегда. Или рассчитывать на GitHub, который может упасть и подвести в неподходящий момент.
В команде Yandex Cloud выделили компоненты с самыми большими рисками: Terraform, Packer, Docker, Linux repos, языковые пакеты (pypi, npm, artifactory, golang, proxy, binaries).
Terraform — инструмент, важный и разработчикам, и DevOps-командам, которые с его помощью разворачивают инфраструктуру и различные инструменты в облаке. Это наиболее опасный компонент в контексте доступности, потому что без hashicorp-releases не работает Terraform Plan и Terraform Apply. Способ решения — зеркало, которое создали в Yandex Cloud для собственных и клиентских потребностей. Его можно использовать и в других проектах.
Риски, которые не реализовались, но по-прежнему существуют, касаются недоступности Docker Hub, Linux-репозиториев, языковых пакетов. Для них в Yandex Cloud также есть зеркала Linux mirror. Их использование уже закреплено во внутренней политике.
Общий алгоритм работы с недоступными компонентами может быть таким:
Идентифицировать, что вы защищаете и чего боитесь.
Просчитать риски.
Подсветить уязвимые места также можно с помощью учений. На этом основании уже можно говорить с руководителями, DevOps, разработкой. У них полезно узнать, какие проблемы они видят помимо уже обозначенных, и посмотреть предметно: от каких лицензий и репозиториев вы зависите, где у вас есть сетевой доступ.
Принять решение по рискам.
Риск можно закрыть: сделать зеркало, воспользоваться уже существующим решением, придумать новое, — либо отложить на какое-то время, если он не очень критичный.
Научиться жить герметично.
Важно оценивать стоимость работы и вкладываться в действительно важное. Не все риски нужно закрывать, некоторые так и остаются частью технического долга.
Уязвимые компоненты в Docker-образе
Переходим в уютный мир Docker и смотрим, какие компоненты уязвимы.
В 2020 году компания Prevasio провела исследование четырёх миллионов образов с Docker Hub и обнаружила, что больше половины из них содержит критичные уязвимости. А в 2022 году согласно исследованию CNCF (Cloud Native Computering Foundation), порядка 64% компаний уже перевели в контейнеры — Docker или Kubernetes — свою инфраструктуру. При этом, по результатам исследования RedHat, 94% IT-специалистов сталкивались хотя бы с одним инцидентом безопасности, связанным с контейнерами. По данным RedHat, половина DevOps-инженеров и специалистов по ИБ даже откладывали развертывание приложений из-за проблем с безопасностью.
Из этого вывод — важно сканировать образы и знать, что находится внутри. Для этого есть масса сканеров, которые могут быть как встроены в облака, так и установлены отдельно. Примеры:
On-premise: Aqua Security, Clair, Anchore, JFrog Xray.
Managed: Snyk, Qualys, GCP, Yandex Cloud, Azure, AWS.
В Yandex Cloud сервисом для хранения Docker-образов является Container Registry. В нём есть встроенный сканер уязвимостей: он позволяет провести статический анализ Docker-образа на наличие уязвимостей в компонентах, библиотеках и зависимостях, которые используются в нём, а также сравнить содержимое с базами уязвимостей CVE. Сканер уязвимостей работает только с Docker-образами из Container Registry. Пользователь может сканировать те Docker-образы, на которые у него есть права. При сканировании происходит распаковка Docker-образа и поиск версий установленных пакетов (deb). Затем найденные версии пакетов сверяются с базой данных известных уязвимостей.
Вы также можете встроить сканирование в свой пайплайн, для того чтобы иметь возможность остановить деплой образа с критическими уязвимостями. На вебинаре «Как выстроить пайплайн безопасной разработки» можно узнать рекомендации команды Yandex Cloud о том, как это правильно сделать.
Защита Docker-образа
Помимо сканирования, мы можем добавить изменения в Docker-файл. Например, обновить пакеты, чтобы устранить известные уязвимости. Сканер уязвимостей показывает название и версию уязвимого пакета и версию исправленного пакета.
Дальше перейдём к Kubernetes, рантайму и запуску приложения.
Избыточные права или сетевые доступы
Прежде чем опубликовать приложение, готовим сетевые политики — Network Policy. Это нужно, чтобы избежать избыточных сетевых доступов.
Для построения Network Policy существует много CNI-плагинов. В этой статье поговорим про Cilium. Он использует eBPF — продвинутые политики, которые можно строить вплоть до вызовов API.
Ещё в Cilium есть такая классная вещь, как UI-интерфейс для построения сетевых политик: можно не описывать их текстом, а накликать в приятном интерфейсе и затем применить в Kubernetes. Также этот инструмент позволяет выгружать логи сетевых подключений — flow-логи.
В библиотеке решений по безопасности Yandex Cloud есть реализация DaemonSet. Он ставится в каждую ноду с приложением и загружает flow-логи в любое облако, в котором есть API, совместимое с AWS S3.
Для чего это делать? Например, так можно обнаружить популярную уязвимость Log4Shell. Если сетевой трафик содержит определённый паттерн поведения, например, обращение к внешнему LDAP-серверу через JNDI, это может быть эксплуатацией Log4Shell. Собранные логи можно отправлять в систему управления конфигурацией, такую как Splunk, Elastic и другие, и использовать для построения детекторов уязвимостей.
Бюллетени безопасности
Когда обнаруживается новая уязвимость, облачные провайдеры выпускают бюллетени безопасности. Но может возникнуть промежуток времени, когда провайдер ещё не устранил уязвимость или клиент не может сразу обновиться. На этот случай специалисты Yandex Cloud публикуют как бюллетени безопасности, так и рекомендации по исправлению. Это можно использовать до официального обновления.
DDoS-атаки
Про DDoS-атаки многие знают, но мало кто защищается. Даже клиенты, как правило, не видят в этом серьёзного риска, и только когда их атакуют, просят срочно включить защиту.
Если смотреть на квартальную динамику атак за последние годы, видно, что массовый пик атак был в 2020 году, когда началась пандемия и все ушли в Интернет. В марте 2022 года ещё один резкий пик — причина его понятна.
В 2023 году количество DDoS-атак также росло. По разным экспертным оценкам, рост DDoS за 2023 год составил от 60%: например, Cloudflare говорят о годовом росте атак сетевого уровня на 85% и снижении HTTP-DDoS на 20%.
На графиках выше — не только DDoS, но и веб-атаки на приложения. Для каждой атаки у разных провайдеров свои способы защиты:
Защита отдельно от переполнения ёмкости каналов, когда канал хотят атаковать на уровне сети.
Защита на уровне приложений от атак, наподобие HTTP Flood и подобных.
Защита от веб-атак из списка OWASP топ-10 и других. От них обычно защищают Web Application Firewall — заветная аббревиатура WAF, которую не всегда знают разработчики.
В Yandex Cloud есть сервисы для защиты от DDoS-атак:
Yandex DDoS Protection в партнерстве с Qrator Labs.
Yandex Smart Web Security — собственный сервис защиты от DDoS, который находится сейчас в стадии ограниченного Preview. В 2023 году инженеры Яндекса усовершенствовали лежащую в основе технологию Smart Protection, которая использует алгоритмы машинного обучения с учётом 20 тысяч факторов.
Ещё один механизм защиты от DDoS — использовать Content Delivery Network (CDN). Если раздавать статический контент с помощью CDN, то появится множество кэширующих серверов по всему миру. Их невозможно одновременно подвергнуть DDoS-атаке, так мы получаем отказоустойчивость.
Опасности Terraform
Мы уже поговорили о рисках недоступности Terraform. Здесь также важно защитить данные и системы от угроз.
В библиотеке Yandex Cloud есть готовый чек-лист безопасности Terraform. В нём по пунктам перечислены принципы работы со State и секретами, когда вы используете Terraform.
Terraform remote state Object Storage
К примеру, известно, что не надо хранить State на ноутбуке, а лучше в облачном хранилище или другом удалённом источнике для надёжности.
Пример, как хранить Terraform State с помощью сервисов Object Storage и Database Serverless
Многие знают, что Terraform State можно хранить в Yandex Cloud. Но не все знают, что нужно защищать и то место, куда вы отправляете State. Если, например, Bucket в S3 не зашифрован, не логируется и всем доступен, то ваш State может утечь из-за каких-то чувствительных данных.
Пример безопасной конфигурации Yandex Cloud Object Storage: Terraform
В качестве решения, чтобы обеспечить безопасность хранения Terraform в Bucket, можно установить его уже с Bucket Policy, с логированием, с шифрованием на основе KMS и с защитой от удаления.
Безопасность IAC
Также важно защищать и Terraform-манифесты. DevOps-инженеры или разработчики могут создавать Bucket публичного доступа или Kubernetes-кластер, в котором нет секьюрити-группы, чтобы защититься от различных сетевых атак. Для этого есть несколько решений и есть статья, где эти решения сравниваются.
К примеру, есть Checkov — бесплатный опенсорс-инструмент, который позволяет сканировать не только Terraform-манифесты, но и Helm charts, Docker-файлы. Вы можете встраивать его в CI/CD-пайплайн и на этапе деплоя отвергать опасные объекты.
Это решение можно встроить в GitLab. Подробнее об этом — в инструкции от Алексея Миртова. В Checkov поддерживаются разные облака — и AWS, и Alibaba Cloud, и Yandex Cloud, и другие контрибьюторы. А ещё есть платные расширения.
Чтобы встроить решение в GitLab, нужно зайти в библиотеку решений на GitHub и взять решение сканирования Terraform-объектов с помощью Checkov.
В библиотеке — полное описание того, как всё работает, и можно отдельно раскрыть список проверок. Он довольно большой. К примеру, можно проверить: назначена ли секьюрити-группа на кластер базы данных, не назначен ли публичный API-адрес на Kubernetes-кластер или есть привилегированные права на сервисный аккаунт — вещи, в которых разработчик или DevOps-инженер могут ошибиться или использовать сознательно со злым умыслом.
Для использования Checkov в Managed Service for GitLab есть три режима:
Blocking mode — режим, в котором блокируется пайплайн, если Checkov обнаружит, что проверка не прошла.
Audit mode.
Blocking mode with specific checks in audit mode — смешанный режим, когда можно исключить конкретные проверки.
На старте лучше использовать режим аудита, чтобы сначала всё обкатать, и только потом внедрять в режиме блокировки.
Безопасность CI/CD
CI/CD-система — важная часть инфраструктуры. Кроме задач, связанных с тестированием, сборкой и доставкой приложения, в ней есть привилегированный доступ к другим критически важным системам. Это тоже нужно защищать.
Есть матрица атак на CI/CD. В ней указано, как получить первоначальный доступ и как продвигаться дальше. С помощью этой матрицы можно моделировать угрозы и действия нарушителя применительно к кейсу любой компании.
Также можно использовать оформленный командой Yandex Cloud чек-лист с рекомендациями по настройке безопасности инстанса GitLab. В нём прописано, как работать с Docker-конфигурациями, с Kubernetes-интеграциями, как правильно настроить 2FA, rate limits. Шаг за шагом можно пройти по чек-листу и убедиться, что ваш GitLab настроен корректно.
Ещё одна важная вещь — это когда разработчики выкладывают секреты в открытые репозитории. Пентестеры часто взламывают инфраструктуру, только загуглив приложение на GitHub, и находят credentials от продакшн-систем прямо в репозиториях.
Какие типы секретов отслеживают в команде Yandex Cloud:
В GitLab есть механизм Secret Detection, он доступен в бесплатной версии — нужно только явным образом его включить. В репозитории есть большая портянка регулярных выражений разных систем и секретов. Если вы включите механизм и после этого кто-то выложит ваш секрет, то в GitLab вы увидите: «Такой-то yaml-токен скомпрометирован, пожалуйста, поменяйте его».
В GitHub тоже есть своя программа поиска секретов в репозиториях. Обычно она работает автоматически, её не надо включать.
Там же есть контрибьют от Yandex Cloud. Теперь если кто-то выложит секреты облака, владельцу придёт письмо об утечке данных из аккаунта: «Уважаемый клиент, вы выложили credentials в открытый доступ. Пожалуйста, поменяйте их».
Важный момент: даже если вы удалите из репозитория этот секрет, то он всё равно останется в истории и будет доступен. Но есть инструкция от GitHub о том, как удалять чувствительные данные.
Выводы
Может показаться, что если настроить все проверки, то точно всё станет хорошо. На самом деле нужно помнить, что каждая из проверок защищает лишь какую-то маленькую часть инфраструктуры, или специфичный случай. Следует всегда пересматривать сделанные выводы и смотреть на систему целиком: как она работает, какие риски и как их закрывать.
Чтобы настроить защиту и покрыть как можно больше потенциальных проблем, пройдите по шагам:
Постройте диалог между DevOps и безопасником. DevOps-команда больше всего знает внутрянку и архитектуру системы: компоненты, CI/CD, работу доступа на уровне продакшн-системы, кто может деплоить, а кто нет. Задача диалога — совместно оценить риски в архитектуре, что можно поменять, а что закрыть дополнительными проверками.
Встройте статические проверки в CI. Часть этих проверок можно автоматизировать и встроить в пайплайн.
Добавьте алерты о странных действиях в вашем кластере. Настройте динамические алерты о том, что кто-то зашёл в кластер, совершил какое-то опасное действие.
Посмотрите, какие встроенные средства есть у вашего облачного провайдера и какие рекомендации он даёт. Это могут быть как просто рекомендации по безопасности, так и встроенные инструменты защиты.
Обращайте внимание на защиту не только сервиса, но и инфраструктуры вокруг него. Не стоит забывать про разработчиков, CI/CD и другие потенциальные объекты защиты.
Постройте модель, которая поможет быстро реагировать на новые угрозы.
В целом нужно понимать, что безопасность — это процесс. Невозможно построить безопасную систему, если вы проходите аудит один раз в год и потом ничего не делаете. К сожалению или к счастью, мир меняется быстрее. Поэтому риски нужно пересматривать чаще, а для этого нужна другая модель.