Abusing Roles/ClusterRoles in Kubernetes
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
Dostęp do dowolnego zasobu z określonym czasownikiem
W RBAC pewne uprawnienia stwarzają znaczne ryzyko:
create
: Udziela możliwości tworzenia dowolnego zasobu klastra, zwiększając ryzyko eskalacji uprawnień.list
: Umożliwia wyświetlanie wszystkich zasobów, potencjalnie ujawniając wrażliwe dane.get
: Pozwala na dostęp do tajnych informacji z kont usług, stanowiąc zagrożenie dla bezpieczeństwa.
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:
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
Utwórz pod z:
Jednolinijkowiec z tego tweeta i z kilkoma dodatkami:
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 PrivilegesUtwó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:
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ł:
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:
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:
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 dohttps://<gateway>:10250/logs/sym/
wyświetli system plików roota hosta (zmiana symlinka może umożliwić dostęp do plików).
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:
Ominięcie ochrony hostPath readOnly
Jak stwierdzono w tej analizie, możliwe jest ominiecie ochrony:
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:
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ę:
Albo skorzystaj z interfejsu REST API:
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:
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:
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):
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:
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 PrivescDrugi 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:
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.
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
Edytuj plik .yaml i dodaj odkomentowane linie:
Zobacz dzienniki 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:
Sprawdź status, aby zobaczyć, czy jest gotowy:
Następnie wdroż nową kapsułkę:
Kiedy widzisz błąd ErrImagePull
, sprawdź nazwę obrazu za pomocą jednego z poniższych zapytań:
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:
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
Last updated