Главная » Хабрахабр » [Перевод] 11 способов (не) стать жертвой взлома в Kubernetes

[Перевод] 11 способов (не) стать жертвой взлома в Kubernetes

Прим. перев.: Оригинал этой статьи был опубликован в официальном блоге Kubernetes и написан Andrew Martin — одним из основателей молодой британской компании Control Plane, специализирующейся на безопасности для cloud native-приложений, запускаемых в K8s.

Предлагаем список полезных рекомендаций по тому, как защитить кластеры и повысить их устойчивость в случае взлома: начнём с control plane, продолжим с рабочими нагрузками и сетевой безопасностью, а закончим оценкой будущего безопасности. Безопасность в Kubernetes прошла длинный путь с момента появления проекта, однако в ней по-прежнему встречаются подводные камни.

Часть 1: Control Plane

Control plane — это мозг Kubernetes. Он имеет общее представление о каждом контейнере и поде, запущенном в кластере, может планировать новые поды (в которых могут находиться контейнеры с root-доступом к своим родительским узлам) и может считывать все секреты, хранимые в кластере. Это очень важный компонент, нуждающийся в постоянной защите от случайной утечки данных и злонамеренных действий: и в то время, когда к нему обращаются, и когда ничего не происходит, и когда данные передаются по сети.

1. Повсеместный TLS

Для каждого компонента, поддерживающего TLS, он должен быть включён — для предотвращения сниффинга трафика, удостоверения идентичности сервера и (в случае Mutual TLS) удостоверения идентичности клиента.

«Обратите внимание, что некоторые компоненты и методы инсталляции могут активировать локальные порты для HTTP, поэтому администраторам необходимо ознакомиться с настройками каждого компонента, чтобы выявить возможные пути для небезопасного трафика».

Из документации Kubernetes

Приведённая ниже сетевая диаграмма от Lucas Käldström демонстрирует, где в идеале необходимо применение TLS: между каждым компонентом на мастере, а также между Kubelet и сервером API. Ставший классикой «Kubernetes The Hard Way» от Kelsey Hightower и документация по безопасности в etcd предлагают подробные инструкции для достижения этих целей.

Kubelet TLS bootstrapping обеспечивает возможность новому Kubelet'у создавать запрос на подпись сертификата, чтобы сертификаты генерировались во время загрузки: Исторически автоматическое масштабирование узлов Kubernetes складывалось непросто, поскольку каждый узел требовал TLS-ключа для подключения к мастеру, а хранение секретов в базовых образах — плохая практика.

2. Минимальные привилегии в RBAC, отключение ABAC, мониторинг логов

Управление доступом на основе ролей (RBAC) обеспечивает тонкое управление политиками, по которым пользователи получают доступ к таким ресурсам, как пространства имён.

6 и не должна быть включена на стороне сервера API. Система управления доступом на основе атрибутов (ABAC, Attribute Based Access Control) в Kubernetes была заменена на RBAC с релиза K8s 1. Используйте RBAC вместо неё: --authorization-mode=RBAC (или этот флаг для GKE: --no-enable-legacy-authorization).

Но не стоит этим ограничиваться: грамотные настройки для RBAC-политик можно получить с помощью audit2rbac из логов audit. Есть множество хороших примеров политик RBAC для различных сервисов в кластере, а также документация.

Поддержка правил RBAC с минимальными привилегиями, их постоянный аудит и улучшение должно стать частью «гигиены технического долга», которую команды применяют в жизненном цикле разработки. Неправильные или излишне разрешающие политики RBAC — угроза безопасности в случае компрометации пода.

