Detection rules › Elastic

Azure AKS API Server Proxying Request to Kubelet

Status
production
Severity
medium
Time window
9m
Author
Elastic
Source
github.com/elastic/detection-rules

Detects a non-system identity using the AKS (Azure Kubernetes Service) API server nodes/proxy subresource to reach a node's Kubelet. Proxying through the API server reaches the Kubelet API to enumerate pods or run commands on nodes, a lateral-movement and privilege-escalation vector (kubeletctl, Peirates). Node, control-plane, and kube-system service account identities that routinely proxy for monitoring are excluded, so remaining matches, including compromised workload service accounts, are surfaced for review.

Known false positives

  • Monitoring and log-collection agents that run outside kube-system (for example a metrics agent in its own namespace) proxy to the Kubelet on every scrape and will match repeatedly. Add targeted exclusions for verified monitoring service accounts and namespaces after review.

MITRE ATT&CK coverage

Telemetry coverage

Rules detecting the same action

These rules filter on the same operation.

Rule body

[metadata]
creation_date = "2026/07/09"
integration = ["azure"]
maturity = "production"
updated_date = "2026/07/09"

[rule]
author = ["Elastic"]
description = """
Detects a non-system identity using the AKS (Azure Kubernetes Service) API server nodes/proxy subresource to reach a
node's Kubelet. Proxying through the API server reaches the Kubelet API to enumerate pods or run commands on nodes, a
lateral-movement and privilege-escalation vector (kubeletctl, Peirates). Node, control-plane, and kube-system service
account identities that routinely proxy for monitoring are excluded, so remaining matches, including compromised
workload service accounts, are surfaced for review.
"""
false_positives = [
    """
    Monitoring and log-collection agents that run outside kube-system (for example a metrics agent in its own namespace)
    proxy to the Kubelet on every scrape and will match repeatedly. Add targeted exclusions for verified monitoring
    service accounts and namespaces after review.
    """,
]
from = "now-9m"
index = ["logs-azure.platformlogs-*"]
language = "kuery"
license = "Elastic License v2"
name = "Azure AKS API Server Proxying Request to Kubelet"
note = """## Triage and analysis

### Investigating Azure AKS API Server Proxying Request to Kubelet

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`. The `nodes/proxy` subresource
tunnels a request through the API server to a node's Kubelet. An identity with this permission can enumerate pods
(`/proxy/pods`, `/proxy/runningpods`) or run commands (`/proxy/run`, `/proxy/exec`) on nodes without direct network
access to the Kubelet port. This rule excludes the node, control-plane, and kube-system service-account identities that
routinely proxy for monitoring, so remaining matches are workload identities or users that should rarely, if ever, reach
the Kubelet.

### Possible investigation steps

- Identify the acting identity in `azure.platformlogs.properties.log.user.username` and whether a workload service
  account or user should reach the Kubelet at all. Compromised pod service accounts (`system:serviceaccount:<ns>:<name>`)
  are the primary vehicle for this technique.
- Inspect the proxied Kubelet endpoint in `azure.platformlogs.properties.log.requestURI`. `/metrics` and `/stats` are
  monitoring; `/pods` and `/runningpods` are reconnaissance; `/run`, `/exec`, `/attach`, and `/portforward` are command
  execution and warrant immediate escalation.
- Evaluate `azure.platformlogs.properties.log.sourceIPs`. This is an array; for an externally operated attack the first
  element is the operator's real client IP, while the trailing entry is the internal API-server/konnectivity hop
  (`172.31.x`). A first entry that is not the cluster's own egress is a strong signal. In-cluster pivots show only
  internal addresses, so absence of an external IP does not clear the event.
- Review the target node in `azure.platformlogs.properties.log.objectRef.name` and correlate with subsequent activity on
  that node's workloads (secret reads, RBAC changes, new pods).

### False positive analysis

- Monitoring and log-collection agents outside kube-system proxy to the Kubelet on every scrape and will match
  repeatedly; add targeted exclusions for verified monitoring service accounts and namespaces.

### Response and remediation

- If unauthorized, revoke the acting identity's tokens and review the RBAC that granted `nodes/proxy`.
- Inspect the target node for command execution, dropped tooling, or credential theft, and rotate credentials reachable
  from affected pods.
- Note that direct Kubelet access on port 10250 bypasses the API server and does not appear in kube-audit; treat a
  confirmed proxy abuse as possible evidence of broader Kubelet access.
- Collect kube-audit and identity artifacts per incident response procedures.
"""
references = [
    "https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/",
    "https://stratus-red-team.cloud/attack-techniques/kubernetes/k8s.privilege-escalation.nodes-proxy/",
    "https://horizon3.ai/attack-research/when-read-only-isnt-k8s-nodes-proxy-get-to-rce/",
    "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/",
    "https://github.com/inguardians/peirates",
]
risk_score = 47
rule_id = "dd43c618-6a5b-465b-8ae4-ce69e34ddac0"
setup = "The Azure Fleet integration collecting AKS diagnostic logs with the `kube-audit` category forwarded through Event Hub into the `azure.platformlogs` data stream is required for this rule."
severity = "medium"
tags = [
    "Domain: Cloud",
    "Domain: Kubernetes",
    "Data Source: Azure",
    "Data Source: Azure Platform Logs",
    "Data Source: Kubernetes",
    "Use Case: Threat Detection",
    "Tactic: Lateral Movement",
    "Tactic: Execution",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "query"

query = '''
data_stream.dataset:azure.platformlogs and
  event.action:"Microsoft.ContainerService/managedClusters/diagnosticLogs/Read" and
  azure.platformlogs.category:"kube-audit" and
  azure.platformlogs.properties.log.objectRef.resource:"nodes" and
  azure.platformlogs.properties.log.objectRef.subresource:"proxy" and
  not azure.platformlogs.properties.log.user.username:(
    system\:node\:* or "aksService" or "hcpService" or "readinessChecker" or
    system\:serviceaccount\:kube-system\:*
  )
'''


[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1210"
name = "Exploitation of Remote Services"
reference = "https://attack.mitre.org/techniques/T1210/"


[rule.threat.tactic]
id = "TA0008"
name = "Lateral Movement"
reference = "https://attack.mitre.org/tactics/TA0008/"
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1609"
name = "Container Administration Command"
reference = "https://attack.mitre.org/techniques/T1609/"


[rule.threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"

[rule.investigation_fields]
field_names = [
    "@timestamp",
    "event.action",
    "azure.platformlogs.category",
    "azure.platformlogs.properties.log.verb",
    "azure.platformlogs.properties.log.user.username",
    "azure.platformlogs.properties.log.sourceIPs",
    "azure.platformlogs.properties.log.requestURI",
    "azure.platformlogs.properties.log.objectRef.resource",
    "azure.platformlogs.properties.log.objectRef.subresource",
    "azure.platformlogs.properties.log.objectRef.name",
]

Stages and Predicates

Stage 1: query

data_stream.dataset:azure.platformlogs and
  event.action:"Microsoft.ContainerService/managedClusters/diagnosticLogs/Read" and
  azure.platformlogs.category:"kube-audit" and
  azure.platformlogs.properties.log.objectRef.resource:"nodes" and
  azure.platformlogs.properties.log.objectRef.subresource:"proxy" and
  not azure.platformlogs.properties.log.user.username:(
    system\:node\:* or "aksService" or "hcpService" or "readinessChecker" or
    system\:serviceaccount\:kube-system\:*
  )

Exclusions

The rule actively suppresses these predicates.

Indicators

These rows show field, operator, and value matches.