Skip to content

Kubernetes cluster exposed

Severity: criticalApplies to: Any reachable cluster

A Kubernetes cluster doesn’t have one exposed surface — it has several, each independently a path to owning everything. That’s what makes cluster security different from a single service: you’re not closing one port, you’re accounting for five distinct front doors, any one of which is the whole cluster.

The API server (6443). Secured with auth and RBAC it’s meant to be reachable — but an internet-facing API server is a continuous CVE and brute-force target, and if anonymous auth is on with a stray system:unauthenticated binding, it’s open. A misconfigured API server is kubectl for attackers.

The kubelet (10250). Every node runs a kubelet, and its API can exec into pods and read their logs and secrets. Historically it allowed anonymous access (--anonymous-auth=true, --authorization-mode=AlwaysAllow), and clusters still ship that way. An exposed, unauthenticated kubelet is code execution in every pod on that node — no API server involved:

Terminal window
curl -sk https://node:10250/pods # every pod on the node
# and exec endpoints from there

etcd (2379). The whole cluster in one store, secrets included. No RBAC in front of it — reach it without client-cert auth and you read and write cluster state directly.

The dashboard. The Kubernetes Dashboard, exposed and granted a powerful service account, was behind real-world breaches (famously Tesla’s, where an open dashboard led to cryptomining in their cluster). If you run it, it must be behind auth and never public.

A compromised pod. The one that doesn’t require any exposed control-plane surface. An RCE in a public-facing app, plus a mounted service account token and a flat network, lets an attacker query the API and reach every internal service — lateral movement from a single container. This is the most common real path, and it’s why the workload-side controls matter as much as the control-plane ones.

These doors connect. The textbook cluster takeover:

  1. RCE in an internet-facing pod.
  2. Read the mounted service account token.
  3. The token’s RBAC allows get secrets (or the pod is on the default SA with too much) → read secrets.
  4. Or reach the kubelet / a privileged neighbour pod → node.
  5. Node → kubelet credential → more of the cluster.
  6. A hostPath or metadata-service reach → cloud credentials → the account.

Every link is one of this cluster’s control pages, which is why they’re a set, not a menu.