Multi-Cloud CLI Token and Credential Access Commands
Correlates process telemetry for shells and major cloud/Kubernetes CLIs when command lines match token or credential material access patterns (GCP, Azure, AWS, GitHub, kubectl, DigitalOcean, OCI). Flags hosts where multiple cloud targets appear within a five-minute window.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2026/04/29"
3integration = ["endpoint", "windows", "system"]
4maturity = "production"
5updated_date = "2026/09/18"
6
7[rule]
8author = ["Elastic"]
9description = """
10Correlates process telemetry for shells and major cloud/Kubernetes CLIs when command lines match token or credential
11material access patterns (GCP, Azure, AWS, GitHub, kubectl, DigitalOcean, OCI). Flags hosts where multiple cloud
12targets appear within a five-minute window.
13"""
14false_positives = [
15 """
16 Automation, CI runners, and platform engineering scripts may legitimately print tokens or dump kubeconfig across
17 providers in one session. Baseline approved identities and runner images before tuning thresholds.
18 """,
19]
20from = "now-6m"
21language = "esql"
22license = "Elastic License v2"
23name = "Multi-Cloud CLI Token and Credential Access Commands"
24note = """## Triage and analysis
25
26### Investigating Multi-Cloud CLI Token and Credential Access Commands
27
28Each result row summarizes activity for one host, user, and five-minute time bucket. Review `Esql.process_command_line_values` for the
29exact invocations and confirm whether the session was interactive, automated, or tied to a known pipeline.
30
31### Possible investigation steps
32
33- Map `Esql.cloud_targets` and `Esql.unique_clouds` to the underlying `process.command_line` values and parent
34 executables.
35- Correlate with authentication, Kubernetes audit, and cloud API logs for misuse of printed tokens.
36- Identify whether the parent chain indicates a remote shell, RMM, or scheduled task.
37
38### Response and remediation
39
40- If unauthorized, isolate the host, invalidate any printed material at the identity provider, and hunt for lateral
41 movement using the same time window as the alert.
42
43**GCP (gcloud / application-default credentials)**
44
45- Sign the user or build identity out of local gcloud sessions on the affected machine (example host session):
46
47 `gcloud auth revoke --all`
48
49- Remove leaked Application Default Credentials on that host (often used by client libraries):
50
51 `gcloud auth application-default revoke`
52
53- If a user OAuth refresh token or service account key was exposed, revoke or rotate it in Google Cloud Console (IAM
54 and admin: delete compromised keys; for end users, revoke OAuth tokens under Security or Workspace admin tools as
55 applicable).
56
57**Azure (`az` / `azd`)**
58
59- Clear cached CLI sessions on the host so new tokens are not silently reusable from disk:
60
61 `az logout`
62
63 `az account clear`
64
65- If `az account get-access-token`, `Get-AzAccessToken`, or `azd auth token` output was captured, treat the bearer as
66 compromised: rotate the underlying secret (for example app registration client secret or federated credential),
67 revoke sessions in Microsoft Entra ID where supported, and enforce re-authentication with Conditional Access.
68
69**GitHub (`gh` / PATs)**
70
71- Remove the GitHub CLI session from the affected profile:
72
73 `gh auth logout`
74
75- If a personal access token or fine-grained token was printed, revoke it under GitHub user or organization settings
76 (Developer settings → Personal access tokens), and rotate any secrets or deploy keys that were readable with that
77 token.
78
79For all providers, prefer provider-console revocation and rotation when a token string left the trust boundary; local
80`logout`/`revoke` alone does not invalidate tokens that were already copied off-host.
81"""
82references = [
83 "https://attack.mitre.org/techniques/T1528/",
84 "https://attack.mitre.org/techniques/T1552/",
85]
86risk_score = 73
87rule_id = "2b9a3b7a-0891-4a89-abbe-dca753c403cd"
88severity = "high"
89tags = [
90 "Domain: Endpoint",
91 "Domain: Cloud",
92 "OS: Windows",
93 "OS: Linux",
94 "OS: macOS",
95 "Use Case: Threat Detection",
96 "Tactic: Credential Access",
97 "Data Source: Elastic Defend",
98 "Data Source: Windows Security Event Logs",
99 "Data Source: Sysmon",
100 "Resources: Investigation Guide",
101 "Noise: Low",
102 "Performance: Normal",
103 "Profile: Recommended",
104 "Threat: Supply Chain",
105 "Rule Type: ES|QL",
106 "Platform: Windows",
107 "Platform: Linux",
108 "Platform: macOS",
109]
110timestamp_override = "event.ingested"
111type = "esql"
112query = '''
113FROM logs-endpoint.events.process-*, logs-system.security-*, logs-windows.sysmon_operational-* METADATA _id, _index, _version
114| WHERE event.category == "process" AND KQL(""" event.type : "start" and not event.action : "fork" """)
115 AND process.command_line IS NOT NULL
116 AND (
117 TO_LOWER(process.name) IN (
118 "cmd.exe", "powershell.exe", "pwsh.exe",
119 "sh", "bash", "zsh", "dash", "fish", "ksh",
120 "gcloud", "gcloud.cmd", "az", "az.cmd", "azd", "azd.exe",
121 "gh", "gh.exe", "aws", "aws.exe",
122 "kubectl", "kubectl.exe",
123 "doctl", "doctl.exe",
124 "oci", "oci.exe"
125 ) OR
126 TO_LOWER(process.parent.name) IN (
127 "cmd.exe", "powershell.exe", "pwsh.exe",
128 "sh", "bash", "zsh", "dash", "fish", "ksh", "bun", "bun.exe",
129 "node", "node.exe", "java", "java.exe"
130 )
131 )
132 AND process.command_line RLIKE """.*(config-helper\s.*--format|auth\s+print-access-token|auth\s+print-identity-token|auth\s+application-default\s+print|get-access-token\s.*--output|Get-AzAccessToken|azd\s+auth\s+token|az\s+account\s+get-access-token|gh\s+auth\s+(token|status)|aws\s+sts\s+(get-session-token|get-caller-identity|assume-role)|aws\s+configure\s+(export-credentials|list)|kubectl\s+config\s+view\s.*--raw|kubectl\s+get\s+secret|doctl\s+auth\s+(list|init)|oci\s+session\s+authenticate|oci\s+iam\s.*token).*"""
133| EVAL cloud_target = CASE(
134 process.command_line RLIKE ".*(gcloud|config-helper|print-access-token|print-identity-token).*", "GCP",
135 process.command_line RLIKE ".*(azd auth|az account|Get-AzAccessToken).*", "AZURE",
136 process.command_line RLIKE ".*(aws sts|aws configure).*", "AWS",
137 process.command_line RLIKE ".*(gh auth).*", "GITHUB",
138 process.command_line RLIKE ".*(kubectl config|kubectl get secret).*", "KUBERNETES",
139 process.command_line RLIKE ".*(doctl).*", "DIGITALOCEAN",
140 process.command_line RLIKE ".*(oci session|oci iam).*", "ORACLE"
141 )
142| WHERE cloud_target IS NOT NULL // drop unclassified events before aggregation
143| STATS
144 Esql.cloud_targets = VALUES(cloud_target),
145 Esql.unique_clouds = COUNT_DISTINCT(cloud_target),
146 Esql.process_command_line_values = VALUES(process.command_line),
147 Esql.process_parent_executable_values = VALUES(process.parent.executable),
148 Esql.first_seen = MIN(@timestamp),
149 Esql.last_seen = MAX(@timestamp),
150 Esql.event_count = COUNT(*)
151 BY host.name, host.id, user.name
152| WHERE Esql.unique_clouds >= 2
153| KEEP Esql.*, user.name, host.name, host.id
154'''
155
156[[rule.threat]]
157framework = "MITRE ATT&CK"
158
159[[rule.threat.technique]]
160id = "T1528"
161name = "Steal Application Access Token"
162reference = "https://attack.mitre.org/techniques/T1528/"
163
164[[rule.threat.technique]]
165id = "T1552"
166name = "Unsecured Credentials"
167reference = "https://attack.mitre.org/techniques/T1552/"
168
169[[rule.threat.technique.subtechnique]]
170id = "T1552.001"
171name = "Credentials In Files"
172reference = "https://attack.mitre.org/techniques/T1552/001/"
173
174[rule.threat.tactic]
175id = "TA0006"
176name = "Credential Access"
177reference = "https://attack.mitre.org/tactics/TA0006/"
Triage and analysis
Investigating Multi-Cloud CLI Token and Credential Access Commands
Each result row summarizes activity for one host, user, and five-minute time bucket. Review Esql.process_command_line_values for the
exact invocations and confirm whether the session was interactive, automated, or tied to a known pipeline.
Possible investigation steps
- Map
Esql.cloud_targetsandEsql.unique_cloudsto the underlyingprocess.command_linevalues and parent executables. - Correlate with authentication, Kubernetes audit, and cloud API logs for misuse of printed tokens.
- Identify whether the parent chain indicates a remote shell, RMM, or scheduled task.
Response and remediation
- If unauthorized, isolate the host, invalidate any printed material at the identity provider, and hunt for lateral movement using the same time window as the alert.
GCP (gcloud / application-default credentials)
-
Sign the user or build identity out of local gcloud sessions on the affected machine (example host session):
gcloud auth revoke --all -
Remove leaked Application Default Credentials on that host (often used by client libraries):
gcloud auth application-default revoke -
If a user OAuth refresh token or service account key was exposed, revoke or rotate it in Google Cloud Console (IAM and admin: delete compromised keys; for end users, revoke OAuth tokens under Security or Workspace admin tools as applicable).
Azure (az / azd)
-
Clear cached CLI sessions on the host so new tokens are not silently reusable from disk:
az logoutaz account clear -
If
az account get-access-token,Get-AzAccessToken, orazd auth tokenoutput was captured, treat the bearer as compromised: rotate the underlying secret (for example app registration client secret or federated credential), revoke sessions in Microsoft Entra ID where supported, and enforce re-authentication with Conditional Access.
GitHub (gh / PATs)
-
Remove the GitHub CLI session from the affected profile:
gh auth logout -
If a personal access token or fine-grained token was printed, revoke it under GitHub user or organization settings (Developer settings → Personal access tokens), and rotate any secrets or deploy keys that were readable with that token.
For all providers, prefer provider-console revocation and rotation when a token string left the trust boundary; local
logout/revoke alone does not invalidate tokens that were already copied off-host.
References
Related rules
- Remote GitHub Actions Runner Registration
- Curl or Wget Spawned via Node.js
- Suspicious Instance Metadata Service (IMDS) API Command Line Execution
- Suspicious Instance Metadata Service (IMDS) API Request
- AWS SSM `SendCommand` with Run Shell Command Parameters