# Pentesting Kubernetes Services {{#include ../../../banners/hacktricks-training.md}} Kubernetes usa varios **servicios de red específicos** que podrías encontrar **expuestos a Internet** o en una **red interna una vez que hayas comprometido un pod**. ## Finding exposed pods with OSINT Una forma podría ser buscar `Identity LIKE "k8s.%.com"` en [crt.sh](https://crt.sh) para encontrar subdominios relacionados con kubernetes. Otra forma podría ser buscar `"k8s.%.com"` en github y buscar **archivos YAML** que contengan la cadena. Señales externas útiles de recon para correlacionar antes de escanear: - Nombres de DNS y certificate transparency que contengan `k8s`, `kube`, `api`, `apiserver`, `eks`, `gke`, `aks`, `cluster`, `ingress`, `argocd`, `grafana`, `prometheus`, `harbor`, `registry`, `dashboard`, `dev`, `stage` o nombres de región. - Nombres de cloud load balancer, CNAMEs, tags y hostnames del proveedor que puedan vincular una aplicación expuesta o una interfaz de plataforma con un cluster. - Repositorios públicos, logs de CI, valores de Helm, estado de Terraform, manifests renderizados, container images y documentación que filtren kubeconfigs, URLs del API server, namespaces, service accounts, `type: LoadBalancer`, `type: NodePort`, hosts de Ingress, listeners de Gateway o configuraciones del dashboard. - Inventario de managed Kubernetes, cuando las credenciales de cloud están dentro del alcance: acceso público/privado al endpoint de EKS y CIDRs públicos, configuración de control-plane público/privado en GKE y redes autorizadas, y configuración de IP autorizadas para clusters privados/API server en AKS. - Herramientas de plataforma expuestas alrededor del cluster como Argo CD, Prometheus, Grafana, Harbor, registries, dashboards de CI/CD, dashboards de service mesh y endpoints de administración o métricas del ingress-controller. Trata estas pistas como indicios de atribución y priorización. Una aplicación pública de Ingress es normal en muchos clusters, mientras que kubelet, etcd, dashboard, control de despliegue de CI/CD o material de kubeconfig filtrado expuestos deben priorizarse mucho más. ## How Kubernetes Exposes Services Puede resultarte útil entender cómo Kubernetes puede **exponer servicios públicamente** para encontrarlos: {{#ref}} ../exposing-services-in-kubernetes.md {{#endref}} ## Finding Exposed pods via port scanning Los siguientes puertos podrían estar abiertos en un cluster de Kubernetes: | Port | Process | Description | | --------------- | -------------- | ---------------------------------------------------------------------- | | 443/TCP | kube-apiserver | Puerto de la API de Kubernetes | | 2379/TCP | etcd | | | 6666/TCP | etcd | etcd | | 4194/TCP | cAdvisor | Métricas del contenedor | | 6443/TCP | kube-apiserver | Puerto de la API de Kubernetes | | 8443/TCP | kube-apiserver | Puerto de la API de Minikube | | 8080/TCP | kube-apiserver | Puerto de API inseguro | | 10250/TCP | kubelet | API HTTPS que permite acceso en modo completo | | 10255/TCP | kubelet | Puerto HTTP de solo lectura sin autenticación: pods, pods en ejecución y estado del nodo | | 10256/TCP | kube-proxy | Servidor de comprobación de salud de Kube Proxy | | 9099/TCP | calico-felix | Servidor de comprobación de salud para Calico | | 6782-4/TCP | weave | Métricas y endpoints | | 30000-32767/TCP | NodePort | Proxy a los servicios | | 44134/TCP | Tiller | Servicio de Helm en escucha | ### Nmap ```bash nmap -n -T4 -p 443,2379,6666,4194,6443,8443,8080,10250,10255,10256,9099,6782-6784,30000-32767,44134 /16 ``` ### Kube-apiserver Este es el **servicio API de Kubernetes** con el que los administradores hablan normalmente usando la herramienta **`kubectl`**. **Puertos comunes: 6443 y 443**, pero también 8443 en minikube y 8080 como inseguro. ```bash curl -k https://:(8|6)443/swaggerapi curl -k https://:(8|6)443/healthz curl -k https://:(8|6)443/api/v1 ``` **Consulta la siguiente página para aprender cómo obtener datos sensibles y realizar acciones sensibles hablando con este servicio:** {{#ref}} ../kubernetes-enumeration.md {{#endref}} ### Kubelet API Este servicio **se ejecuta en cada nodo del cluster**. Es el servicio que **controlará** los pods dentro del **nodo**. Habla con el **kube-apiserver**. Si encuentras este servicio expuesto, podrías haber encontrado una **RCE sin autenticación**. #### Kubelet API ```bash curl -k https://:10250/metrics curl -k https://:10250/pods ``` Si la respuesta es `Unauthorized`, entonces requiere autenticación. Si puedes listar nodes, puedes obtener una lista de endpoints de kubelets con: ```bash kubectl get nodes -o custom-columns='IP:.status.addresses[0].address,KUBELET_PORT:.status.daemonEndpoints.kubeletEndpoint.Port' | grep -v KUBELET_PORT | while IFS='' read -r node; do ip=$(echo $node | awk '{print $1}') port=$(echo $node | awk '{print $2}') echo "curl -k --max-time 30 https://$ip:$port/pods" echo "curl -k --max-time 30 https://$ip:2379/version" #Check also for etcd done ``` #### kubelet (Solo lectura) ```bash curl -k https://:10255 http://:10255/pods ``` ### API de etcd ```bash curl -k https://:2379 curl -k https://:2379/version etcdctl --endpoints=http://:2379 get / --prefix --keys-only ``` ### Tiller ```bash helm --host tiller-deploy.kube-system:44134 version ``` Podrías abusar de este service para escalar privilegios dentro de Kubernetes: ### cAdvisor Service útil para recopilar métricas. ```bash curl -k https://:4194 ``` ### NodePort Cuando un puerto se expone en todos los nodos mediante un **NodePort**, el mismo puerto se abre en todos los nodos proxificando el tráfico hacia el **Service** declarado. Por defecto, este puerto estará en el **rango 30000-32767**. Así que nuevos servicios no comprobados podrían ser accesibles a través de esos puertos. ```bash sudo nmap -sS -p 30000-32767 ``` ### Service mesh and proxy surfaces Los clústeres que usan **Istio, Linkerd, Cilium service mesh, o gateways basados en Envoy** añaden otra capa de servicios para enumerar. Un mesh puede proporcionar mTLS, identidad de workload, routing L7, authorization policy, telemetry y controles de gateway/egress, pero solo protege el tráfico que realmente está inscrito e interceptado por el mesh. Comprobaciones útiles desde el acceso a Kubernetes: ```bash kubectl get ns --show-labels | egrep 'istio|linkerd|mesh|cilium' kubectl get crd | egrep 'istio.io|linkerd.io|gateway.networking.k8s.io|cilium.io' kubectl get mutatingwebhookconfiguration,validatingwebhookconfiguration | egrep 'istio|linkerd|cilium' kubectl get pods -A -o custom-columns='NS:.metadata.namespace,NAME:.metadata.name,SA:.spec.serviceAccountName,CONTAINERS:.spec.containers[*].name' kubectl get svc -A | egrep 'istio|envoy|linkerd|kiali|jaeger|prometheus|grafana|zipkin|hubble' ``` Review: - Namespaces or workloads that opted out of injection, still run without a proxy, or were created before injection was enabled. - mTLS mode. Permissive migration modes may still accept plaintext from unmeshed sources. - Istio `PeerAuthentication`, `AuthorizationPolicy`, `RequestAuthentication`, gateways, waypoints, and egress resources. - Linkerd policy resources, identity, Server/authorization objects, and exposed `linkerd-viz`, tap, or metrics surfaces. - Cilium service mesh and Gateway API resources, Hubble visibility, Cilium policies, and Envoy integration points. - Envoy admin, config dump, stats, metrics, tracing, dashboard, and debug endpoints. These can leak routes, upstreams, certificates, identity, and traffic state if exposed too broadly. Do not treat service mesh as a replacement for Kubernetes RBAC or NetworkPolicies. A mesh policy can block an HTTP request while an unmeshed Pod, skipped port, direct Pod IP path, gateway, egress proxy, or missing NetworkPolicy still leaves a practical route. ## Vulnerable Misconfigurations ### Kube-apiserver Anonymous Access Anonymous access to **kube-apiserver resource APIs should not be allowed**. Health endpoints such as `/livez`, `/readyz`, and `/healthz` may be intentionally reachable, especially when the API server uses `AuthenticationConfiguration` to scope anonymous requests to specific paths. Treat health or version responses as reachability evidence; the critical issue is a `200` response for real resource APIs such as namespaces, Secrets, Pods, RBAC objects, metrics, logs, or proxy subresources without valid credentials. ![Kubernetes API server anonymous access output listing exposed API paths](https://www.cyberark.com/wp-content/uploads/2019/09/Kube-Pen-2-fig-5.png) Useful checks: ```bash APISERVER='https://:6443' curl -sk -o /dev/null -w 'livez=%{http_code}\n' "$APISERVER/livez" curl -sk -o /dev/null -w 'readyz=%{http_code}\n' "$APISERVER/readyz" curl -sk -o /dev/null -w 'namespaces=%{http_code}\n' "$APISERVER/api/v1/namespaces" curl -sk -o /dev/null -w 'clusterroles=%{http_code}\n' "$APISERVER/apis/rbac.authorization.k8s.io/v1/clusterroles" ``` Si las resource APIs devuelven `403`, el API server puede haber clasificado la request como `system:anonymous` pero la authorization la bloqueó. Si las resource APIs devuelven `200` sin credentials, busca RoleBindings o ClusterRoleBindings hacia `system:anonymous` o `system:unauthenticated`, una configuración permisiva de authorizer-chain, o un error de authentication en la front-door. ### **Checking for ETCD Anonymous Access** ETCD almacena los cluster secrets, configuration files y más datos **sensitive**. Por **default**, ETCD **no** puede ser accedido **anonymously**, pero siempre es bueno comprobarlo. Si ETCD puede ser accedido anonymously, quizá necesites **usar la** [**etcdctl**](https://github.com/etcd-io/etcd/blob/master/etcdctl/READMEv2.md) **tool**. El siguiente comando obtendrá todas las keys almacenadas: ```bash etcdctl --endpoints=http://:2379 get / --prefix --keys-only ``` ### **Kubelet RCE** La [**Kubelet documentation**](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/) explica que, por **default, el acceso anónimo** al servicio **está permitido:** > Enables anonymous requests to the Kubelet server. Requests that are not rejected by another authentication method are treated as anonymous requests. Anonymous requests have a username of `system:anonymous`, and a group name of `system:unauthenticated` Para entender mejor cómo funciona la **authentication y authorization de la Kubelet API** revisa esta página: {{#ref}} kubelet-authentication-and-authorization.md {{#endref}} El servicio **Kubelet** **API is not documented**, pero el código fuente se puede encontrar aquí y descubrir los endpoints expuestos es tan fácil como **ejecutar**: ```bash curl -s https://raw.githubusercontent.com/kubernetes/kubernetes/master/pkg/kubelet/server/server.go | grep 'Path("/' Path("/pods"). Path("/run") Path("/exec") Path("/attach") Path("/portForward") Path("/containerLogs") Path("/runningpods/"). ``` Todos suenan interesantes. Puedes usar la herramienta [**Kubeletctl**](https://github.com/cyberark/kubeletctl) para interactuar con Kubelets y sus endpoints. #### /pods Este endpoint lista los pods y sus contenedores: ```bash kubeletctl pods ``` #### /exec Este endpoint permite ejecutar código dentro de cualquier contenedor muy fácilmente: ```bash kubeletctl exec [command] ``` > [!NOTE] > Para evitar este ataque, el servicio _**kubelet**_ debe ejecutarse con `--anonymous-auth false` y el servicio debe estar segregado a nivel de red. ### **Checking Kubelet (Read Only Port) Information Exposure** Cuando un **kubelet read-only port** está expuesto, es posible que partes no autorizadas recuperen información desde la API. La exposición de este puerto puede llevar a la divulgación de varios **cluster configuration elements**. Aunque la información, incluidos **pod names, locations of internal files, and other configurations**, puede no ser crítica, su exposición sigue representando un riesgo de seguridad y debe evitarse. Un ejemplo de cómo puede explotarse esta vulnerabilidad implica que un atacante remoto acceda a una URL específica. Al navegar a `http://:10255/pods`, el atacante puede recuperar información sensible del kubelet: ![Kubelet read-only port response exposing pod information](https://www.cyberark.com/wp-content/uploads/2019/09/KUbe-Pen-2-fig-6.png) ## References {{#ref}} https://www.cyberark.com/resources/threat-research-blog/kubernetes-pentest-methodology-part-2 {{#endref}} {{#ref}} https://labs.f-secure.com/blog/attacking-kubernetes-through-kubelet {{#endref}} {{#include ../../../banners/hacktricks-training.md}}