forked from elastic/detection-rules
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcredential_access_multi_could_secrets_via_api.toml
More file actions
194 lines (174 loc) · 8.73 KB
/
Copy pathcredential_access_multi_could_secrets_via_api.toml
File metadata and controls
194 lines (174 loc) · 8.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
[metadata]
creation_date = "2025/12/01"
integration = ["aws", "gcp", "azure"]
maturity = "production"
updated_date = "2026/01/12"
[rule]
author = ["Elastic"]
description = """
This rule detects authenticated sessions accessing secret stores across multiple cloud providers from the same source
address within a short period of time. Adversaries with access to compromised credentials or session tokens may attempt
to retrieve secrets from services such as AWS Secrets Manager, Google Secret Manager, or Azure Key Vault in rapid
succession to expand their access or exfiltrate sensitive information.
"""
from = "now-9m"
interval = "5m"
language = "esql"
license = "Elastic License v2"
name = "Multiple Cloud Secrets Accessed by Source Address"
note = """## Triage and analysis
### Multiple Cloud Secrets Accessed by Source Address
This alert identifies a single source IP address accessing secret-management APIs across **multiple cloud providers**
(e.g., AWS Secrets Manager, Google Secret Manager, Azure Key Vault) within a short timeframe.
This behavior is strongly associated with **credential theft, session hijacking, or token replay**, where an adversary
uses stolen authenticated sessions to harvest secrets across cloud environments.
Unexpected cross-cloud secret retrieval is uncommon and typically indicates automation misuse or malicious activity.
### Possible investigation steps
- Validate the principal
- Identify the user, service account, workload identity, or application making the requests.
- Confirm whether this identity is expected to operate across more than one cloud provider.
- Review related activity
- Look for additional alerts involving the same identity, source IP, or token over the last 24–48 hours.
- Identify whether the source IP has been observed performing unusual authentication, privilege escalation,
or reconnaissance.
- Check application or service context
- Determine whether any workload legitimately pulls secrets from multiple cloud providers.
- Review deployment pipelines or integration layers that might legitimately bridge AWS, Azure, and GCP.
- Analyze user agent and invocation patterns
- Compare `user_agent.original` or equivalent fields against expected SDKs or automation tools.
- Suspicious indicators include CLI tools, unknown libraries, browser user agents, or custom scripts.
- Inspect IP reputation and origin
- Determine whether the source IP corresponds to a managed workload (EC2, GCE, Azure VM) or an unexpected host.
- Validate that the associated instance or host is under your control and behaving normally.
- Review IAM permissions and accessed secrets
- Check the policies attached to the identity.
- Verify whether the accessed secrets are sensitive, unused, or unrelated to the identity’s purpose.
- Assess potential compromise scope
- If compromise is suspected, enumerate other assets accessed by the same identity in the last 24 hours.
- Look for lateral movement, privilege escalation, or abnormal API usage.
### False positive analysis
- Validate whether the source IP is associated with a legitimate multi-cloud orchestration tool, automation pipeline,
or shared CI/CD system.
- Confirm that the identity is authorized to access secrets across multiple cloud services.
- If activity is expected, consider adding exceptions that pair account identity, source IP, and expected user agent
to reduce noise.
### Response and remediation
- Initiate incident response** if the activity is unauthorized or suspicious.
- Restrict or disable** the affected credentials or service accounts.
- Rotate all accessed secrets** and review other secrets the identity can access.
- Analyze systems** that may have leaked credentials, such as compromised hosts or exposed tokens.
- Harden identity security:
- Enforce MFA for users where applicable.
- Reduce permissions to least privilege.
- Review trust relationships, workload identities, and cross-cloud integrations.
- Search for persistence mechanisms** such as newly created keys, roles, or service accounts.
- Improve monitoring and audit visibility** by ensuring logging is enabled across all cloud environments.
- Determine root cause** (phishing, malware, token replay, exposed credential, etc.) and close the vector to prevent recurrence.
"""
references = [
"https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html",
"https://docs.cloud.google.com/secret-manager/docs/samples/secretmanager-access-secret-version",
"https://learn.microsoft.com/en-us/azure/key-vault/secrets/about-secrets",
"https://www.wiz.io/blog/shai-hulud-2-0-ongoing-supply-chain-attack",
]
risk_score = 73
rule_id = "472b4944-d810-43cf-83dc-7d080ae1b8dd"
setup = """
This multi-datasource rule relies on additional configurations from each hyperscaler.
- GCP Audit: [Enable DATA_READ for the Secret Manager API service](https://docs.cloud.google.com/logging/docs/audit/configure-data-access)
- Azure: [Enable Diagnostic Logging for the Key Vault Service](https://learn.microsoft.com/en-us/azure/key-vault/general/howto-logging?tabs=azure-cli)
- AWS: Secrets Manager read access is automatically logged by CloudTrail.
"""
severity = "high"
tags = [
"Domain: Cloud",
"Domain: IAM",
"Domain: Storage",
"Data Source: AWS",
"Data Source: Amazon Web Services",
"Data Source: AWS Secrets Manager",
"Data Source: Azure",
"Data Source: Azure Activity Logs",
"Data Source: GCP",
"Data Source: Google Cloud Platform",
"Tactic: Credential Access",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "esql"
query = '''
FROM logs-* METADATA _id, _version, _index
| WHERE
(
/* AWS Secrets Manager */
(event.dataset == "aws.cloudtrail" AND event.provider == "secretsmanager.amazonaws.com" AND event.action == "GetSecretValue") OR
// Azure Key Vault (platform logs)
(event.dataset == "azure.platformlogs" AND event.action IN ("SecretGet", "KeyGet")) or
/* Google Secret Manager */
(event.dataset IN ("googlecloud.audit", "gcp.audit") AND
event.action IN ("google.cloud.secretmanager.v1.SecretManagerService.AccessSecretVersion", "google.cloud.secretmanager.v1.SecretManagerService.GetSecretRequest"))
) AND source.ip IS NOT NULL
// Unified user identity (raw)
| EVAL Esql_priv.user_id =
COALESCE(
client.user.id,
aws.cloudtrail.user_identity.arn,
NULL
)
// Cloud vendor label based on dataset
| EVAL Esql.cloud_vendor = CASE(
event.dataset == "aws.cloudtrail", "aws",
event.dataset == "azure.platformlogs", "azure",
event.dataset IN ("googlecloud.audit","gcp.audit"), "gcp",
"unknown"
)
// Vendor+tenant label, e.g. aws:123456789012, azure:tenant, gcp:project
| EVAL Esql.tenant_label = CASE(
Esql.cloud_vendor == "aws", CONCAT("aws:", cloud.account.id),
Esql.cloud_vendor == "azure", CONCAT("azure:", cloud.account.id),
Esql.cloud_vendor == "gcp", CONCAT("gcp:", cloud.account.id),
NULL
)
| STATS
// Core counts
Esql.events_count = COUNT(*),
Esql.vendor_count_distinct = COUNT_DISTINCT(Esql.cloud_vendor),
// Action & data source context
Esql.event_action_values = VALUES(event.action),
Esql.data_source_values = VALUES(event.dataset),
// Cloud vendor + tenant context
Esql.cloud_vendor_values = VALUES(Esql.cloud_vendor),
Esql.tenant_label_values = VALUES(Esql.tenant_label),
// Hyperscaler-specific IDs
Esql.aws_account_id_values = VALUES(CASE(Esql.cloud_vendor == "aws", cloud.account.id, NULL)),
Esql.azure_tenant_id_values = VALUES(CASE(Esql.cloud_vendor == "azure", cloud.account.id, NULL)),
Esql.gcp_project_id_values = VALUES(CASE(Esql.cloud_vendor == "gcp", cloud.account.id, NULL)),
// Generic cloud metadata
Esql.cloud_region_values = VALUES(cloud.region),
Esql.cloud_service_name_values = VALUES(cloud.service.name),
// Identity (privileged)
Esql_priv.user_values = VALUES(Esql_priv.user_id),
Esql_priv.client_user_id_values = VALUES(client.user.id),
Esql_priv.aws_user_identity_arn_values = VALUES(aws.cloudtrail.user_identity.arn),
// Namespace values
Esql.data_stream_namespace_values = VALUES(data_stream.namespace)
BY source.ip
// Require multi-vendor cred-access from same source IP
| WHERE Esql.vendor_count_distinct >= 2
| SORT Esql.events_count DESC
| KEEP Esql.*, Esql_priv.*, source.ip
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1555"
name = "Credentials from Password Stores"
reference = "https://attack.mitre.org/techniques/T1555/"
[[rule.threat.technique.subtechnique]]
id = "T1555.006"
name = "Cloud Secrets Management Stores"
reference = "https://attack.mitre.org/techniques/T1555/006/"
[rule.threat.tactic]
id = "TA0006"
name = "Credential Access"
reference = "https://attack.mitre.org/tactics/TA0006/"