Azure AKS Secret get or list with Suspicious User Agent

edit
IMPORTANT: This documentation is no longer updated. Refer to Elastic's version policy and the latest documentation.

Azure AKS Secret get or list with Suspicious User Agent

edit

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.

Rule type: query

Rule indices:

  • logs-azure.platformlogs-*

Severity: high

Risk score: 73

Runs every: 5m

Searches indices from: now-9m (Date Math format, see also Additional look-back time)

Maximum alerts per execution: 100

References:

Tags:

  • Domain: Cloud
  • Domain: Kubernetes
  • Data Source: Azure
  • Data Source: Azure Platform Logs
  • Data Source: Kubernetes
  • Use Case: Threat Detection
  • Tactic: Credential Access
  • Resources: Investigation Guide

Version: 1

Rule authors:

  • Elastic

Rule license: Elastic License v2

Investigation guide

edit

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.username and its group memberships in azure.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 (allow vs forbid) and the azure.platformlogs.properties.log.responseStatus.code.
  • Review the targeted secret via azure.platformlogs.properties.log.objectRef.namespace and azure.platformlogs.properties.log.objectRef.name, and the exact API path in azure.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.0 user agent when no custom agent is set (see kubernetes/kubernetes#108726), so an operator or platform component reading secrets may match Go-http*. Exclude the specific benign identity (for example system:serviceaccount:kube-system:* or a validated operator service account) rather than removing the Go-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.

Setup

edit

The Azure Fleet integration collecting AKS diagnostic logs forwarded through Event Hub into the azure.platformlogs data stream is required for this rule. The kube-audit log category is required specifically: secret get/list are read operations, which the kube-audit-admin category excludes, so a cluster shipping only kube-audit-admin is blind to this rule.

Rule query

edit
data_stream.dataset:azure.platformlogs and
  event.action:"Microsoft.ContainerService/managedClusters/diagnosticLogs/Read" and
  azure.platformlogs.category:"kube-audit" and
  azure.platformlogs.properties.log.responseStatus.code:("200" or "201") and
  azure.platformlogs.properties.log.verb:("get" or "list") and
  azure.platformlogs.properties.log.objectRef.resource:"secrets" and
  azure.platformlogs.properties.log.userAgent:(
    curl* or python* or Python* or wget* or Wget* or Go-http* or perl* or libwww-perl* or
    java* or Java* or node* or php* or Guzzle* or Bun* or axios* or undici* or okhttp* or
    Apache-HttpClient* or HTTPie* or Ruby* or PostmanRuntime* or RestSharp* or *distrib#kali* or *kali-amd64* or *kali-arm64*
  )

Framework: MITRE ATT&CKTM