Что будет, если разрешить лишнее при создании подов в Kubernetes? Зависит от того, какие неймспейсы хоста и контексты безопасности разрешены. Здесь мы поговорим о восьми небезопасных конфигурациях подов и методах эскалации привилегий. Эта статья и созданный для нее репозиторий помогут пентестерам и администраторам разобраться в распространенных ошибках конфигурации.


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


Пентестеры получат представление о том, как показать последствия слишком либеральной политики безопасности подов. В репозитории вы найдете для этого готовые манифесты и инструкции.


Краткий обзор


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


Слишком большие привилегии — это вообще частая проблема Kubernetes и других технологий DevOps. В нашем исследовании «Проблемные поды» мы показали, что при использовании Kubernetes в инфраструктуре нужно выяснить у разработчиков, как они настраивают и защищают эту среду.


Защита подов: что может натворить один атрибут?


Любой эксперт по безопасности Kubernetes скажет, что при подготовке подов нужно использовать принцип наименьших привилегий. Но как выполнить детальную настройку и оценить риск каждого атрибута?


Администратор Kubernetes может реализовать принцип наименьших привилегий с помощью контроллеров допуска. Это может быть, допустим, встроенный контроллер PodSecurityPolicy или популярный сторонний контроллер OPA Gatekeeper. Контроллеры допуска запрещают поду доступ в кластер, если у него больше разрешений, чем предписано политикой.


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


Пентестеры часто получают доступ к созданию подов на кластере, где не действует никакая политика. Это я называю легким уровнем сложности. Используем этот манифест от Рори МакКьюна (Rory McCune) (@raesene), эту команду от Даффи Кули (Duffie Cooley) (@mauilion) или плагин node-shell krew — и вот уже можно интерактивно выполнять код в привилегированном режиме на хосте. Проще уже не придумаешь.


А что если создавать поды можно только с hostNetwork, hostPID, hostIPC, hostPath или privileged? Что будет в каждом случае? Сейчас узнаем.



Проблемные поды: атрибуты и их худшие последствия


Я расположил проблемные поды по мере убывания рисков. Атаки, которым подвержены любые поды Kubernetes (например, проверка доступа пода к сервису метаданных облачного провайдера или поиск неправильно настроенного Kubernetes RBAC) описаны в разделе Проблемный под 8: все запрещено.


Проблемные поды:


Поды


Проблемный под 1: все разрешено


Проблемный под 2: Privileged и hostPid


Проблемный под 3: только Privileged


Проблемный под 4: только hostPath


Проблемный под 5: только hostPid


Проблемный под 6: только hostNetwork


Проблемный под 7: только hostIPC


Проблемный под 8: все запрещено.


Проблемный под 1: все разрешено



Что произойдет в худшем случае?


Много всего.


Как?


Созданный под монтирует файловую систему хоста к поду. Проще всего будет создать под в ноде control-plane с помощью селектора nodeName в манифесте. Потом можно выполнить в поде exec и сделать chroot для каталога, где примонтирована файловая система хоста. Теперь у нас есть права root в ноде, где запущен наш под.


  • Читаем секреты из etcd. Если мы запускаем под на ноде control-plane с помощью селектора nodeName в спецификации пода, мы легко получаем доступ к базе данных etcd, где хранится вся конфигурация кластера, включая секреты.
  • Ищем токены привилегированных учеток сервисов. Даже если удалось запустить под только на рабочей ноде, мы все равно можем получить доступ к секретам всех подов на этой ноде. В продакшен-кластере даже на рабочей ноде всегда есть хотя бы один под с токеном, который привязан к учетке сервиса, связанной с clusterrolebinding, так что мы можем, например, создавать поды или просматривать секреты во всех неймспейсах.

Больше схем эскалации привилегий см. в файле README (ниже) и в разделе Проблемный под 4: hostPath.


Примеры использования


https://github.com/BishopFox/badPods/tree/main/manifests/everything-allowed


Дополнительные материалы



Проблемный под 2: privileged и hostpid



Что произойдет в худшем случае?


Много всего.


Как?


Единственное отличие от предыдущего варианта — способ получения root-доступа к хосту. Там мы делали chroot для файловой системы хоста, а здесь используем nsenter, чтобы получить права root для ноды, где запущен наш под.


Почему это работает?


  • Privileged. Контекст безопасности privileged: true на уровне контейнера ломает почти любые преграды, которые по идее должен давать контейнер для защиты от атак. Остается разве что неймспейс PID. Без hostPID nsenter сможет входить только в неймспейсы процесса, который запущен в контейнере. Больше примеров действий, которые можно совершить с privileged: true, см. в следующем разделе — Проблемный под 3: только Privileged.


  • Privileged + hostPID. Если одновременно задать hostPID: true и privileged: true, поду будут доступны все процессы на хосте, и мы сможем войти в систему init (PID 1) на хосте. А там уже можно запустить shell на ноде.



