KCSA — Kubernetes-Specific Threats
Kubernetes-Specific vs. Generic Threats
While many security threats (SQL injection, XSS, buffer overflows) apply to all systems, Kubernetes introduces a set of threats that are unique to its architecture. These arise from how Kubernetes manages workloads, handles identity, stores configuration, and enforces access control.
The KCSA exam focuses heavily on threats that are specific to Kubernetes — not generic application-layer vulnerabilities. This section covers those Kubernetes-native threats in detail.
RBAC Misconfiguration Threats
Role-Based Access Control (RBAC) is Kubernetes’ primary authorization mechanism. Misconfigurations in RBAC are among the most common and most dangerous Kubernetes-specific threats.
Common RBAC Misconfigurations
| Misconfiguration | Risk | Example |
|---|---|---|
Wildcard verbs (*) |
Grants ALL operations on a resource | verbs: ["*"] allows create, delete, escalate |
Wildcard resources (*) |
Grants access to ALL resources | resources: ["*"] includes Secrets, RBAC resources |
Wildcard API groups (*) |
Grants access to ALL API groups | apiGroups: ["*"] includes RBAC, apps, extensions |
| cluster-admin binding to users | Full cluster access with no restrictions | ClusterRoleBinding to cluster-admin for devs |
| cluster-admin binding to ServiceAccounts | Any pod using that SA has full cluster control | Commonly seen in CI/CD serviceaccounts |
| Overpermissive default ServiceAccount | Every pod in the namespace gets excessive access | Adding roles to default SA in a namespace |
| Ability to create RoleBindings | Can self-escalate by binding to higher roles | verbs: ["create"] on rolebindings resource |
| Pod creation permissions | Can create privileged pods to escape to host | verbs: ["create"] on pods resource |
# DANGEROUS: Overly permissive ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: too-permissive
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
The ability to create pods, create rolebindings, or escalate privileges are all privilege escalation vectors. Any ServiceAccount with these permissions should be carefully controlled.
RBAC Escalation Prevention
Kubernetes has a built-in protection: the escalation prevention rule. A user cannot grant permissions they do not already have — unless they have the escalate verb on the roles or clusterroles resource.
# This allows a user to escalate RBAC — extremely dangerous
rules:
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["clusterroles"]
verbs: ["escalate"]
However, this protection has gaps:
- Users who can create pods can mount SA tokens with higher privileges
- Users who can patch RoleBindings can change which role is referenced
- Users who can create RoleBindings can bind to existing high-privilege roles
Exposed Kubernetes Dashboard
The Kubernetes Dashboard provides a web-based UI for managing the cluster. When misconfigured, it becomes a direct path to cluster compromise.
How Dashboard Exposure Happens
- Dashboard deployed with no authentication (skip login enabled)
- Dashboard exposed via NodePort or LoadBalancer instead of
kubectl proxy - Dashboard ServiceAccount granted cluster-admin permissions
- No network policy restricting access to the Dashboard pod
Real-World Impact
The Tesla cryptojacking incident (2018) was caused by an exposed Kubernetes Dashboard:
- Attackers discovered the Dashboard was accessible without authentication
- Through the Dashboard, they accessed AWS credentials stored as Kubernetes Secrets
- They deployed cryptocurrency mining pods
- They configured the mining to use a non-standard pool to avoid detection
Secure Dashboard Configuration
- Never expose the Dashboard to the internet
- Use
kubectl proxyfor local access only - Require authentication (token-based or OIDC)
- Grant the Dashboard SA minimal RBAC permissions (read-only if possible)
- Apply a NetworkPolicy to restrict who can reach the Dashboard pod
The Kubernetes Dashboard should never be exposed publicly. Even with authentication, it is a high-value target. Use kubectl proxy or a VPN.
Insecure etcd Access
etcd is the backbone of Kubernetes — it stores every resource object, Secret, RBAC policy, and configuration in the cluster.
Why etcd Is a Critical Target
- No authorization layer — etcd does not have its own RBAC; if you can connect, you can read and write everything
- Secrets stored in plain text by default — Without encryption at rest, Secrets are base64-encoded but not encrypted in etcd
- Full cluster control — An attacker with etcd write access can create cluster-admin bindings, modify pod specs, or delete critical resources
etcd Attack Scenarios
| Scenario | How It Happens | Impact |
|---|---|---|
| Direct network access | etcd ports (2379/2380) exposed without firewall rules | Full cluster compromise |
| No TLS | Client-to-etcd communication unencrypted | Traffic interception, MitM attacks |
| No client cert auth | Any client can connect to etcd | Unauthorized data access |
| Backup theft | etcd backups stored without encryption | All cluster data exposed offline |
| Snapshot restore | Attacker restores a malicious snapshot | Cluster state overwritten |
Securing etcd
- Restrict network access — etcd should only be reachable by the API server
- Enable TLS — Both client-to-server and peer-to-peer (server-to-server) communication
- Require client certificate authentication — Only the API server’s certificate should be trusted
- Enable encryption at rest — Use
EncryptionConfigurationto encrypt Secrets in etcd - Encrypt backups — etcd backups contain full cluster state; encrypt them at rest
# EncryptionConfiguration for encrypting Secrets in etcd
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: <base64-encoded-32-byte-key>
- identity: {}
Malicious Container Images
Container images are one of the primary supply chain attack vectors in Kubernetes.
Types of Malicious Image Threats
| Threat | Description | Example |
|---|---|---|
| Typosquatting | Images with names similar to popular images | ngimx instead of nginx, pythonn instead of python |
| Backdoored base images | Legitimate-looking images with hidden malware | Base image with a reverse shell added |
| Compromised official images | Official images tampered with at the registry | SolarWinds-style supply chain attack |
| Vulnerable images | Images with known CVEs in OS packages or libraries | Apache Log4j, OpenSSL vulnerabilities |
| No image tags | Using latest tag, which can be overwritten by anyone |
Image pulled today may differ from image pulled tomorrow |
| No digest pinning | Tags are mutable; images can change under the same tag | Attacker replaces a tagged image with a malicious one |
Mitigations
- Use private registries — Don’t pull directly from Docker Hub in production
- Scan images — Use Trivy, Grype, or Snyk to scan for CVEs
- Sign images — Use Cosign (Sigstore) to sign and verify images
- Enforce via admission — Use an admission webhook (Kyverno, OPA Gatekeeper) to block unsigned or vulnerable images
- Pin image digests — Use
image: nginx@sha256:abc123...instead ofimage: nginx:latest
# Safe: Image pinned by digest
containers:
- name: web
image: nginx@sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31
Never use latest or mutable tags in production. Always pin images by digest to ensure you are running exactly the image you intended.
Tiller (Helm v2) — Historical Vulnerability
While Helm v2 is deprecated, the Tiller vulnerability is a classic example of a Kubernetes-specific threat that may appear on the exam as a historical reference.
What Was Tiller?
- Helm v2 used a server-side component called Tiller that ran inside the cluster
- Tiller had cluster-admin privileges by default
- Tiller’s gRPC API had no authentication
- Any pod in the cluster could reach Tiller and perform any cluster operation
Why It Matters
- Demonstrates the risk of running privileged services without authentication
- Helm v3 removed Tiller entirely, using the client’s kubeconfig credentials instead
- This pattern (privileged service + no auth + network accessible) recurs in many Kubernetes-specific threats
Kubelet API Exposure
The kubelet runs on every worker node and provides an API for managing pods on that node.
Anonymous Authentication
When kubelet anonymous authentication is enabled:
# kubelet config — DANGEROUS
authentication:
anonymous:
enabled: true
authorization:
mode: AlwaysAllow
An attacker who can reach port 10250 can:
- List all pods on the node
- Execute commands inside any container on the node
- Read container logs including sensitive output
- Retrieve container metrics for reconnaissance
Read-Only Port (10255)
The kubelet read-only port exposes pod and node information without any authentication:
# Enumerating pods on a node via the read-only port
curl http://<node-ip>:10255/pods
This is deprecated but may still be enabled on older clusters.
Mitigation
- Disable anonymous authentication:
authentication.anonymous.enabled: false - Use webhook authorization:
authorization.mode: Webhook - Close port 10255 entirely
- Use NetworkPolicy or firewall rules to restrict access to port 10250
Admission Controller Bypass Scenarios
Admission controllers enforce policies on API requests. Bypassing them undermines the entire policy enforcement layer.
How Admission Controllers Can Be Bypassed
| Bypass Scenario | Description |
|---|---|
| Not all resource types covered | Policy checks pods but not Deployments, which create pods |
| Namespace exceptions | kube-system or other namespaces excluded from policy enforcement |
| Static pods | Pods created by kubelet directly bypass API server admission |
| Webhook failure policy: Ignore | If the webhook is down, requests are allowed through (failurePolicy: Ignore) |
| Ephemeral containers | Some admission controllers don’t check ephemeral containers added via kubectl debug |
# Dangerous: Webhook allows requests when unavailable
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: my-policy
webhooks:
- name: validate.example.com
failurePolicy: Ignore # Should be "Fail" in production
Always set failurePolicy: Fail for security-critical admission webhooks. Ignore means that if the webhook is down, all requests pass through unenforced.
ConfigMap and Secret Exposure via API
Kubernetes Secrets and ConfigMaps are accessible via the API server. Over-permissive RBAC can expose them.
Secrets Are Not Encrypted by Default
- Secrets are stored in etcd base64-encoded — not encrypted
- Any user or ServiceAccount with
get/listonsecretscan read them - The default ServiceAccount in a namespace may have more access than intended
Common Exposure Patterns
- ServiceAccount with
get secretsin all namespaces - Secrets injected as environment variables (visible in
/proc) - Secrets logged by applications in plain text
- Secrets visible in
kubectl describe podoutput (when used as env vars)
Mitigation
- Apply least privilege — only grant
geton specific Secrets by name - Use external secret managers (HashiCorp Vault, AWS Secrets Manager)
- Enable encryption at rest for etcd
- Use projected service account tokens instead of long-lived tokens
Compromised Node Attack Scenarios
When an attacker gains root access to a Kubernetes worker node, the blast radius is significant.
What a Compromised Node Gives an Attacker
| Access | Description |
|---|---|
| All pods on the node | Access to every container’s filesystem, environment, and running processes |
| Kubelet credentials | The kubelet’s client certificate for API server access |
| Container runtime | Direct access to the container runtime socket (containerd, CRI-O) |
| Host network | Ability to sniff traffic from all pods on the node |
| CNI credentials | Network plugin credentials and configuration |
| Mounted Secrets | All Secrets mounted as volumes in pods on that node |
| Cloud credentials | Node instance metadata (IMDS) with cloud IAM role |
Mitigation
- Use Node Authorization to limit what kubelet credentials can access (only resources for pods on that node)
- Apply Pod Security Standards to prevent pods from accessing host resources
- Enable runtime monitoring (Falco) to detect suspicious node-level activity
- Use immutable/minimal node OS (Bottlerocket, Talos) to reduce attack surface
Namespace Breakout
Namespaces provide logical isolation, but they are not a security boundary without additional configuration.
How Namespace Isolation Fails
| Gap | Description |
|---|---|
| No NetworkPolicy | Pods in different namespaces can communicate freely |
| Shared ServiceAccount | Default SA with broad cluster-scoped permissions |
| Cluster-scoped resources | ClusterRoles, PersistentVolumes, Nodes are not namespace-scoped |
| Shared nodes | Multiple namespaces’ pods run on the same node |
| DNS discovery | Pods can discover services in other namespaces via DNS |
Achieving Namespace Isolation
For strong namespace isolation:
- Default-deny NetworkPolicy in every namespace
- RBAC scoped per namespace — no cluster-wide roles for regular users
- ResourceQuota per namespace — prevent resource starvation
- Pod Security Standards (Restricted) — enforced per namespace via admission
- Separate node pools for sensitive namespaces (if available)
- Disable automountServiceAccountToken for the default SA
Namespaces are organizational units, NOT security boundaries. You must layer RBAC, NetworkPolicy, PSS, and ResourceQuotas on top to achieve real isolation.
Threat Summary Table
| Threat | Why It’s K8s-Specific | Primary Mitigation |
|---|---|---|
| RBAC misconfiguration | RBAC is a Kubernetes-native concept | Least-privilege roles, no wildcards, audit |
| Exposed Dashboard | K8s Dashboard is a native web UI | Never expose publicly, use kubectl proxy |
| Insecure etcd | etcd is the K8s state store | TLS, client certs, network restriction |
| Malicious images | Container images are the K8s deployment unit | Scanning, signing, admission control |
| Tiller (Helm v2) | Helm v2’s Tiller ran inside the cluster | Upgrade to Helm v3 (Tiller removed) |
| Kubelet API exposure | Kubelet is a K8s node agent | Disable anonymous auth, webhook authz |
| Admission bypass | Admission controllers are K8s policy enforcement | failurePolicy: Fail, cover all resource types |
| Secret exposure | K8s Secrets API stores sensitive data | Encryption at rest, external secrets |
| Compromised node | Nodes run K8s workloads with kubelet creds | Node authz, minimal OS, runtime detection |
| Namespace breakout | Namespaces are K8s-native logical boundaries | NetworkPolicy, RBAC, PSS per namespace |
Key Takeaways for the Exam
| Concept | What to Remember |
|---|---|
| RBAC wildcards | * in verbs/resources/apiGroups is almost always wrong in production |
| Pod creation | Ability to create pods ≈ ability to escalate to node-level access |
| Dashboard | Never expose publicly; Tesla breach was caused by unauthenticated Dashboard |
| etcd | No internal authz — access = full cluster compromise |
| Image security | Pin by digest, scan, sign, enforce via admission |
| Kubelet | Port 10250 + anonymous auth = execute in any pod on that node |
| Admission controllers | failurePolicy: Ignore = no enforcement when webhook is down |
| Secrets | Base64 ≠ encryption; enable encryption at rest |
| Namespaces | Not a security boundary without NetworkPolicy + RBAC |
- KCSA expects you to identify which threat applies to a given scenario
- Understand the “why” behind each threat, not just the name
- Know which mitigations map to which threats — this is frequently tested
Next: Mitigation Strategies →