Files
hacktricks-cloud/src/pentesting-cloud/kubernetes-security/pentesting-kubernetes-services/README.md
T

13 KiB

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 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

nmap -n -T4 -p 443,2379,6666,4194,6443,8443,8080,10250,10255,10256,9099,6782-6784,30000-32767,44134 <pod_ipaddress>/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.

curl -k https://<IP Address>:(8|6)443/swaggerapi
curl -k https://<IP Address>:(8|6)443/healthz
curl -k https://<IP Address>:(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

curl -k https://<IP address>:10250/metrics
curl -k https://<IP address>:10250/pods

Si la respuesta es Unauthorized, entonces requiere autenticación.

Si puedes listar nodes, puedes obtener una lista de endpoints de kubelets con:

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)

curl -k https://<IP Address>:10255
http://<external-IP>:10255/pods

API de etcd

curl -k https://<IP address>:2379
curl -k https://<IP address>:2379/version
etcdctl --endpoints=http://<MASTER-IP>:2379 get / --prefix --keys-only

Tiller

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.

curl -k https://<IP Address>: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.

sudo nmap -sS -p 30000-32767 <IP>

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:

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

Useful checks:

APISERVER='https://<api-server>: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 tool. El siguiente comando obtendrá todas las keys almacenadas:

etcdctl --endpoints=http://<MASTER-IP>:2379 get / --prefix --keys-only

Kubelet RCE

La Kubelet documentation 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:

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 para interactuar con Kubelets y sus endpoints.

/pods

Este endpoint lista los pods y sus contenedores:

kubeletctl pods

/exec

Este endpoint permite ejecutar código dentro de cualquier contenedor muy fácilmente:

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://<external-IP>:10255/pods, el atacante puede recuperar información sensible del kubelet:

Kubelet read-only port response exposing pod information

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