Abusing Roles/ClusterRoles in Kubernetes
Tutaj możesz znaleźć potencjalnie niebezpieczne konfiguracje Roles i ClusterRoles.
Pamiętaj, że możesz uzyskać wszystkie obsługiwane zasoby za pomocą kubectl api-resources
Privilege Escalation
Odnosimy się do sztuki uzyskiwania dostępu do innego podmiotu w klastrze z innymi uprawnieniami (w obrębie klastra kubernetes lub do zewnętrznych chmur) niż te, które już posiadasz. W Kubernetes istnieją zasadniczo 4 główne techniki eskalacji uprawnień:
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, w których 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ść 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 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ć dowolnej przestrzeni nazw w klastrze.
Uzyskaj dostęp do dowolnego zasobu za pomocą konkretnego czasownika
W RBAC niektóre uprawnienia niosą ze sobą istotne ryzyko:
create
: Przyznaje możliwość tworzenia dowolnych zasobów klastra, co stwarza ryzyko eskalacji uprawnień.list
: Umożliwia wylistowanie wszystkich zasobów, co może prowadzić do wycieku wrażliwych danych.get
: Zezwala na dostęp do sekretów z kont serwisowych, co stanowi zagrożenie dla bezpieczeństwa.
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.
Przykład poda, który ukradnie token konta usługi bootstrap-signer
i wyśle go do atakującego:
Tworzenie podów i ucieczka
Poniżej przedstawiono wszystkie uprawnienia, jakie może mieć kontener:
Dostęp uprzywilejowany (wyłączanie zabezpieczeń i ustawianie możliwości)
Wyłączenie przestrzeni nazw hostIPC i hostPid, co może pomóc w eskalacji uprawnień
Wyłączenie przestrzeni nazw hostNetwork, co daje dostęp do kradzieży uprawnień chmurowych węzłów i lepszego dostępu do sieci
Zamontowanie hostów / wewnątrz kontenera
Utwórz pod za pomocą:
Jednolinijkowiec z tego tweeta oraz z dodatkami:
Teraz, gdy możesz uciec do węzła, sprawdź techniki po eksploatacji w:
Stealth
Prawdopodobnie chcesz być bardziej dyskretny, na następnych stronach możesz zobaczyć, do czego będziesz miał dostęp, jeśli stworzysz pod, włączając tylko niektóre z wymienionych uprawnień w poprzednim szablonie:
Privileged + hostPID
Privileged only
hostPath
hostPID
hostNetwork
hostIPC
Możesz znaleźć przykład, jak stworzyć/wykorzystać poprzednie konfiguracje podów z uprawnieniami w https://github.com/BishopFox/badPods
Pod Create - Przenieś do chmury
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. 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ź:
Pod Escape PrivilegesUtwórz/Zaktualizuj wdrożenie, Daemonsets, Statefulsets, Replicationcontrollers, Replicasets, Jobs i Cronjobs
Możliwe jest nadużycie tych uprawnień do stworzenia nowego poda i uzyskania uprawnień, jak w poprzednim przykładzie.
Poniższy yaml tworzy daemonset i eksfiltruje token SA wewnątrz poda:
Pods Exec
pods/exec
to zasób w kubernetes używany do uruchamiania poleceń w powłoce wewnątrz poda. Umożliwia to uruchamianie poleceń wewnątrz kontenerów lub uzyskanie powłoki wewnątrz.
Dlatego możliwe jest dostanie się do poda i kradzież tokena SA, lub wejście do uprzywilejowanego poda, ucieczka do węzła i kradzież wszystkich tokenów podów w węźle oraz (nadużycie) węzła:
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:
Hosts Writable /var/log/ Escape
As wskazano w tych badaniach, jeśli możesz uzyskać dostęp lub stworzyć 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.
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 wykorzystać to zachowanie na 2 sposoby:
Modyfikując plik
0.log
swojego kontenera (zwykle znajdujący się w/var/logs/pods/namespace_pod_uid/container/0.log
), aby był symlinkiem wskazującym na/etc/shadow
na przykład. Wtedy będziesz mógł wyeksfiltrować plik shadow hosta, wykonując:
Jeśli atakujący kontroluje jakikolwiek podmiot z uprawnieniami do odczytu
nodes/log
, może po prostu utworzyć symlink w/host-mounted/var/log/sym
do/
i podczas dostępu dohttps://<gateway>:10250/logs/sym/
wyświetli system plików root hosta (zmiana symlinka może zapewnić dostęp do plików).
Laboratorium i zautomatyzowany exploit można znaleźć w https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts
Ominięcie ochrony readOnly
Jeśli masz szczęście i wysoko uprzywilejowana zdolność CAP_SYS_ADMIN
jest dostępna, możesz po prostu ponownie zamontować folder jako rw:
Obejście ochrony hostPath readOnly
Jak stwierdzono w tych badaniach, możliwe jest obejście ochrony:
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:
Impersonowanie uprzywilejowanych kont
Dzięki uprawnieniu impersonacji użytkownika, atakujący może udawać uprzywilejowane konto.
Wystarczy użyć parametru --as=<username>
w poleceniu kubectl
, aby udawać użytkownika, lub --as-group=<group>
, aby udawać grupę:
Lub użyj REST API:
Listing Secrets
Uprawnienie do wyświetlania sekretów może pozwolić atakującemu na rzeczywiste odczytanie sekretów uzyskując dostęp do punktu końcowego REST API:
Odczytanie 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 wyświetlania sekretów, nadal istnieją luki. Domyślne konta serwisowe w systemie mogą być enumerowane, z których każde jest powiązane 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.
Token jest generowany z ograniczonego zestawu 27 znaków (bcdfghjklmnpqrstvwxz2456789
), a nie z pełnego zakresu alfanumerycznego. To ograniczenie redukuje 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 do eskalacji uprawnień poprzez uzyskanie dostępu do wrażliwych kont serwisowych.
Żą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.
Zgodnie z dokumentacją, możliwe jest automatyczne zatwierdzanie tych żądań, 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>/*
Przykład roli z wszystkimi wymaganymi uprawnieniami to:
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ń.
W tym poście i tym konfiguracja TLS Bootstrap K8s w GKE 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.
Sposobem na obejście tego jest 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):
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 aws-auth configmap.
Potrzebne czasowniki to update
i patch
, lub create
, jeśli configmap nie został utworzony:
Możesz użyć aws-auth
do utrzymania dostępu dla użytkowników z innych kont.
Jednakże, 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 tylko 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.
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).
Rozmawiając z punktem końcowym API K8s, token autoryzacji 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. 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ć.
GCP - Container PrivescDruga metoda to przypisanie uprawnień K8s wewnątrz klastra poprzez identyfikację użytkownika po jego e-mailu (w tym konta serwisowe GCP).
Tworzenie tokenów serviceaccounts
Zasady, które mogą tworzyć TokenRequests (serviceaccounts/token
) podczas rozmowy z punktem końcowym API K8s SAs (informacje z tutaj).
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 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 mutatingwebhookconfigurations
przykładu sprawdź tę sekcję tego posta.
Eskalacja
Jak można przeczytać w następnej sekcji: Wbudowana zapobieganie eskalacji uprawnień, 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.
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). Więcej informacji na temat autoryzacji Kubelet na tej stronie:
Masz przykład, jak uzyskać RCE rozmawiając autoryzowanym z API Kubelet tutaj.
Usuwanie podów + węzły nieschedulowalne
Zasady, które mogą usuwać pody (delete
czasownik nad zasobem pods
), lub ewikować pody (create
czasownik 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 (delete
czasownik nad zasobem nodes
) i mają kontrolę nad podami, 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.
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).
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 wymuszone ograniczenia harmonogramu.
Wbudowana zapobieganie eskalacji uprawnień
Kubernetes ma wbudowany mechanizm 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 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.
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 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 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.
Inne ataki
Aplikacja proxy sidecar
Domyślnie nie ma żadnego szyfrowania w komunikacji między podami. Wzajemna autoryzacja, dwukierunkowa, pod do pod.
Utwórz aplikację proxy sidecar
Utwórz swój plik .yaml
Edytuj swój plik .yaml i dodaj odkomentowane linie:
Zobacz logi 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 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 zazwyczaj także utrzymania się w klastrze.
Przykład z https://blog.rewanthtammana.com/creating-malicious-admission-controllers:
Sprawdź status, aby zobaczyć, czy jest gotowy:
Następnie wdroż nowy pod:
Kiedy widzisz błąd ErrImagePull
, sprawdź nazwę obrazu za pomocą jednej z poniższych zapytań:
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
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:
The above snippet replaces the first container image in every pod with rewanthtammana/malicious-image
.
OPA Gatekeeper bypass
Kubernetes - OPA Gatekeeper bypassBest Practices
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 konta usługi lub podów, począwszy od wersji Kubernetes 1.6.
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.
Role specyficzne dla przestrzeni nazw zamiast ról ogólnoklastrowych
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ń.
Używaj narzędzi automatycznych
Referencje
Last updated