С root-доступом на хосте у нас есть те же пути эскалации привилегий, о которых мы говорили в разделе Проблемный под 1: все разрешено.


Примеры использования


https://github.com/BishopFox/badPods/tree/main/manifests/priv-and-hostpid


Дополнительные материалы



Проблемный под 3: только privileged



Что произойдет в худшем случае?


Много всего.


Как?


С privileged: true у нас два пути:


  • Примонтировать файловую систему хоста. В привилегированном режиме /dev на хосте будет доступен нашему поду. Мы можем примонтировать к нашему поду диск с файловой системой хоста командой mount. По моему опыту, полной свободы действий нам это не даст. Некоторые файлы и пути эскалации привилегий недоступны из привилегированного пода, если только мы не эскалируем его до полноценной shell. Зато можно легко примонтировать диск и посмотреть, что мы там увидим.
  • Использовать уязвимость cgroup в user mode с помощью специальных программ. Лучше всего получить интерактивный root-доступ к ноде, но тут придется повозиться. Можем использовать прототип эксплойта Феликса Уилхелма (Felix Wilhelm) undock.sh, чтобы выполнять по команде за раз, или вариант, который Брэндон Эдвадрс (Brandon Edwards) и Ник Фриман (Nick Freeman) предложили в своем выступлении Краткое руководство по выходу из контейнера. В этом варианте мы заставляем хост подключиться к listener на поде для эскалации до интерактивного root-доступа на хосте. Еще один вариант — взять модуль Metasploit Docker Privileged Container Escape, где используется тот же эксплойт для апгрейда shell на контейнере до shell на хосте.

При любом варианте пути эскалации привилегий в Kubernetes во многом похожи на те, которые мы описали для проблемного пода 1, где все разрешено.


Примеры использования


https://github.com/BishopFox/badPods/tree/main/manifests/priv


Дополнительные материалы



Проблемный под 4: только hostpath



Что произойдет в худшем случае?


Много всего.


Как?


Допустим, у нас нет доступа к хостовым process- и network- неймспейсам, но администраторы не ограничили возможности монтирования. Тогда можно примонтировать всю файловую систему хоста к поду и получить к ней доступ на чтение и запись. Теперь можем использовать те же пути эскалации привилегий, что и раньше. Этих путей столько, что Иен Колдуотер (Ian Coldwater) и Даффи Кули (Duffie Cooley) посвятили им целое выступление на Black Hat 2019: «Неизведанный путь: атака на Kubernetes с параметрами по умолчанию».


Вот несколько путей эскалации привилегий, которые можно использовать, когда у нас есть доступ к файловой системе ноды Kubernetes:


  • Ищем файлы kubeconfig в файловой системе хоста. Если повезет, можно даже найти конфигурацию cluster-admin с полным доступом вообще ко всему.
  • Ищем токены во всех подах на ноде. Возьмем что-то типа kubectl auth can-i --list или access-matrix и посмотрим, есть ли в подах токены, которые дадут нам больше разрешений. Ищем токены, с которыми можно получать секреты или создавать поды, деплойменты и т. д. в kube-system или создавать clusterrolebinding.
  • Добавляем свой SSH-ключ. Если у нас есть сетевой доступ к SSH-соединению с нодой, добавим к ноде свой публичный ключ и подключимся к ней по SSH, чтобы получить полный интерактивный доступ.
  • Ломаем хэшированные пароли. Взламываем хэши в /etc/shadow и пытаемся использовать их для доступа к другим нодам.

Примеры использования


https://github.com/BishopFox/badPods/tree/main/manifests/hostpath


Дополнительные материалы



Проблемный под 5: только hostpid



Что произойдет в худшем случае?


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


Как?


С одним только hostPID не так просто получить root-доступ к ноде, но кое-что натворить можно.


  • Смотрим процессы на хосте. Если запустим ps в поде с hostPID: true, увидим все процессы на хосте, включая процессы на каждом поде.
  • Ищем пароли, токены, ключи и тому подобное.Если повезет, найдем что-нибудь для эскалации привилегий и доберемся до кластера, до сервисов, поддерживаемых кластером, или до сервисов, которые общаются с приложениями на кластере. Придется повозиться, но можно найти токен для учетки сервиса в Kubernetes или что-то подобное, чтобы раздобыть доступ к другим пространствам имен и в итоге получить привилегии cluster-admin.
  • Завершаем процессы. Можно завершить на ноде любой процесс, чтобы вызвать отказ в обслуживании (не советую пентестерам экспериментировать с этим пунктом).

Примеры использования


https://github.com/BishopFox/badPods/tree/main/manifests/hostpid


Проблемный под 6: только hostnetwork



Что произойдет в худшем случае?


Риск компрометации кластера.


Как?


