Azure AKS Potential API Enumeration by User
Detects a single Kubernetes identity in AKS (Azure Kubernetes Service) that is denied (HTTP 403 Forbidden) across multiple distinct API resource types within a short window. Broad authorization failures spanning many resources are a strong signal of API enumeration (reconnaissance with a stolen service account token), as an actor probes what its credentials can reach before privilege escalation. Detection is based on the breadth of denied resources rather than the raw failure count, so single-resource controller retry loops do not trigger it.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2026/07/09"
3integration = ["azure"]
4maturity = "production"
5updated_date = "2026/07/09"
6
7[rule]
8author = ["Elastic"]
9description = """
10Detects a single Kubernetes identity in AKS (Azure Kubernetes Service) that is denied (HTTP 403 Forbidden) across
11multiple distinct API resource types within a short window. Broad authorization failures spanning many resources are a
12strong signal of API enumeration (reconnaissance with a stolen service account token), as an actor
13probes what its credentials can reach before privilege escalation. Detection is based on the breadth of denied resources
14rather than the raw failure count, so single-resource controller retry loops do not trigger it.
15"""
16false_positives = [
17 """
18 A workload or observability agent with partial RBAC can be denied across several resource types and resemble
19 enumeration (for example a monitoring agent that watches resources it lacks permission for). Baseline such
20 identities and raise the cardinality threshold, or exclude the specific validated service account, after review.
21 Single-resource retry loops (one resource denied repeatedly) do not trigger this rule because detection is based on
22 the number of distinct resources denied, not the raw failure count.
23 """,
24]
25from = "now-9m"
26index = ["logs-azure.platformlogs-*"]
27interval = "5m"
28language = "kuery"
29license = "Elastic License v2"
30name = "Azure AKS Potential API Enumeration by User"
31note = """## Triage and analysis
32
33### Investigating Azure AKS Potential API Enumeration by User
34
35AKS kube-audit events are carried under the flattened `azure.platformlogs.properties.log.*` subtree and share the ARM
36operation `event.action: Microsoft.ContainerService/managedClusters/diagnosticLogs/Read`. This rule groups forbidden
37(HTTP 403) Kubernetes API calls by `azure.platformlogs.properties.log.user.username` and alerts when one identity is
38denied across several distinct `objectRef.resource` types within the interval. Breadth of denied resources (rather than
39raw failure volume) is the signal: an identity probing many resource types it cannot reach is characteristic of API
40enumeration with a stolen service account token, whereas a controller stuck retrying one forbidden resource stays on a
41single resource and does not trigger.
42
43### Possible investigation steps
44
45- Enumerate the distinct `azure.platformlogs.properties.log.objectRef.resource` and
46 `azure.platformlogs.properties.log.verb` values denied for the identity, and read the human-readable denial in
47 `azure.platformlogs.properties.log.responseStatus.message` (for example "secrets is forbidden: User ... cannot list
48 resource"), to see what the actor was mapping out.
49- Identify the acting identity in `azure.platformlogs.properties.log.user.username` and its groups in
50 `azure.platformlogs.properties.log.user.groups`. Service account tokens (`system:serviceaccount:<ns>:<sa>`) probing
51 broadly are the primary concern; confirm whether that identity should be issuing these calls at all.
52- Inspect `azure.platformlogs.properties.log.userAgent` to distinguish interactive tooling (`kubectl`) or a known
53 controller from custom recon tooling (for example `kubectl-recon`, `curl`, or other enumeration clients).
54- Validate the source in `azure.platformlogs.properties.log.sourceIPs`. In-cluster agents use loopback
55 (`127.0.0.1`/`::1`) or pod-network addresses (e.g. `10.244.0.0/16`); an external caller wielding a service account
56 token is more suspicious.
57- Hunt for later successful calls (`responseStatus.code:2xx`) from the same identity or source that indicate the actor
58 found a permitted action or escalated, and correlate with recent Entra ID sign-ins or role assignments.
59
60### False positive analysis
61
62- A workload or observability agent with partial RBAC can be denied across several resource types and resemble
63 enumeration. Baseline such identities, raise the cardinality threshold, or exclude the specific validated service
64 account after review.
65- Single-resource retry loops (one resource denied repeatedly, such as a controller watching a resource it lacks
66 permission for) do not trigger this rule, since detection is based on the count of distinct resources denied.
67
68### Response and remediation
69
70- If unauthorized, revoke the identity's tokens and kubeconfig and review the RBAC bindings assigned to it.
71- Determine whether any request from the identity succeeded and scope the impact accordingly.
72- Collect kube-audit and identity artifacts per incident response procedures.
73"""
74references = [
75 "https://learn.microsoft.com/en-us/azure/aks/monitor-aks",
76 "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/",
77 "https://github.com/inguardians/peirates",
78]
79risk_score = 47
80rule_id = "13a3cc0e-1f69-4cc9-8f2f-892d7c7032dc"
81setup = """
82The Azure Fleet integration collecting AKS diagnostic logs forwarded through Event Hub into the `azure.platformlogs`
83data stream is required for this rule. The `kube-audit` log category is required specifically: authorization denials
84during enumeration are predominantly get/list/watch (read) operations, which the `kube-audit-admin` category excludes.
85A cluster that ships only `kube-audit-admin` is effectively blind to this rule, since only write-verb denials remain
86visible.
87"""
88severity = "medium"
89tags = [
90 "Domain: Cloud",
91 "Domain: Kubernetes",
92 "Data Source: Azure",
93 "Data Source: Azure Platform Logs",
94 "Data Source: Kubernetes",
95 "Use Case: Threat Detection",
96 "Tactic: Discovery",
97 "Resources: Investigation Guide",
98]
99timestamp_override = "event.ingested"
100type = "threshold"
101
102query = '''
103data_stream.dataset:azure.platformlogs and
104 event.action:"Microsoft.ContainerService/managedClusters/diagnosticLogs/Read" and
105 azure.platformlogs.category:"kube-audit" and
106 azure.platformlogs.properties.log.stage:"ResponseComplete" and
107 azure.platformlogs.properties.log.responseStatus.code:"403" and
108 azure.platformlogs.properties.log.responseStatus.reason:"Forbidden" and
109 not azure.platformlogs.properties.log.user.username:(
110 system\:node\:* or "aksService" or "hcpService" or "readinessChecker" or
111 system\:serviceaccount\:kube-system\:*
112 )
113'''
114
115[rule.investigation_fields]
116field_names = [
117 "@timestamp",
118 "event.action",
119 "azure.platformlogs.category",
120 "azure.platformlogs.properties.log.verb",
121 "azure.platformlogs.properties.log.user.username",
122 "azure.platformlogs.properties.log.user.groups",
123 "azure.platformlogs.properties.log.userAgent",
124 "azure.platformlogs.properties.log.sourceIPs",
125 "azure.platformlogs.properties.log.objectRef.resource",
126 "azure.platformlogs.properties.log.objectRef.namespace",
127 "azure.platformlogs.properties.log.requestURI",
128 "azure.platformlogs.properties.log.responseStatus.code",
129 "azure.platformlogs.properties.log.responseStatus.reason",
130 "azure.platformlogs.properties.log.responseStatus.message",
131]
132
133[rule.threshold]
134field = [
135 "azure.resource.id",
136 "azure.platformlogs.properties.log.user.username"
137]
138value = 1
139
140[[rule.threshold.cardinality]]
141field = "azure.platformlogs.properties.log.objectRef.resource"
142value = 4
143
144[[rule.threat]]
145framework = "MITRE ATT&CK"
146
147[[rule.threat.technique]]
148id = "T1613"
149name = "Container and Resource Discovery"
150reference = "https://attack.mitre.org/techniques/T1613/"
151
152[rule.threat.tactic]
153id = "TA0007"
154name = "Discovery"
155reference = "https://attack.mitre.org/tactics/TA0007/"
Triage and analysis
Investigating Azure AKS Potential API Enumeration by User
AKS kube-audit events are carried under the flattened azure.platformlogs.properties.log.* subtree and share the ARM
operation event.action: Microsoft.ContainerService/managedClusters/diagnosticLogs/Read. This rule groups forbidden
(HTTP 403) Kubernetes API calls by azure.platformlogs.properties.log.user.username and alerts when one identity is
denied across several distinct objectRef.resource types within the interval. Breadth of denied resources (rather than
raw failure volume) is the signal: an identity probing many resource types it cannot reach is characteristic of API
enumeration with a stolen service account token, whereas a controller stuck retrying one forbidden resource stays on a
single resource and does not trigger.
Possible investigation steps
- Enumerate the distinct
azure.platformlogs.properties.log.objectRef.resourceandazure.platformlogs.properties.log.verbvalues denied for the identity, and read the human-readable denial inazure.platformlogs.properties.log.responseStatus.message(for example "secrets is forbidden: User ... cannot list resource"), to see what the actor was mapping out. - Identify the acting identity in
azure.platformlogs.properties.log.user.usernameand its groups inazure.platformlogs.properties.log.user.groups. Service account tokens (system:serviceaccount:<ns>:<sa>) probing broadly are the primary concern; confirm whether that identity should be issuing these calls at all. - Inspect
azure.platformlogs.properties.log.userAgentto distinguish interactive tooling (kubectl) or a known controller from custom recon tooling (for examplekubectl-recon,curl, or other enumeration clients). - Validate the source in
azure.platformlogs.properties.log.sourceIPs. In-cluster agents use loopback (127.0.0.1/::1) or pod-network addresses (e.g.10.244.0.0/16); an external caller wielding a service account token is more suspicious. - Hunt for later successful calls (
responseStatus.code:2xx) from the same identity or source that indicate the actor found a permitted action or escalated, and correlate with recent Entra ID sign-ins or role assignments.
False positive analysis
- A workload or observability agent with partial RBAC can be denied across several resource types and resemble enumeration. Baseline such identities, raise the cardinality threshold, or exclude the specific validated service account after review.
- Single-resource retry loops (one resource denied repeatedly, such as a controller watching a resource it lacks permission for) do not trigger this rule, since detection is based on the count of distinct resources denied.
Response and remediation
- If unauthorized, revoke the identity's tokens and kubeconfig and review the RBAC bindings assigned to it.
- Determine whether any request from the identity succeeded and scope the impact accordingly.
- Collect kube-audit and identity artifacts per incident response procedures.
References
Related rules
- Azure AKS Suspicious Self-Subject Review by Service Account or Node Identity
- Azure AKS Ephemeral Container Added to Pod
- Azure AKS Attempted User Exec into Pod
- Azure AKS API Server Proxying Request to Kubelet
- Azure AKS Kubelet Proxy to Command Execution Endpoint