Kubernetes Secret or ConfigMap Access via Azure Arc Proxy
editKubernetes Secret or ConfigMap Access via Azure Arc Proxy
editDetects when secrets or configmaps are accessed, created, modified, or deleted in a Kubernetes cluster by the Azure Arc AAD proxy service account. When operations are routed through the Azure Arc Cluster Connect proxy, the Kubernetes audit log records the acting user as system:serviceaccount:azure-arc:azure-arc-kube-aad-proxy-sa with the actual caller identity in the impersonatedUser field. This pattern indicates that someone is accessing the cluster through the Azure ARM API rather than directly via kubectl against the API server. While legitimate for Arc-managed workflows, adversaries with stolen service principal credentials can abuse Arc Cluster Connect to read, exfiltrate, or modify secrets and configmaps while appearing as the Arc proxy service account in K8s audit logs.
Rule type: esql
Rule indices: None
Severity: medium
Risk score: 47
Runs every: 9m
Searches indices from: now-5d (Date Math format, see also Additional look-back time)
Maximum alerts per execution: 100
References:
- https://learn.microsoft.com/en-us/azure/azure-arc/kubernetes/cluster-connect
- https://microsoft.github.io/Threat-Matrix-for-Kubernetes/
- https://www.ibm.com/think/x-force/identifying-abusing-azure-arc-for-hybrid-escalation-persistence
- https://cloud.google.com/blog/topics/threat-intelligence/escalating-privileges-azure-kubernetes-services
- https://www.wiz.io/blog/lateral-movement-risks-in-the-cloud-and-how-to-prevent-them-part-3-from-compromis
Tags:
- Data Source: Kubernetes
- Domain: Kubernetes
- Domain: Cloud
- Use Case: Threat Detection
- Tactic: Credential Access
- Tactic: Collection
- Resources: Investigation Guide
Version: 1
Rule authors:
- Elastic
Rule license: Elastic License v2
Investigation guide
editTriage and analysis
Investigating Kubernetes Secret or ConfigMap Access via Azure Arc Proxy
When Kubernetes operations are performed through Azure Arc Cluster Connect, the K8s audit log shows the Arc AAD proxy
service account as the authenticated user, with the actual Azure AD identity in the impersonatedUser field. This
rule detects non-system secret and configmap access — including reads, writes, and deletions — routed through this
proxy path. Read operations (get, list) are particularly important to detect as they represent the most common
adversary action: exfiltrating secrets without leaving obvious modification traces.
Possible investigation steps
-
Check the
kubernetes.audit.impersonatedUser.usernamefield — this contains the Azure AD object ID of the actual caller. Cross-reference with Azure AD to identify the service principal or user. -
Review the
kubernetes.audit.impersonatedUser.extra.oidfield for the Azure AD object ID. -
Examine the namespace — operations in
defaultor application namespaces are more suspicious thanazure-arcorkube-system. -
Check the
kubernetes.audit.objectRef.name— look for suspicious secret/configmap names that don’t match known application resources. -
Correlate with Azure Activity Logs for the same time window to find the
LISTCLUSTERUSERCREDENTIALoperation that initiated the Arc proxy session. - Review Azure Sign-In Logs for the impersonated identity’s authentication source IP and geolocation.
Response and remediation
- If the impersonated identity is not recognized, revoke its Azure AD credentials immediately.
- Remove the ClusterRoleBinding or RoleBinding that grants the identity access to secrets/configmaps.
- Rotate any Kubernetes secrets that may have been read or exfiltrated.
- Review the Arc connection and consider disconnecting it if compromised.
Rule query
editFROM logs-kubernetes.audit_logs-* metadata _id, _version, _index
| WHERE STARTS_WITH(kubernetes.audit.user.username, "system:serviceaccount:azure-arc:")
AND kubernetes.audit.objectRef.resource IN ("secrets", "configmaps")
AND kubernetes.audit.verb IN ("get", "list", "create", "update", "patch", "delete")
AND kubernetes.audit.objectRef.namespace NOT IN ("azure-arc", "azure-arc-release", "kube-system")
AND NOT STARTS_WITH(kubernetes.audit.objectRef.name, "sh.helm.release.v1")
| STATS
Esql.verb_values = VALUES(kubernetes.audit.verb),
Esql.resource_type_values = VALUES(kubernetes.audit.objectRef.resource),
Esql.resource_name_values = VALUES(kubernetes.audit.objectRef.name),
Esql.namespace_values = VALUES(kubernetes.audit.objectRef.namespace),
Esql.acting_user_values = VALUES(kubernetes.audit.user.username),
Esql.user_agent_values = VALUES(kubernetes.audit.userAgent),
Esql.source_ips_values = VALUES(kubernetes.audit.sourceIPs),
Esql.response_code_values = VALUES(kubernetes.audit.responseStatus.code),
Esql.timestamp_first_seen = MIN(@timestamp),
Esql.timestamp_last_seen = MAX(@timestamp),
Esql.event_count = COUNT(*)
BY kubernetes.audit.impersonatedUser.username
| WHERE Esql.timestamp_first_seen >= NOW() - 9 minutes
| KEEP *
Framework: MITRE ATT&CKTM
-
Tactic:
- Name: Credential Access
- ID: TA0006
- Reference URL: https://attack.mitre.org/tactics/TA0006/
-
Technique:
- Name: Unsecured Credentials
- ID: T1552
- Reference URL: https://attack.mitre.org/techniques/T1552/
-
Sub-technique:
- Name: Container API
- ID: T1552.007
- Reference URL: https://attack.mitre.org/techniques/T1552/007/
-
Tactic:
- Name: Collection
- ID: TA0009
- Reference URL: https://attack.mitre.org/tactics/TA0009/
-
Technique:
- Name: Data from Cloud Storage
- ID: T1530
- Reference URL: https://attack.mitre.org/techniques/T1530/