Если у нас есть только hostNetwork: true, напрямую выполнить код в привилегированном режиме на хосте мы не можем, но если сильно повезет, шанс добраться до cluster-admin все же есть. Путей эскалации может быть три:


  • Прослушиваем трафик. С tcpdump можно прослушивать незашифрованный трафик на любом интерфейсе хоста. Если звезды сложатся, нам попадутся токены учетки сервиса или другая конфиденциальная информация, которая передается по незашифрованным каналам.
  • Получаем доступ к сервисам, связанным с localhost. Мы можем получить доступ к сервисам, которые принимают трафик только через loopback интерфейс хоста или как-то еще ограничены сетевыми политиками. Оттуда можно найти какие-нибудь интересные пути эскалации привилегий.
  • Обходим сетевую политику. Если пространство имен ограничено сетевой политикой, можно задеплоить под с атрибутом hostNetwork: true, чтобы обойти эти ограничения. Суть в том, что мы привязываемся к сетевым интерфейсам хоста, а не подам.

Примеры использования


https://github.com/BishopFox/badPods/tree/main/manifests/hostnetwork


Проблемный под 7: только hostipc



Что произойдет в худшем случае?


Можно получить доступ к данным, к которым обращаются поды, использующие пространство имен хоста IPC.


Как?


Если какой-то процесс на хосте или процессы в поде используют механизмы межпроцессного взаимодействия (IPC) хоста (общая память, массивы семафоров, очереди сообщений и т. д.), можно использовать эти механизмы для чтения/записи. Сначала ищем /dev/shm, общий для всех подов с атрибутом hostIPC: true и хоста. Можно проверить и другие механизмы IPC с помощью ipcs.


  • Проверяем /dev/shm. Ищем файлы в общей памяти.
  • Проверяем существующие объекты IPC. С помощью /usr/bin/ipcs можно узнать, используются ли какие-нибудь объекты IPC.

Примеры использования


https://github.com/BishopFox/badPods/tree/main/manifests/hostipc


Проблемный под 8: все запрещено



Что произойдет в худшем случае?


Много всего.


Как?


Даже если все атрибуты запрещены, мы все равно можем найти множество путей атак, если можно создать под или хотя бы получить к нему доступ. Имея доступ к поду Kubernetes, обращаем внимание на следующее:


  • Доступные облачные метаданные. Если под размещен в облаке, пытаемся получить доступ к облачному сервису метаданных. Там можно найти учетные данные IAM, связанные с нодой, или хотя бы облачные учетные данные IAM, созданные специально для этого пода. В обоих случаях можно добраться до кластера, до облачной среды или и туда, и туда.
  • Учетки сервисов с лишними разрешениями. Если учетка сервиса по умолчанию в пространстве имен примонтирована к /var/run/secrets/kubernetes.io/serviceaccount/token в поде и позволяет слишком многое, с этим токеном можно эскалировать привилегии в кластере.
  • Компоненты Kubernetes с неправильной конфигурацией. Если у apiserver или kubelet'ов для anonymous-auth задано true и никакие сетевые политики нам не мешают, можно взаимодействовать с ними напрямую без аутентификации.
  • Эксплойты в ядре, движке контейнера или Kubernetes. Эксплойт в этих компонентах можно использовать для выхода из контейнера или доступа к кластеру Kubernetes без дополнительных разрешений.
  • Уязвимые сервисы. Если смотреть на сетевые сервисы кластера через под, скорее всего, мы увидим больше, чем с машины, где создали этот под. Можем поискать уязвимые сервисы и приложения, направляя трафик через под.

Примеры использования
https://github.com/BishopFox/badPods/tree/main/manifests/nothing-allowed


Дополнительные материалы


Защита Kubernetes — KubeCon NA 2019 CTF
Kubernetes Goat
Атака на Kubernetes через Kubelet
Подробный обзор угроз для Kubernetes в реальном мире
Краткое руководство по выходу из контейнера
CVE-2020-8558 POC


Заключение


Если не считать проблемный под номер 8, где все и так запрещено, все пути эскалации привилегий в этом посте (и репозитории к нему) можно перекрыть политиками безопасности.


Администраторы Kubernetes могут использовать и другие методы глубокой защиты, чтобы снизить или полностью устранить риски некоторых путей атак, даже если у злоумышленника есть доступ к некоторым или ко всем неймспейсам и возможностям на хосте (отключить автоматическое монтирование токенов учеток сервисов или запретить подам запуск с правами root, указав MustRunAsNonRoot=trueи allowPrivilegeEscalation=false). Как это обычно и бывает с пентестами, для взлома может потребоваться больше или меньше усилий.


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


От редакции: подробнее о безопасности в K8s можно узнать на интенсиве Kubernetes Мега. Интенсив пройдет в онлайн-формате с 17 по 19 мая 2021.