Что будет, если разрешить лишнее при создании подов в 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
Дополнительные материалы
- Самая бестолковая команда Kubernetes на свете
- Защита Kubernetes — KubeCon NA 2019 CTF
- Подробный обзор угроз для Kubernetes в реальном мире
- Компрометация кластера Kubernetes с помощью разрешений RBAC (слайды)
- Неизведанный путь: атака на Kubernetes с параметрами по умолчанию с репозиторием
Проблемный под 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
Дополнительные материалы
- Твит Даффи Кули (Duffie Cooley) про Nsenter Pod
- Неизведанный путь: атака на Kubernetes с параметрами по умолчанию с репозиторием
- Node-shell Krew Plugin
Проблемный под 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
Дополнительные материалы
- Экслойт Феликса Уилхелма Cgroup Usermode Helper
- Обзор Container Escape в Docker
- Краткое руководство по выходу из контейнера
- Модуль Metasploit Docker Privileged Container Escape
Проблемный под 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
Дополнительные материалы
- Неизведанный путь: атака на Kubernetes с параметрами по умолчанию с репозиторием
- Защита Kubernetes — KubeCon NA 2019 CTF
- Подробный обзор угроз для Kubernetes в реальном мире
- Компрометация кластера Kubernetes с помощью разрешений RBAC (слайды)
Проблемный под 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.