Так как многие используют Kubernetes для разворачивания сервисов, кластеры K8s могут быть одной из интересных целей. Но их ещё нужно найти и понять, что в них.
Один из способов обнаружить ноды — найти, какие хосты используют SSL-сертификат с common name
Kubernetes Ingress Controller Fake Certificate. Например, это можно сделать с помощью скрипта для nmap ssl-cert. На одном из проектов мы нашли таким способом 47 нод. И по некоторым хостнеймам и подсетям сделали вывод, что кластер не один. Но как узнать, какие сервисы запущены в этих кластерах?
Благодаря использованию одного места для сбора всей информации, мы выяснили, что у нас уже есть учётные данные пользователя с привилегией
sudo на этих хостах после успешной атаки Password Spray.В директории
/etc/kubernetes/ на мастер-ноде был конфиг не только самой ноды, но и администратора кластера, что позволило не тратить время на повышение привилегий. Так как Kubernetes API доступен был только на localhost мастер-ноды, использовали опцию
-D при подключении по SSH к ноде, и с конфигом администратора кластера получили полный доступ к API. А затем собрали всю необходимую информацию о кластере K8s, добавив опцию для игнорирования недоверенного сертификата и переменную окружения для работы через прокси: export KUBECONFIG=~/admin.conf
HTTPS_PROXY=socks5://127.0.0.1:1080 kubectl --insecure-skip-tls-verify=true cluster-info
Список нод поможет оценить размер кластера и отметить хосты, которые к нему относятся:
kubectl get nodes -o wide
По названиям неймспейсов можно попытаться понять, какие сервисы запущены в кластере (например, minio или keycloak):
kubectl get namespaces
Для получения полных конфигов подов можно использовать вывод в формате yaml. Из результата выполнения команды можно получить список подов, информацию о том, какие образы используют контейнеры, на каких портах слушают сервисы, что примонтировано в файловую систему пода. Зачастую из передаваемых в контейнеры переменных окружения можно получить учетные данные или полезные параметры конфигурации сервисов. Параметр
-A для команды позволит получить сведения сразу для всех пространств имен:kubectl get pods -A -o yaml
В списке ingress-ов можно увидеть имена виртуальных хостов и правила маршрутизации трафика (на уровне L7):
kubectl get ingress -A
Пример вывода:
NAMESPACE NAME CLASS HOSTS ADDRESS PORTS
minio minio nginx s3.domain.local 10.10.10.10 80, 443
Configmap-ы предназначены для хранения настроек в виде пар "ключ-значение". И хотя не рекомендуется хранить в них учётные данные, ключи и подобные настройки, они там все равно встречаются. А ещё скрипты, настройки coredns и другие конфигурационные файлы. Поэтому заглянем и туда:
kubectl get configmaps -A -o yaml
Все секреты мы не забираем, а только получаем список. Если по конфигам подов или по названию секрета видим, что используется значение секрета, который нам нужен, то получаем только это значение:
kubectl get secrets -A
kubectl get secret -n <namespace> <secret_name>
Если в списке ingress-ов мы обнаружили виртуальный хост, а при обращении к нему получаем 404, то для поиска нужного пути можно посмотреть логи nginx (для каждого пода
ingress-nginx-controller).kubectl get logs -n ingress-nginx ingress-nginx-controller-<id>
Анализируя полученную информацию, мы можем получить доступ к сервисам. Например, мы в конфиге пода обнаружили, что используются значения из секрета minio для доступа к S3-хранилищу на узле minio.minio.svc.cluster.local. А в списке ingress-ов увидели, что виртуальный хост s3.domain.local доступен на хосте 10.10.10.10, и входящий трафик на порт 443/TCP перенаправляется на под minio в неймспейсе minio. Используя значения секрета, мы получили доступ к содержимому бакетов в S3-хранилище и реализовали один из бизнес-рисков.