10) предлагает настраиваемый API для логирования для рабочих нагрузок (например, запроса и ответа на него) и на уровне метаданных. Audit logging (бета-версия в Kubernetes 1. Уровень логирования может быть настроен в соответствии с принятой в организации политикой безопасности — GKE применяет разумные значения по умолчанию для тех, кто только начинает с ним работать.

Для запросов, затрагивающих конфиденциальные данные вроде Secret или ConfigMap, экспортируются только метаданные. Для запросов на чтение, таких как get, list и watch, в audit-логах сохраняется только запрашиваемый объект, без ответного объекта. Для всех остальных запросов в audit-логи записываются оба объекта: и запрос, и ответ.

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

3. Используйте стороннюю аутентификацию для API Server

Централизация аутентификации и авторизации для всей организации (т.е. Single Sign On) помогает в процессах принятия и ухода новых сотрудников, обеспечении консистентных прав доступа.

Интеграция Kubernetes со сторонними поставщиками аутентификации (вроде Google или GitHub) обеспечивает гарантии идентичности от удалённой платформы (с защитой вроде двухфакторной аутентификации) и избавляет администраторов от необходимости перенастраивать сервер API в Kubernetes для добавления/удаления пользователей.

0 с подключаемыми «разъёмами» (connectors). Dex — провайдер OpenID Connect Identity (OIDC) и OAuth 2. Компания Pusher пошла ещё дальше, предоставив настраиваемый инструментарий, в дополнение к которому есть и некоторые другие помощники, ориентированные на иные случаи применения.

4. Отделите и поместите за firewall свой кластер etcd

etcd хранит информацию о состоянии Kubernetes и секретах, является критичным компонентом K8s — он должен быть защищён отдельно от остального кластера.

Доступ на запись в etcd у сервера API равнозначен выдаче root-прав на весь кластер, да и даже доступ на чтение может быть легко использован для эскалации привилегий.

Затем он отправляет все найденные поды на доступный Kubelet для планирования. Планировщик Kubernetes именно в etcd ищет определения пода, у которых нет узла. Валидация этих подов производится сервером API перед тем, как записывать их в etcd, поэтому злоумышленники, напрямую пишущие в etcd, могут обойти множество механизмов безопасности — например, PodSecurityPolicies.

Для снижения риска кражи и использования приватных ключей с рабочих узлов можно также ограничить firewall'ом API Server кластера. etcd должен быть настроен с обоими TLS-сертификатами (client и peer) и деплоиться на выделенные узлы.

5. Ротация ключей шифрования

Регулярная ротация ключей безопасности и сертификатов — лучшая практика в безопасности, позволяющая ограничить «радиус поражения» при компрометации ключа.

Kubernetes будет автоматически ротировать некоторые сертификаты (в частности, клиентский и серверный сертификаты Kubelet) созданием новых CSR по истечении времени действия текущих.

Для данной операции требуется доступ уровня master, поэтому управляемые сервисы (вроде GKE и AKS) прячут проблему от пользователя. Однако симметричные ключи, используемые сервером API для шифрования значений etcd, не ротируются автоматически — это нужно делать вручную.

Часть 2: рабочие нагрузки

При обеспечении минимальной безопасности на уровне control plane кластер уже может функционировать безопасно. Однако, как и для корабля с потенциально опасным грузом, контейнеры такого судна должны защитить груз на случай непредвиденной аварии или утечки. То же самое справедливо для рабочих нагрузок в Kubernetes (Pods, Deployments, Jobs, Sets и т.п.) — им можно доверять на момент деплоя, но, если они доступны извне, всегда есть риск, что впоследствии ими воспользуются [злоумышленники]. Снижению этого риска может способствовать запуск рабочих нагрузок с минимальными привилегиями и их безопасной конфигурацией.

6. Используйте фичи безопасности в Linux и PodSecurityPolicies

У ядра Linux есть множество частично перекрывающих друг друга расширений безопасности (capabilities, SELinux, AppArmor, seccomp-bpf), которые можно настроить так, чтобы предоставлять приложениям минимальные привилегии.

Утилиты вроде bane помогут сгенерировать профили для AppArmor, а docker-slim — профили seccomp, но будьте осторожны: для выявления всех побочных эффектов применения этих политик требуется всесторонний набор тестов, проверяющий весь код приложения.

Они отвечают за минимальные требования, которым должен соответствовать под, чтобы попасть на сервер API, включая профили безопасности, флаг привилегированности, совместное использование сети хоста, процессов или пространств имён для IPC. PodSecurityPolicies регулируют использование этих расширений безопасности, а также других директив безопасности Kubernetes.

Пример PodSecurityPolicy от Tim Allclair весьма универсален — его можно взять за основу и поднастроить под свой случай. Эти директивы важны, потому что помогают предотвратить выход контейнеризированных процессов из их изолированных границ.

7. Проводите статический анализ YAML

Если PodSecurityPolicies ограничивают доступ к серверу API, то статический анализ можно также использовать в процессе разработки для моделирования нормативных требований организации и склонности к риску.

Чувствительная информация не должна храниться в YAML-ресурсах вроде подов (Pods, Deployments, Sets и т.п.), а чувствительные ConfigMaps и Secrets необходимо шифровать утилитами вроде Vault (с оператором от CoreOS), git-crypt, sealed secrets или KMS облачного провайдера.

kubesec генерирует оценки риска для ресурсов: Статический анализ YAML-конфигурации может использоваться как основа для обеспечения безопасности во время запуска.

], "advise": [{ "selector": "containers[] .securityContext .runAsNonRoot == true", "reason": "Force the running image to run as a non-root user to ensure least privilege" }, { "selector": "containers[] .securityContext .capabilities .drop", "reason": "Reducing kernel capabilities available to a container limits its attack surface", "href": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/" }] }
}

А kubetest — фреймворк для модульного тестирования конфигураций Kubernetes:

#// vim: set ft=python:
def test_for_team_label(): if spec["kind"] == "Deployment": labels = spec["spec"]["template"]["metadata"]["labels"] assert_contains(labels, "team", "should indicate which team owns the deployment") test_for_team_label()

Эти утилиты реализуют подход «shift left» (т.е. перемещают проверки и верификацию на ранние этапы цикла разработки). Тестирование безопасности на этапе разработки даёт пользователям быструю обратную связь по коду и конфигурации, которые могут быть в дальнейшем отклонены ручной или автоматизированной проверкой, а также может облегчить введение дополнительных практик по безопасности.

8. Запускайте контейнеры не под root

У контейнеров, которые запускают с правами root, зачастую намного больше прав, чем того требуют их рабочие нагрузки, а в случае компрометации они помогают атакующим добиться больших возможностей.

Контейнеры по-прежнему опираются на традиционную модель безопасности UNIX (называемую DAC, discretionary access control) — всё есть файл, а права выдаются пользователям и группам.

Это означает, что таблица пользовательских ID в контейнере отображается на таблицу пользователей хоста, и запуск процесса с правами root внутри контейнера приводит к его запуску с правами root на хосте. Пространства имён для пользователей не работают в Kubernetes. Хоть ко всему этому и добавляются механизмы, предотвращающие выход из пределов контейнера, запуск с правами root внутри контейнера не рекомендуется.

Многие образы контейнеров используют пользователя root для запуска PID 1: если этот процесс скомпрометирован, злоумышленник получает root в контейнере и при любой ошибке в конфигурации эксплуатация проблемы становится значительно проще.

В Bitnami проделали большую работу по переводу своих образов контейнеров на обычных (не root) пользователей (к тому же, это требование OpenShift по умолчанию), что может упростить и вашу миграцию на образы, не использующие права root.

Этот фрагмент PodSecurityPolicy предотвращает запуск процессов с правами root в контейнере и эскалацию до root'а:

# Required to prevent escalations to root.
allowPrivilegeEscalation: false
runAsUser: # Require the container to run without root privileges. rule: 'MustRunAsNonRoot'

Контейнеры, не использующие root, не могут занимать привилегированные порты, т.е. до 1024 (за это отвечает соответствующая capability в ядре Linux — CAP_NET_BIND_SERVICE), однако использование Services помогает обойти это ограничение. Вот пример для приложения MyApp, которое занимает порт 8443 в контейнере, но Service делает его доступным по порту 443, проксируя запросы на targetPort:

kind: Service
apiVersion: v1
metadata: name: my-service
spec: selector: app: MyApp ports: - protocol: TCP port: 443 targetPort: 8443

Необходимость запуска рабочих нагрузок без использования root будет сохраняться до тех пор, пока в ходу пространства имён для пользователей или же наработки по запуску контейнеров без root не войдут в состав исполняемых сред для контейнеров.

9. Используйте сетевые политики

По умолчанию сеть в Kubernetes разрешает весь трафик между подами. Эту настройку можно ограничить сетевой политикой — NetworkPolicy.

Поскольку эти IP-адреса очень редко меняются, они исторически использовались как вид идентификации. Традиционные сервисы ограничены firewall'ами, использующими статические IP-адреса и диапазоны портов для каждого сервиса. Эти особенности значительно усложняют настройку и проверку работы firewall'ов. У контейнеров редко бывают статические IP — их природа подразумевает возможность быстрого падения и повторного создания, для них вместо статических IP-адресов используется service discovery.

Calico, Cilium, kube-router, Romana и Weave Net — все эти плагины поддерживают сетевые политики. Поскольку Kubernetes хранит все данные о состоянии системы в etcd, возможна настройка динамического firewall'а — если есть необходимая поддержка в сетевом плагине CNI.

Важно заметить, что политики работают по принципу fail-closed, то есть отсутствие podSelector здесь по умолчанию приравнивается ко всем возможным значениям (wildcard):

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: name: default-deny
spec: podSelector:

Далее приведён пример NetworkPolicy, которая запрещает всё от egress кроме UDP 53 (DNS), что также предотвращает входящие подключения к приложению. Политики NetworkPolicies являются stateful, поэтому приложение всё-таки получит ответы на исходящие подключения.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: name: myapp-deny-external-egress
spec: podSelector: matchLabels: app: myapp policyTypes: - Egress egress: - ports: - port: 53 protocol: UDP - to: - namespaceSelector: {}

Сетевые политики Kubernetes нельзя применять к DNS-именам. Причина в том, что DNS поддерживает round-robin на множество IP-адресов и динамические ответы, зависимые от обращающегося IP, так что сетевые политики применяются только к фиксированным IP-адресам или podSelector'ам (для динамических IP-адресов Kubernetes).

Процесс может быть непростым, поэтому в ControlPlane разработали netassert — утилиту для тестирования сетевой безопасности в сценариях DevSecOps с сильно распараллеленным nmap: Лучшая практика — начать с запрета всего трафика для пространства имён и пошагово добавлять маршруты, требуемые приложению для прохождения приёмочного тестирования.


k8s: # used for Kubernetes pods deployment: # only deployments currently supported test-frontend: # pod name, defaults to `default` namespace test-microservice: 80 # `test-microservice` is the DNS name of the target service test-database: -80 # `test-frontend` should not be able to access test-database’s port 80 169.254.169.254: -80, -443 # AWS metadata API metadata.google.internal: -80, -443 # GCP metadata API new-namespace:test-microservice: # `new-namespace` is the namespace name test-database.new-namespace: 80 # longer DNS names can be used for other namespaces test-frontend.default: 80 169.254.169.254: -80, -443 # AWS metadata API metadata.google.internal: -80, -443 # GCP metadata API

API с метаданными от облачного провайдера — постоянный источник потенциальной эскалации (демонстрируется недавним bug bounty от Shopify), так что специальные тесты, подтверждающие блокировку API в сети контейнеров, помогут защититься от ошибок в конфигурации.

10. Сканируйте образы и запустите IDS

Веб-серверы — плацдарм для атаки сетей, к которым они прикреплены. Сканирование файлов, установленных в образы, позволяет убедиться в отсутствии известных уязвимостей, которыми злоумышленник может воспользоваться для получения удалённого доступа к контейнеру. Системы обнаружения вторжений (IDS) фиксируют эти события, если они происходят.

В них каждый под может валидироваться на допуск или меняться его содержимое, в дополнение к чему теперь также поддерживаются webhooks на стороне backend'а. Kubernetes допускает поды в кластер через набор контролирующих проверок (в admission controller), применяемых не только к подам, но и другим ресурсам вроде Deployments.

Образы, не прошедшие проверку, не получат допуск контроллера. Эти webhooks могут использоваться инструментами сканирования образов контейнеров для проверки образов до их деплоя в кластер.

Для предотвращения выкатывания образов с критическими уязвимости в pipeline'е деплоя можно использовать бесплатные утилиты вроде Clair от CoreOS и Micro Scanner от Aqua. Сканирование образов контейнеров на известные уязвимости помогает снизить время, за которое атакующий сможет воспользоваться открытой CVE.

Сканирование образа контейнера с помощью этого хэша равносильно сканированию образов, разворачиваемых в production, и может осуществляться постоянно без необходимости иметь доступ к production-окружениям. Такие инструменты, как Grafeas, позволяют хранить метаданные образа для постоянных проверок на соответствие и уязвимости с помощью уникальной подписи контейнера (или специального контентно-адресуемого хэша).

IDS обнаруживает необычное поведение в контейнере и останавливает или убивает его. Неизвестные 0day-уязвимости всегда будут существовать, поэтому в Kubernetes следует развернуть систему обнаружения вторжений вроде Twistlock, Aqua или Sysdig Secure. Falco от Sysdig — Open Source-движок правил и отправная точка к этой экосистеме.

Часть 3: Будущее

Следующим этапом безопасности в «эволюции cloud native», похоже, будет service mesh, хотя его принятие случится не сразу: эта миграция требует смещения сложности приложений в mesh-инфраструктуру, и организациям предстоит осознать эту лучшую практику.

11. Запустите service mesh

Service mesh — это сеть постоянных зашифрованных соединений, сделанных между «подключёнными сбоку» (по аналогии с «sidecar»), высокопроизводительными прокси-серверами вроде Envoy и Linkerd. Она приносит управление трафиком, мониторинг и политики — и всё это без изменений в микросервисах.

С дополнением в виде SPIFFE для криптографической идентичности каждого пода и множества других возможностей, Istio может упростить развёртывание сетевой безопасности следующего поколения. Перенос из микросервисов кода, связанного с безопасностью и сетями, в разделяемый и проверенный в бою набор библиотек был возможен уже с Linkerd, а появление Istio от Google, IBM и Lyft, принесли альтернативу в это пространство.

В сетях «нулевого доверия» (zero trust) может и не быть потребности в традиционном firewall'е или сетевых политиках Kubernetes, поскольку каждое взаимодействие происходит с использованием mTLS (mutual TLS), что не только гарантирует безопасность взаимодействия, но и подтверждает идентичность обоих сервисов.

В качестве введения в этот новый мир мы очень рекомендуем книгу «Zero Trust Networking» от Evan Gilman из SPIFFE. Этот переход от традиционных сетевых подходов к принципам безопасности мира Cloud Native не будет простым для тех, у кого устоялось традиционное мышление в области безопасности.

8 LTS, и проект быстро приближается к своему релизу 1. На данный момент доступен Istio 0. Версионирование проекта в вопросах стабильности ведётся аналогично модели Kubernetes: стабильное ядро с отдельными API, для которых с помощью пространств имён указывается их статус alpha или beta. 0. Ожидайте увидеть рост распространения Istio в ближайшие месяцы.

Заключение

У приложений категории Cloud Native более детализированный набор легковесных примитивов безопасности, позволяющих защитить рабочие нагрузки и инфраструктуру. Мощность и гибкость таких инструментов — одновременно и благословение, и проклятие: не имея достаточной автоматизации [для их применения], выставить наружу небезопасные приложения, позволяющие выходить за рамки контейнера или их изоляционной модели, стало ещё проще.

Утилит для защиты доступно больше, чем когда-либо, однако для снижения возможностей для атаки и потенциала некорректных конфигураций необходимо пользоваться ими с осторожностью.

Использование принципов Continuous Delivery применительно к цепочке поставки программного обеспечения позволяет организации добиться соблюдения нормативных требований, непрерывного аудита и усиленного управления, не влияя на бизнес-показатели. Если безопасность замедляет скорость организации в доставке изменений, она никогда не станет первоочерёдной.

Оно достигается с Continuous Security — альтернативой заданным определённым временем пентестам с постоянной валидацией в pipeline'е, гарантирующей, что площадь атаки известна, риск всегда понятен и управляем. Быстрое поступательное улучшение безопасности — самый простой путь при наличии всеобъемлющего набора тестов.

P.S. от переводчика

Читайте также в нашем блоге:


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

Сервис для торговли на бирже Robinhood обвинили в продаже данных о заявках пользователей высокочастотным трейдерам

В частности, там утверждается, что сервис, предлагающий пользователям возможность торговли на бирже без комиссий, продает данные о выставляемых ими заявкам высокочастотным трейдерам. Издание о финансах и технологиях Seeking Alpha опубликовало расследование о деятельности финансового стартапа Robinhood. В чем дело Журналисты ...

Удаленное выполнение кода в Microsoft JET Database Engine

 Участник проекта Zero Day Initiative Lucas Leong (Trend Micro) раскрыл подробности о наличии критической уязвимости в Windows, позволяющей удаленно выполнить произвольный код в контексте текущего процесса. Для успешной эксплуатации проблемы потребуется участие пользователя, который должен открыть вредоносный файл или перейти ...