Azure AKS Secret get or list with Suspicious User Agent
Detects successful AKS (Azure Kubernetes Service) secret get or list operations where the user agent matches scripting runtimes (python, ruby, perl), command-line HTTP clients (curl, wget, HTTPie), or generic HTTP libraries (Go-http-client, okhttp, Apache-HttpClient, Guzzle, axios, undici) rather than typical kubectl or named controller traffic. Reading Kubernetes secrets with a generic client is a common credential-access step after a token or kubeconfig is stolen, and offensive tooling (for example peirates and kdigger) frequently reaches the API with a default Go HTTP client.
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 successful AKS (Azure Kubernetes Service) secret get or list operations where the user agent matches scripting
11runtimes (python, ruby, perl), command-line HTTP clients (curl, wget, HTTPie), or generic HTTP libraries (Go-http-client,
12okhttp, Apache-HttpClient, Guzzle, axios, undici) rather than typical kubectl or named controller traffic. Reading
13Kubernetes secrets with a generic client is a common credential-access step after a token or kubeconfig is stolen, and
14offensive tooling (for example peirates and kdigger) frequently reaches the API with a default Go HTTP client.
15"""
16false_positives = [
17 """
18 Approved scripts, CI jobs, or penetration tests may use generic HTTP clients. Validate change tickets and identity
19 scope before treating as compromise. Internal automation using generic libraries can be excluded by stable service
20 account after review.
21 """,
22]
23from = "now-9m"
24index = ["logs-azure.platformlogs-*"]
25language = "kuery"
26license = "Elastic License v2"
27name = "Azure AKS Secret get or list with Suspicious User Agent"
28note = """## Triage and analysis
29
30### Investigating Azure AKS Secret get or list with Suspicious User Agent
31
32AKS kube-audit events are carried under the flattened `azure.platformlogs.properties.log.*` subtree and share the ARM
33operation `event.action: Microsoft.ContainerService/managedClusters/diagnosticLogs/Read`. This rule fires when a
34successful `get` or `list` against Kubernetes `secrets` is issued with a user agent that matches scripting runtimes
35(python, ruby, perl), command-line HTTP clients (curl, wget, HTTPie), or generic HTTP libraries (Go-http-client, okhttp,
36Apache-HttpClient, Guzzle, axios, undici) rather than typical `kubectl` or named controller traffic. The user agent is
37trivially spoofable (the telemetry shows offensive tooling masquerading as `kubectl`), so this is a corroborating
38indicator, not proof.
39
40### Possible investigation steps
41
42- Identify the acting identity in `azure.platformlogs.properties.log.user.username` and its group memberships in
43 `azure.platformlogs.properties.log.user.groups`. Control-plane and node identities (`system:apiserver`, `aksService`,
44 `system:node:*`, `system:serviceaccount:kube-system:*`) are expected; a human or service-principal identity reading
45 secrets with a scripted client is not.
46- Confirm the request was authorized by checking
47 `azure.platformlogs.properties.log.annotations.authorization.k8s.io/decision` (`allow` vs `forbid`) and the
48 `azure.platformlogs.properties.log.responseStatus.code`.
49- Review the targeted secret via `azure.platformlogs.properties.log.objectRef.namespace` and
50 `azure.platformlogs.properties.log.objectRef.name`, and the exact API path in
51 `azure.platformlogs.properties.log.requestURI`.
52- Evaluate the source in `azure.platformlogs.properties.log.sourceIPs`. In-cluster control-plane traffic uses loopback
53 (`::1`) or node subnet addresses; a public or pod-network source for a secret read is more suspicious. Pivot on the
54 source for other API bursts, exec sessions, or RBAC changes.
55- Correlate with recent Entra ID sign-ins or role assignments for the identity to determine whether the token was
56 recently issued or scoped unusually.
57
58### False positive analysis
59
60- Approved scripts, CI jobs, or penetration tests may use generic HTTP clients. Validate identity scope before treating
61 as compromise.
62- Internal automation using generic libraries can be excluded by stable service account after review.
63- The kubelet and controllers built on client-go can default to a `Go-http-client/2.0` user agent when no custom agent
64 is set (see kubernetes/kubernetes#108726), so an operator or platform component reading secrets may match `Go-http*`.
65 Exclude the specific benign identity (for example `system:serviceaccount:kube-system:*` or a validated operator
66 service account) rather than removing the `Go-http*` pattern, which also catches default-user-agent offensive tooling.
67
68### Response and remediation
69
70- If unauthorized, revoke the identity's tokens and kubeconfig, rotate the exposed secrets, and review RBAC that permits
71 secret reads.
72- Hunt for downstream use of the retrieved secrets, such as new sign-ins, workload deployments, or outbound connections.
73- Collect kube-audit and identity artifacts per incident response procedures.
74"""
75references = [
76 "https://kubernetes.io/docs/concepts/configuration/secret/",
77 "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/",
78 "https://unit42.paloaltonetworks.com/hildegard-malware-teamtnt/",
79 "https://unit42.paloaltonetworks.com/modern-kubernetes-threats/",
80 "https://www.sysdig.com/blog/teamtnt-kubelet-credentials",
81 "https://github.com/kubernetes/kubernetes/issues/108726",
82]
83risk_score = 73
84rule_id = "4eaf5dd4-c511-4d0e-b66d-e218e6e3da76"
85setup = """
86The Azure Fleet integration collecting AKS diagnostic logs forwarded through Event Hub into the `azure.platformlogs`
87data stream is required for this rule. The `kube-audit` log category is required specifically: secret get/list are
88read operations, which the `kube-audit-admin` category excludes, so a cluster shipping only `kube-audit-admin` is blind
89to this rule.
90"""
91severity = "high"
92tags = [
93 "Domain: Cloud",
94 "Domain: Kubernetes",
95 "Data Source: Azure",
96 "Data Source: Azure Platform Logs",
97 "Data Source: Kubernetes",
98 "Use Case: Threat Detection",
99 "Tactic: Credential Access",
100 "Resources: Investigation Guide",
101]
102timestamp_override = "event.ingested"
103type = "query"
104
105query = '''
106data_stream.dataset:azure.platformlogs and
107 event.action:"Microsoft.ContainerService/managedClusters/diagnosticLogs/Read" and
108 azure.platformlogs.category:"kube-audit" and
109 azure.platformlogs.properties.log.responseStatus.code:("200" or "201") and
110 azure.platformlogs.properties.log.verb:("get" or "list") and
111 azure.platformlogs.properties.log.objectRef.resource:"secrets" and
112 azure.platformlogs.properties.log.userAgent:(
113 curl* or python* or Python* or wget* or Wget* or Go-http* or perl* or libwww-perl* or
114 java* or Java* or node* or php* or Guzzle* or Bun* or axios* or undici* or okhttp* or
115 Apache-HttpClient* or HTTPie* or Ruby* or PostmanRuntime* or RestSharp* or *distrib#kali* or *kali-amd64* or *kali-arm64*
116 )
117'''
118
119[rule.investigation_fields]
120field_names = [
121 "@timestamp",
122 "event.action",
123 "azure.platformlogs.category",
124 "azure.platformlogs.properties.log.verb",
125 "azure.platformlogs.properties.log.user.username",
126 "azure.platformlogs.properties.log.userAgent",
127 "azure.platformlogs.properties.log.sourceIPs",
128 "azure.platformlogs.properties.log.objectRef.resource",
129 "azure.platformlogs.properties.log.objectRef.namespace",
130 "azure.platformlogs.properties.log.objectRef.name",
131 "azure.platformlogs.properties.log.responseStatus.code",
132]
133
134[[rule.threat]]
135framework = "MITRE ATT&CK"
136
137[[rule.threat.technique]]
138id = "T1552"
139name = "Unsecured Credentials"
140reference = "https://attack.mitre.org/techniques/T1552/"
141
142[[rule.threat.technique.subtechnique]]
143id = "T1552.007"
144name = "Container API"
145reference = "https://attack.mitre.org/techniques/T1552/007/"
146
147[rule.threat.tactic]
148id = "TA0006"
149name = "Credential Access"
150reference = "https://attack.mitre.org/tactics/TA0006/"
Triage and analysis
Investigating Azure AKS Secret get or list with Suspicious User Agent
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 fires when a
successful get or list against Kubernetes secrets is issued with a user agent that matches scripting runtimes
(python, ruby, perl), command-line HTTP clients (curl, wget, HTTPie), or generic HTTP libraries (Go-http-client, okhttp,
Apache-HttpClient, Guzzle, axios, undici) rather than typical kubectl or named controller traffic. The user agent is
trivially spoofable (the telemetry shows offensive tooling masquerading as kubectl), so this is a corroborating
indicator, not proof.
Possible investigation steps
- Identify the acting identity in
azure.platformlogs.properties.log.user.usernameand its group memberships inazure.platformlogs.properties.log.user.groups. Control-plane and node identities (system:apiserver,aksService,system:node:*,system:serviceaccount:kube-system:*) are expected; a human or service-principal identity reading secrets with a scripted client is not. - Confirm the request was authorized by checking
azure.platformlogs.properties.log.annotations.authorization.k8s.io/decision(allowvsforbid) and theazure.platformlogs.properties.log.responseStatus.code. - Review the targeted secret via
azure.platformlogs.properties.log.objectRef.namespaceandazure.platformlogs.properties.log.objectRef.name, and the exact API path inazure.platformlogs.properties.log.requestURI. - Evaluate the source in
azure.platformlogs.properties.log.sourceIPs. In-cluster control-plane traffic uses loopback (::1) or node subnet addresses; a public or pod-network source for a secret read is more suspicious. Pivot on the source for other API bursts, exec sessions, or RBAC changes. - Correlate with recent Entra ID sign-ins or role assignments for the identity to determine whether the token was recently issued or scoped unusually.
False positive analysis
- Approved scripts, CI jobs, or penetration tests may use generic HTTP clients. Validate identity scope before treating as compromise.
- Internal automation using generic libraries can be excluded by stable service account after review.
- The kubelet and controllers built on client-go can default to a
Go-http-client/2.0user agent when no custom agent is set (see kubernetes/kubernetes#108726), so an operator or platform component reading secrets may matchGo-http*. Exclude the specific benign identity (for examplesystem:serviceaccount:kube-system:*or a validated operator service account) rather than removing theGo-http*pattern, which also catches default-user-agent offensive tooling.
Response and remediation
- If unauthorized, revoke the identity's tokens and kubeconfig, rotate the exposed secrets, and review RBAC that permits secret reads.
- Hunt for downstream use of the retrieved secrets, such as new sign-ins, workload deployments, or outbound connections.
- Collect kube-audit and identity artifacts per incident response procedures.
References
Related rules
- Azure AKS Kubernetes Events Deleted
- Azure AKS Potential API Enumeration by User
- 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