Kubernetes Security: From Pod Escape to Cluster Takeover¶
Kubernetes now orchestrates over 80% of containerized production workloads. That dominance makes it the highest-value target in modern cloud infrastructure. Attackers who gain a foothold inside a single pod can chain misconfigurations — privileged containers, overly permissive RBAC, exposed secrets, and unpatched nodes — into full cluster compromise. The gap between "I own one pod" and "I own your entire cluster" is often measured in minutes, not days.
This post maps the most common Kubernetes attack paths, provides detection queries for each stage, and walks through a synthetic breach scenario from initial pod escape to cluster-wide takeover.
1. Kubernetes Attack Paths¶
Pod Escape to Host¶
A container running with privileged: true or with host namespace access (hostPID, hostNetwork, hostIPC) can trivially escape to the underlying node. Attackers mount the host filesystem via /proc/1/root, write SSH keys or cron jobs, and gain persistent node-level access. Even without explicit privilege escalation, containers with CAP_SYS_ADMIN or writable /var/run/docker.sock mounts provide direct breakout paths.
Key Insight
In most cluster compromises, the pod escape is not the hard part. The hard part is detecting it. Privileged containers are deployed intentionally for monitoring, logging, and CI/CD runners — making malicious use blend with legitimate operations.
RBAC Abuse and Privilege Escalation¶
Kubernetes RBAC misconfigurations are endemic. Common patterns include:
- Wildcard permissions:
ClusterRolebindings withverbs: ["*"]onresources: ["*"]— effectively cluster-admin - Service account token theft: every pod mounts a service account token by default unless
automountServiceAccountToken: falseis set - Binding escalation: users with
createpermissions onClusterRoleBindingcan grant themselvescluster-admin
| Misconfiguration | Prevalence | Impact |
|---|---|---|
| Privileged containers in production | ~35% of clusters | Direct node escape |
| Default service account tokens mounted | ~60% of clusters | Lateral movement via API server |
| Wildcard RBAC permissions | ~20% of clusters | Full cluster admin access |
| Secrets readable by default service accounts | ~25% of clusters | Credential theft |
Secrets Exposure¶
Kubernetes Secrets are base64-encoded, not encrypted at rest by default. Attackers with get or list permissions on secrets in any namespace can harvest database credentials, API keys, TLS certificates, and cloud provider tokens. Direct access to etcd — the cluster's backing datastore — exposes every secret in plaintext.
Supply Chain via Container Images¶
Compromised or typosquatted container images in public registries introduce malicious code at deploy time. Without image signing verification and admission controllers, a single poisoned image in a CI/CD pipeline propagates across every environment that pulls it. See Chapter 35: DevSecOps Pipeline Security for supply chain hardening strategies.
2. ATT&CK Technique Spotlight¶
T1610 — Deploy Container¶
Adversaries deploy new containers within the cluster to execute malicious payloads, establish persistence, or mine cryptocurrency. Detection priority: monitor for container creation from unsigned or unexpected images, especially in kube-system or privileged namespaces.
T1611 — Escape to Host¶
Container escape techniques — nsenter, chroot, mounting host filesystems — allow adversaries to break out of container isolation and execute commands on the underlying node. This is the pivot point from "application compromise" to "infrastructure compromise."
T1613 — Container and Resource Discovery¶
After initial access, adversaries enumerate the Kubernetes environment: listing pods, services, namespaces, secrets, and RBAC bindings to map privilege escalation paths. High-frequency API calls to list and get resources from unusual service accounts signal reconnaissance.
For deep-dive coverage of container-specific red team techniques, see Chapter 46: Cloud & Container Red Team.
3. Detection Queries¶
Privileged Container Creation¶
Detect new containers launched with privileged security contexts or host namespace access:
// Detect privileged container creation in Kubernetes
let detection_window = 24h;
KubeAuditLogs
| where TimeGenerated > ago(detection_window)
| where Verb_s in ("create", "update", "patch")
| where ObjectRef_Resource_s == "pods"
| where RequestBody_s has_any ("privileged\":true", "hostPID\":true",
"hostNetwork\":true", "hostIPC\":true")
| project TimeGenerated, UserAgent_s, Username_s,
ObjectRef_Namespace_s, ObjectRef_Name_s,
SourceIP_s = SourceIPs_s
| where ObjectRef_Namespace_s !in ("kube-system", "monitoring")
| sort by TimeGenerated desc
index=kubernetes sourcetype=kube:audit
| spath verb | search verb IN ("create", "update", "patch")
| spath objectRef.resource | search "objectRef.resource"="pods"
| where match(requestObject, "\"privileged\":\s*true")
OR match(requestObject, "\"hostPID\":\s*true")
OR match(requestObject, "\"hostNetwork\":\s*true")
| eval namespace=spath(objectRef, "namespace")
| where NOT namespace IN ("kube-system", "monitoring")
| table _time, user.username, sourceIPs{}, namespace,
objectRef.name, userAgent
| sort - _time
ClusterRoleBinding Changes¶
Monitor for creation or modification of ClusterRoleBindings, especially those granting cluster-admin:
// Detect ClusterRoleBinding changes — privilege escalation indicator
KubeAuditLogs
| where TimeGenerated > ago(24h)
| where ObjectRef_Resource_s == "clusterrolebindings"
| where Verb_s in ("create", "update", "patch", "delete")
| extend RoleRef = parse_json(RequestBody_s).roleRef.name
| project TimeGenerated, Username_s, Verb_s,
ObjectRef_Name_s, RoleRef,
SourceIP_s = SourceIPs_s, UserAgent_s
| sort by TimeGenerated desc
index=kubernetes sourcetype=kube:audit
| spath "objectRef.resource"
| search "objectRef.resource"="clusterrolebindings"
| spath verb | search verb IN ("create", "update", "patch", "delete")
| spath "requestObject.roleRef.name" AS role_name
| table _time, user.username, verb, objectRef.name,
role_name, sourceIPs{}, userAgent
| sort - _time
Secrets Access Anomalies¶
Detect unusual patterns of secrets access — bulk listing, access from unexpected service accounts, or access to secrets in other namespaces:
// Detect anomalous secrets access patterns
let baseline_window = 7d;
let SecretBaseline = KubeAuditLogs
| where TimeGenerated > ago(baseline_window)
| where ObjectRef_Resource_s == "secrets"
| where Verb_s in ("get", "list", "watch")
| summarize AvgDaily = count() / 7.0 by Username_s;
KubeAuditLogs
| where TimeGenerated > ago(1d)
| where ObjectRef_Resource_s == "secrets"
| where Verb_s in ("get", "list", "watch")
| summarize TodayCount = count(),
NamespacesAccessed = dcount(ObjectRef_Namespace_s),
SecretsAccessed = dcount(ObjectRef_Name_s)
by Username_s
| join kind=leftouter SecretBaseline on Username_s
| where TodayCount > coalesce(AvgDaily, 0) * 3
or NamespacesAccessed > 3
| project Username_s, TodayCount, AvgDaily, NamespacesAccessed, SecretsAccessed
index=kubernetes sourcetype=kube:audit
| spath "objectRef.resource" | search "objectRef.resource"="secrets"
| spath verb | search verb IN ("get", "list", "watch")
| bin _time span=1d
| stats count as today_count, dc(objectRef.namespace) as ns_count,
dc(objectRef.name) as secret_count by user.username, _time
| eventstats avg(today_count) as avg_daily by user.username
| where today_count > avg_daily * 3 OR ns_count > 3
| table _time, user.username, today_count, avg_daily, ns_count, secret_count
| sort - today_count
etcd Direct Access Attempts¶
Direct connections to etcd bypass Kubernetes API server authentication entirely. Any non-API-server connection to etcd port 2379 is a critical indicator:
// Detect direct etcd access attempts bypassing API server
CommonSecurityLog
| where TimeGenerated > ago(24h)
| where DestinationPort == 2379
| where SourceIP !in ("10.0.1.10", "10.0.1.11", "10.0.1.12")
// Replace with your API server IPs
| project TimeGenerated, SourceIP, DestinationIP,
DestinationPort, DeviceAction, Protocol
| sort by TimeGenerated desc
4. Case Study: Acme Corp Kubernetes Breach¶
Scenario: Pod Escape to Cluster Takeover (Fictional)
Organization: Acme Corp (fictional, 2,400 employees) Infrastructure: Multi-tenant Kubernetes cluster on managed cloud, 340 pods across 12 namespaces Initial Access: Compromised CI/CD runner pod with privileged: true Impact: Full cluster compromise, 28 secrets exfiltrated, cryptominer deployed on 6 nodes
Timeline¶
| Time (UTC) | Event | Detection |
|---|---|---|
| 09:14 | Attacker exploits RCE in web application pod (CVE-2027-XXXXX, fictional) | WAF alert — initial access logged |
| 09:16 | Attacker reads service account token from /var/run/secrets/kubernetes.io/serviceaccount/token | -- |
| 09:17 | Attacker queries API server: kubectl get pods --all-namespaces — discovers CI runner pod with privileged context | API audit log captured but no alert |
| 09:19 | Attacker creates pod in ci-runners namespace using stolen service account token with privileged: true | Privileged container creation alert fires |
| 09:21 | From privileged pod, attacker runs nsenter --target 1 --mount --uts --ipc --net --pid -- bash to escape to node | Process audit on node captures nsenter |
| 09:24 | Attacker reads kubelet credentials from node filesystem, authenticates as kubelet to API server | -- |
| 09:26 | Attacker creates ClusterRoleBinding granting cluster-admin to compromised service account | ClusterRoleBinding change alert fires |
| 09:28 | Attacker lists all secrets: kubectl get secrets --all-namespaces -o json — harvests 28 secrets including database credentials and cloud IAM keys | Secrets anomaly alert fires |
| 09:32 | Attacker deploys cryptominer DaemonSet across all 6 worker nodes | DaemonSet creation in non-standard namespace detected |
| 09:35 | SOC analyst triages cascading alerts, identifies attack chain | -- |
| 09:38 | SOC isolates cluster network, revokes compromised service accounts | Containment |
| 09:45 | All secrets rotated, malicious workloads terminated, node images rebuilt | Eradication |
Root Causes¶
- CI runner pod ran as privileged — common shortcut for Docker-in-Docker builds, but grants full node access
- Service account tokens auto-mounted — default Kubernetes behavior, provided free API server credentials to every compromised pod
- No Pod Security Standards enforced — no admission controller prevented privileged pod creation
- Flat network — no network policies restricted pod-to-pod or pod-to-API-server communication
- Secrets unencrypted at rest — etcd encryption was not enabled
For cloud defense strategies that apply to this scenario, see Chapter 20: Cloud Attack & Defense.
5. Defensive Recommendations¶
-
Enforce Pod Security Standards — apply
restrictedprofile as the default for all namespaces. Only grantprivilegedorbaselineprofiles to namespaces with documented justification. UsePodSecurityadmission controller (built-in since v1.25) or OPA/Gatekeeper for custom policies. -
Disable automatic service account token mounting — set
automountServiceAccountToken: falseon all pods and service accounts that do not require API server access. Create dedicated service accounts with minimal RBAC permissions for pods that do. -
Deploy runtime security monitoring — tools like Falco, Tetragon, or KubeArmor detect container escapes, unexpected process execution, and filesystem modifications in real time. Alert on
nsenter,chroot, and host filesystem mounts. -
Enforce network policies — default-deny all ingress and egress at the namespace level. Explicitly allow only required communication paths. Block pod-to-control-plane traffic except from designated namespaces.
-
Enable etcd encryption at rest — configure the API server's
EncryptionConfigurationto encrypt secrets stored in etcd. Rotate encryption keys annually. -
Implement image admission controls — require image signatures (Cosign/Notary) and restrict pulls to approved registries via admission webhooks. Scan all images for CVEs before deployment.
The Bottom Line
Kubernetes misconfiguration is the primary attack vector — not zero-days. Enforce Pod Security Standards, disable default service account tokens, deploy network policies, and monitor the audit log. These four controls block the majority of cluster takeover chains.
Related Resources¶
- Chapter 46: Cloud & Container Red Team — container escape techniques and red team methodology for Kubernetes environments
- Chapter 20: Cloud Attack & Defense — cloud security fundamentals, shared responsibility, and defense strategies
- Chapter 35: DevSecOps Pipeline Security — securing CI/CD pipelines, image supply chain, and infrastructure-as-code
- Detection Query Library — pre-built KQL/SPL queries for SOC teams