Skip to content

CHAIN-049 — AKS full stack compromise via public registry and layered misconfigurations

Summary

Severity: Critical · Likelihood: High · Logic: ANCHOR_PLUS_ONE · Anchor: zt_wl_013

Why this chain matters

This is the Kubernetes nightmare scenario where every layer of the stack is misconfigured simultaneously. The Azure Container Registry allows public (anonymous) access, serving as the anchor finding that enables supply-chain injection. On top of that, one or more of the following conditions amplify the blast radius: ACR admin account is enabled (providing a static, non-rotatable credential), AKS has no network policy enforcement (pods can communicate freely across namespaces), Azure RBAC for Kubernetes is not enabled (legacy kubeconfig grants cluster-admin), pod security standards are not enforced (privileged pods can escape to the node), and Microsoft Defender for Containers is not enabled (runtime threats go undetected). An attacker who pushes a malicious image to the public ACR can escalate through whichever combination of these weaknesses exists, ultimately achieving cluster-admin, node-level access, and control-plane compromise of the entire AKS environment.

Component rules

This chain fires when its trigger conditions are met by the following rules. Click any rule to see its detection logic and compliance mappings.

Rule ID Role
zt_wl_013 Anchor
zt_wl_012 Trigger
zt_wl_014 Trigger
zt_wl_015 Trigger
zt_wl_016 Trigger
zt_wl_021 Trigger

Attack walkthrough

Step 1 — Push a malicious container image to the publicly accessible ACR, optionally using the admin credential.

Actor: Supply-chain attacker
MITRE ATT&CK: T1195.002
Enabled by: zt_wl_013

ACR is configured with publicNetworkAccess=Enabled and anonymousPullEnabled=true (zt_wl_013). If the admin account is enabled (zt_wl_012), the attacker may also use the static admin username/password (available via az acr credential show) to push. Image tag 'latest' or a version tag is overwritten with a trojanised image.

Attacker gain: Malicious image placed at a trusted tag in the production registry.

Step 2 — Pull and deploy the tainted image as a privileged pod due to missing pod security enforcement.

Actor: AKS cluster (automated pull)
MITRE ATT&CK: T1610
Enabled by: zt_wl_016

No pod security standards (zt_wl_016) means the malicious image's pod spec can request privileged=true, hostPID=true, hostNetwork=true, and mount hostPath=/. The Kubernetes admission controller does not reject the escalated pod spec.

Attacker gain: Malicious container running with full host privileges inside the AKS cluster.

Step 3 — Escape the container to the underlying node and steal the kubelet's managed identity token.

Actor: Attacker in privileged pod
MITRE ATT&CK: T1611
Enabled by: zt_wl_016

Mount the host filesystem via hostPath=/, access /var/lib/kubelet and the container runtime socket. Query IMDS at 169.254.169.254 from the host network namespace to obtain the node's managed identity token.

Attacker gain: Root access on the AKS node and a valid ARM token for the node's managed identity.

Step 4 — Move laterally across namespaces exploiting the absence of network policies.

Actor: Attacker on node
MITRE ATT&CK: T1210
Enabled by: zt_wl_014

No Kubernetes network policies (zt_wl_014) means all pod-to-pod traffic is allowed across every namespace. The attacker's pod can reach kube-system components, monitoring agents, and every application pod's exposed ports directly.

Attacker gain: Unrestricted network access to every pod and service in every namespace of the cluster.

Step 5 — Obtain cluster-admin privileges via legacy kubeconfig because Azure RBAC for Kubernetes is disabled.

Actor: Attacker with cluster access
MITRE ATT&CK: T1078.001
Enabled by: zt_wl_015

Without Azure RBAC for AKS (zt_wl_015), the cluster uses legacy Kubernetes RBAC. The attacker extracts the cluster-admin kubeconfig from the compromised node or from the AKS management API using the stolen managed identity token (az aks get-credentials --admin).

Attacker gain: Full cluster-admin Kubernetes API access - can create, modify, and delete any resource in any namespace.

Step 6 — Operate with impunity as Defender for Containers is not monitoring runtime threats.

Actor: Attacker with cluster-admin
MITRE ATT&CK: T1562.001
Enabled by: zt_wl_021

Microsoft Defender for Containers (zt_wl_021) is not enabled, so runtime threat detections (crypto mining, reverse shells, suspicious exec into containers, known malicious images) are not generated. The attacker's activities produce no security alerts.

Attacker gain: Complete AKS stack compromise with no runtime detection: registry to pod to node to cluster-admin, entirely unmonitored.

Blast radius

Initial access Publicly accessible Azure Container Registry allowing anonymous image push.
Lateral movement Container → privileged pod → node → cross-namespace (no network policy) → cluster-admin (no Azure RBAC).
Max privilege cluster-admin on AKS + node-level managed identity on ARM + potential access to all downstream services the cluster identity can reach.
Data at risk All application data accessible to cluster workloads, Kubernetes Secrets (including TLS certs and service credentials), Persistent Volumes and their contents, Container registry images (IP, source code)
Services at risk AKS, ACR, Resource Manager (via node identity), All services consumed by cluster workloads
Estimated scope 100% of the AKS cluster and its resource group

How the logic works

The chain fires when the anchor rule fires AND at least one of the other triggers fires. The anchor represents the initial foothold; the second rule amplifies it into a meaningful attack. Remediate the anchor to eliminate the entire chain.