Kubernetes Dashboard Unauthenticated Access: Pod Creation, Secret Enumeration and Admin Escalation
Theory
Why This Matters
In 2018, Tesla's Kubernetes clusters were compromised by attackers who discovered a Kubernetes Dashboard exposed to the internet without authentication. The dashboard's service account had cluster-admin privileges, and the attackers used it to enumerate running pods, extract AWS credentials from pod environment variables, and deploy cryptomining workloads. This incident, disclosed by RedLock, was the case that made Kubernetes Dashboard security a mainstream concern. The same misconfiguration — unauthenticated dashboard with cluster-admin RBAC bindings — has been found in subsequent assessments at financial institutions, healthcare providers, and SaaS companies. The dashboard is a legitimate operations tool; the vulnerability is in how it is deployed and what RBAC permissions its service account holds.
Core Concept
The Kubernetes Dashboard is a web-based UI for managing Kubernetes clusters. When properly configured, it requires token-based authentication or integrates with an identity provider via OIDC, and its service account holds only the permissions needed to display cluster state. When misconfigured, it is deployed with:
--enable-skip-loginor the skip button enabled, allowing anonymous access to the dashboard UI.- A service account bound to the
cluster-adminClusterRole, granting full control over every resource in the cluster. - Exposed via a
NodePort,LoadBalancer, orIngresswithout network restrictions — accessible from the internet.
The combination of these three misconfigurations allows any unauthenticated internet user to interact with the cluster as a cluster administrator: create pods, read secrets, modify deployments, and execute commands inside existing containers.
RBAC analysis for the dashboard: The default dashboard service account (kubernetes-dashboard in the kubernetes-dashboard namespace) has minimal permissions by design. The vulnerability arises when operators create a ClusterRoleBinding attaching cluster-admin to the dashboard service account, typically to "fix" permission errors rather than diagnosing the correct minimal permission set.
Network exposure analysis: The dashboard service type and ingress rules determine whether external access is possible. ClusterIP (the default) requires kubectl port-forward for access — not externally reachable. NodePort exposes it on all cluster nodes. LoadBalancer creates a cloud load balancer with a public IP. Ingress with no authentication middleware is equivalent to LoadBalancer exposure.
Metrics Server is often co-deployed with the dashboard and may expose its own API endpoint without authentication — a separate but related finding.
Technical Deep-Dive
# Enumerate all services across namespaces to find the dashboard
kubectl get services -A | grep -i dashboard
# Check the service type and external IPs
kubectl get service kubernetes-dashboard -n kubernetes-dashboard
-o jsonpath='{.spec.type}: {.status.loadBalancer.ingress[*].ip}'
# Check all ingress resources for dashboard exposure
kubectl get ingress -A | grep -i dashboard
# Describe the dashboard service account
kubectl describe serviceaccount kubernetes-dashboard -n kubernetes-dashboard
# Find all ClusterRoleBindings for the dashboard service account
kubectl get clusterrolebindings -o json |
python3 -c "
import sys, json
bindings = json.load(sys.stdin)
for b in bindings['items']:
for subj in b.get('subjects', []):
if 'dashboard' in subj.get('name', '').lower():
role = b['roleRef']['name']
print(f"Binding: {b['metadata']['name']} Role: {role} Subject: {subj['name']}")
"
# Check if skip-login is enabled (in dashboard deployment args)
kubectl get deployment kubernetes-dashboard -n kubernetes-dashboard
-o jsonpath='{.spec.template.spec.containers[0].args}' | tr ',' '
' | grep skip
# List all secrets accessible from the dashboard namespace
kubectl get secrets -n kubernetes-dashboard
# Check if the dashboard can access secrets cluster-wide (if cluster-admin bound)
kubectl auth can-i get secrets --all-namespaces
--as=system:serviceaccount:kubernetes-dashboard:kubernetes-dashboard
# Use pacu for AWS credential harvesting from dashboard (if cluster has AWS workloads)
# First: use the dashboard to exec into a pod and extract IMDS credentials
# kubectl exec -n production deployment/api-server --
# curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
# Run kube-bench to check dashboard-related CIS controls
kube-bench run --targets=node,policies --check 1.2.1,5.1.1,5.1.2
# Secure dashboard deployment pattern
apiVersion: v1
kind: ServiceAccount
metadata:
name: kubernetes-dashboard
namespace: kubernetes-dashboard
---
# Bind to minimal read-only role — NOT cluster-admin
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kubernetes-dashboard
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: view # read-only, no secret values
# DO NOT use cluster-admin here
subjects:
- kind: ServiceAccount
name: kubernetes-dashboard
namespace: kubernetes-dashboard
---
# Expose only as ClusterIP — access via kubectl port-forward only
apiVersion: v1
kind: Service
metadata:
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
type: ClusterIP # NOT NodePort or LoadBalancer
ports:
- port: 443
targetPort: 8443
Security Assessment Methodology
- Discover the dashboard service. Run
kubectl get services -A | grep -i dashboardandkubectl get ingress -A. Check service types:LoadBalancerorNodePortwith external IPs is an internet-exposure finding. Check ingress rules for authentication middleware (oauth2-proxy, auth annotations). - Test unauthenticated access. Port-forward to the dashboard (
kubectl port-forward -n kubernetes-dashboard svc/kubernetes-dashboard 8443:443) and browse tohttps://localhost:8443. If the login page has a "Skip" button or if you can reach the dashboard UI without a token, unauthenticated access is confirmed. If externally exposed, test directly from a browser without any tokens. - Enumerate RBAC bindings for the dashboard service account. Check all
ClusterRoleBindingsandRoleBindingsfor thekubernetes-dashboardservice account. A binding tocluster-adminis a critical finding even if authentication is required — the service account should have only read access. - Assess what the service account can access. Use
kubectl auth can-i --list --as=system:serviceaccount:kubernetes-dashboard:kubernetes-dashboardto enumerate all permitted actions. Focus on:get secrets,execinto pods,create pods,list nodes. - Check network policies. Verify whether a
NetworkPolicyrestricts ingress to the dashboard pod to internal IPs only. Missing network policies combined with NodePort exposure mean the dashboard is reachable from any node IP. - Remediate by: setting the dashboard service type to
ClusterIP; disabling--enable-skip-loginin dashboard deployment args; binding the dashboard service account to theviewClusterRole (or a custom role with only required permissions); adding an authentication proxy (oauth2-proxy + OIDC) in front of any ingress exposure; enforcing a NetworkPolicy restricting ingress to the dashboard namespace from admin VPN CIDRs only.
Common Assessment Errors
- Assuming authentication means safe. A dashboard that requires a bearer token is still a critical finding if the service account is cluster-admin and the token is stored insecurely (in a developer's
~/.kube/configor a CI/CD environment variable). Authentication without least-privilege RBAC is incomplete remediation. - Missing the
metrics-serverAPI exposure. Metrics Server, commonly deployed alongside the dashboard, exposes the/apis/metrics.k8s.ioendpoint. In older versions, this was accessible without authentication. Always enumerate API server extensions alongside the dashboard. - Not checking for dashboard in non-default namespaces. Operators sometimes deploy the dashboard in
kube-system,monitoring, or a custom namespace.kubectl get services -A | grep -i dashboardcovers all namespaces. - Ignoring the
kubernetes-dashboardHelm chart skip-auth flag. Helm chart installations of the dashboard may haveextraArgs: [--enable-skip-login]set invalues.yaml. Always inspect the dashboard deployment's container args, not just the Helm chart defaults. - Treating ClusterIP as definitely safe. ClusterIP is not accessible from outside the cluster, but pods inside the cluster — including any compromised workload — can reach it. An attacker with a foothold on any pod can access a ClusterIP dashboard. Always assess RBAC regardless of service type.
- Missing the Kubernetes API server directly. The Kubernetes API server itself (
kubectl proxyor direct HTTPS access) may be accessible to the dashboard service account token. Enumerate what the token can do against the API server directly, not only through the dashboard UI.
NICE Framework Alignment
| Code | Knowledge/Skill/Task Statement | How This Card Develops It |
|---|---|---|
| K0053 | Knowledge of security risk management processes | Understanding that dashboard exposure is a risk multiplier: it provides a GUI for every RBAC permission the service account holds, lowering the skill bar for cluster compromise |
| K0167 | Knowledge of system administration, network, and OS hardening techniques | Hardening Kubernetes dashboard deployments: ClusterIP service type, disabled skip-login, least-privilege RBAC, authentication proxy, and NetworkPolicy restrictions |
| S0073 | Skill in conducting vulnerability scans and recognizing vulnerabilities | Using kubectl get services, RBAC enumeration, and kube-bench to identify exposed dashboards, over-privileged service accounts, and missing authentication controls |
| T0144 | Conduct penetration testing as required for new or updated applications | Enumerating Kubernetes Dashboard exposure and RBAC bindings during cluster penetration tests to demonstrate unauthenticated cluster-admin access paths |
| T0395 | Write code to address security vulnerabilities | Writing secure Kubernetes RBAC manifests with minimal dashboard service account permissions and ClusterIP service configurations with NetworkPolicy restrictions |
Further Reading
- Kubernetes Security — Best Practices Guide — Kubernetes Documentation (kubernetes.io/docs/concepts/security)
- CIS Kubernetes Benchmark — Center for Internet Security, Section 5.1: RBAC and Service Accounts (cisecurity.org)
- Kubernetes Goat — Dashboard Attack Scenario — Madhu Akula, interactive Kubernetes security training (github.com/madhuakula/kubernetes-goat)
Challenge Lab
Reinforce your learning with a hands-on generated challenge based on this card's competency.