AWS Discovery API Calls via CLI from a Single Resource
Detects when a single AWS resource is running multiple read-only, discovery API calls in a 10-second window. This behavior could indicate an actor attempting to discover the AWS infrastructure using compromised credentials or a compromised instance. Adversaries may use this information to identify potential targets for further exploitation or to gain a better understanding of the target's infrastructure.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2024/11/04"
3integration = ["aws"]
4maturity = "production"
5updated_date = "2025/12/04"
6
7[rule]
8author = ["Elastic"]
9description = """
10Detects when a single AWS resource is running multiple read-only, discovery API calls in a 10-second window. This
11behavior could indicate an actor attempting to discover the AWS infrastructure using compromised credentials or a
12compromised instance. Adversaries may use this information to identify potential targets for further exploitation or to
13gain a better understanding of the target's infrastructure.
14"""
15false_positives = [
16 """
17 Administrators or automated systems may legitimately perform multiple `Describe`, `List`, `Get` and `Generate` API calls in a short
18 time frame. Verify the user identity and the purpose of the API calls to determine if the behavior is expected.
19 """,
20]
21from = "now-6m"
22language = "esql"
23license = "Elastic License v2"
24name = "AWS Discovery API Calls via CLI from a Single Resource"
25note = """## Triage and analysis
26
27> **Disclaimer**:
28> This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.
29
30### Investigating AWS Discovery API Calls via CLI from a Single Resource
31
32This rule detects when a single AWS identity executes more than five unique discovery-related API calls (`Describe*`, `List*`, `Get*`, or `Generate*`) within a 10-second window using the AWS CLI.
33High volumes of diverse “read-only” API calls in such a short period can indicate scripted reconnaissance, often an early phase of compromise after credential exposure or access to a compromised EC2 instance.
34
35#### Possible Investigation Steps
36
37**Identify the actor and session context**
38- **Actor ARN (`aws.cloudtrail.user_identity.arn`)**: Determine which IAM user, role, or service principal performed the actions.
39 - Check whether this identity normally performs enumeration activity or belongs to automation infrastructure.
40- **Identity type (`Esql.aws_cloudtrail_user_identity_arn_type`)**: Validate if the caller is a human IAM user, assumed role, or federated identity. Unusual types (e.g., temporary credentials from an unfamiliar role) may indicate lateral movement.
41- **Access key (`Esql.aws_cloudtrail_user_identity_access_key_id_values`)** – Identify which specific access key or temporary credential was used.
42 - If multiple suspicious keys are found, use AWS IAM console or `aws iam list-access-keys` to determine when they were last used or rotated.
43- **Account (`Esql.cloud_account_id_values`)** – Confirm which AWS account was affected and whether it matches the intended operational context (e.g., production vs. sandbox).
44
45**Assess the API call pattern and intent**
46- **Distinct action count (`Esql.event_action_count_distinct`)**: Note how many unique API calls occurred within each 10-second window. Counts far above normal operational baselines may indicate scripted reconnaissance.
47- **API actions (`Esql.event_action_values`)**: Review which discovery APIs were invoked.
48 - Focus on services such as EC2 (`DescribeInstances`), IAM (`ListRoles`, `ListAccessKeys`), S3 (`ListBuckets`), and KMS (`ListKeys`), which adversaries frequently query to map assets.
49- **Service providers (`Esql.event_provider_values`)**: Identify which AWS services were targeted.
50 - Multi-service enumeration (IAM + EC2 + S3) suggests broad discovery rather than a specific diagnostic task.
51- **Time window (`Esql.time_window_date_trunc`)**: Verify whether activity occurred during normal maintenance windows or outside expected hours.
52
53**Analyze the source and origin**
54- **Source IP (`Esql.source_ip_values`)**: Check the originating IPs to determine whether the calls came from a known internal host, an EC2 instance, or an unfamiliar external network.
55 - Compare with known corporate CIDR ranges, VPC flow logs, or guardrail baselines.
56- **Source organization (`Esql.source_as_organization_name_values`)**: Review the associated ASN or organization.
57 - If the ASN belongs to a commercial ISP or VPN service, investigate possible credential compromise or remote attacker usage.
58
59**Correlate with additional events**
60- Search CloudTrail for the same `aws.cloudtrail.user_identity.arn` or `aws_cloudtrail_user_identity_access_key_id_values` within ±30 minutes.
61 - Look for follow-on actions such as `GetCallerIdentity`, `AssumeRole`, `CreateAccessKey`, or data access (`GetObject`, `CopySnapshot`).
62 - Correlate this enumeration with authentication anomalies or privilege-related findings.
63- Cross-reference `Esql.cloud_account_id_values` with other alerts for lateral or privilege escalation patterns.
64
65### False positive analysis
66
67Legitimate, high-frequency API activity may originate from:
68- **Inventory or compliance automation**: Scripts or tools such as AWS Config, Cloud Custodian, or custom CMDB collection performing periodic Describe/List calls.
69- **Operational monitoring systems**: DevOps pipelines, Terraform, or deployment verifiers enumerating resources.
70- **Security tooling**: Security scanners performing asset discovery across services.
71
72Validate by confirming:
73- Whether the `aws.cloudtrail.user_identity.arn` corresponds to a documented automation or monitoring identity.
74- That the observed `Esql.event_action_values` match known inventory or cost-reporting workflows.
75- Timing alignment with approved maintenance schedules.
76
77### Response and remediation
78
79If the activity is unexpected or originates from unrecognized credentials, follow AWS’s incident-handling guidance:
80
81**1. Contain**
82- Temporarily disable or rotate the access key (`Esql.aws_cloudtrail_user_identity_access_key_id_values`) using IAM.
83- Restrict outbound connectivity for the instance or resource from which the API calls originated.
84
85**2. Investigate**
86- Retrieve full CloudTrail logs for the actor and `Esql.time_window_date_trunc` interval.
87- Identify any subsequent write or privilege-modification actions.
88- Review associated IAM policies for excessive permissions.
89
90**3. Recover and Harden**
91- Rotate credentials, enforce MFA on human users, and tighten IAM role trust policies.
92- Implement AWS Config rules or SCPs to monitor and restrict large-scale enumeration.
93
94**4. Post-Incident Actions**
95- Document the finding and response in your organization’s IR management system.
96- Update detection logic or allow-lists for known benign automation.
97- Validate recovery by confirming no new suspicious discovery bursts occur.
98
99### Additional information
100
101- **AWS Documentation**
102 - [CloudTrail Event Reference](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-event-reference.html)
103 - [AWS Security Incident Response Guide](https://docs.aws.amazon.com/whitepapers/latest/aws-security-incident-response-guide/aws-security-incident-response-guide.pdf)
104- **AWS Playbook Resources**
105 - [AWS Incident Response Playbooks](https://github.com/aws-samples/aws-incident-response-playbooks/tree/c151b0dc091755fffd4d662a8f29e2f6794da52c/playbooks)
106 - [AWS Customer Playbook Framework](https://github.com/aws-samples/aws-customer-playbook-framework)
107
108"""
109references = ["https://stratus-red-team.cloud/attack-techniques/AWS/aws.discovery.ec2-enumerate-from-instance/"]
110risk_score = 21
111rule_id = "74f45152-9aee-11ef-b0a5-f661ea17fbcd"
112severity = "low"
113tags = [
114 "Domain: Cloud",
115 "Data Source: AWS",
116 "Data Source: AWS EC2",
117 "Data Source: AWS IAM",
118 "Data Source: AWS S3",
119 "Data Source: AWS Cloudtrail",
120 "Data Source: AWS RDS",
121 "Data Source: AWS Lambda",
122 "Data Source: AWS STS",
123 "Data Source: AWS KMS",
124 "Data Source: AWS SES",
125 "Data Source: AWS Cloudfront",
126 "Data Source: AWS DynamoDB",
127 "Data Source: AWS Elastic Load Balancing",
128 "Use Case: Threat Detection",
129 "Tactic: Discovery",
130 "Resources: Investigation Guide",
131]
132timestamp_override = "event.ingested"
133type = "esql"
134
135query = '''
136from logs-aws.cloudtrail-* metadata _id, _version, _index
137// create time window buckets of 10 seconds
138| eval Esql.time_window_date_trunc = date_trunc(10 seconds, @timestamp)
139
140| where
141 event.dataset == "aws.cloudtrail"
142 // filter on CloudTrail audit logs for IAM, EC2, S3, etc.
143 and event.provider in (
144 "iam.amazonaws.com",
145 "ec2.amazonaws.com",
146 "s3.amazonaws.com",
147 "rds.amazonaws.com",
148 "lambda.amazonaws.com",
149 "dynamodb.amazonaws.com",
150 "kms.amazonaws.com",
151 "cloudfront.amazonaws.com",
152 "elasticloadbalancing.amazonaws.com",
153 "cloudtrail.amazonaws.com",
154 "sts.amazonaws.com",
155 "ses.amazonaws.com"
156 )
157 // ignore AWS service actions
158 and aws.cloudtrail.user_identity.type != "AWSService"
159 // filter for aws-cli specifically
160 and user_agent.name == "aws-cli"
161 // exclude DescribeCapacityReservations events related to AWS Config
162 and event.action != "DescribeCapacityReservations"
163
164// filter for Describe, Get, List, and Generate API calls
165| where true in (
166 starts_with(event.action, "Describe"),
167 starts_with(event.action, "Get"),
168 starts_with(event.action, "List"),
169 starts_with(event.action, "Generate")
170)
171
172// extract owner, identity type, and actor from the ARN
173| dissect aws.cloudtrail.user_identity.arn "%{}::%{Esql_priv.aws_cloudtrail_user_identity_arn_owner}:%{Esql.aws_cloudtrail_user_identity_arn_type}/%{Esql.aws_cloudtrail_user_identity_arn_roles}"
174
175| where starts_with(Esql.aws_cloudtrail_user_identity_arn_roles, "AWSServiceRoleForConfig") != true
176
177// keep relevant fields (preserving ECS fields and computed time window)
178| keep
179 @timestamp,
180 Esql.time_window_date_trunc,
181 event.action,
182 aws.cloudtrail.user_identity.arn,
183 aws.cloudtrail.user_identity.type,
184 aws.cloudtrail.user_identity.access_key_id,
185 source.ip,
186 cloud.account.id,
187 event.provider,
188 user_agent.name,
189 source.as.organization.name,
190 cloud.region,
191 data_stream.namespace
192
193// count the number of unique API calls per time window and actor
194| stats
195 Esql.event_action_count_distinct = count_distinct(event.action),
196 Esql.event_action_values = VALUES(event.action),
197 Esql.event_timestamp_values = VALUES(@timestamp),
198 Esql.aws_cloudtrail_user_identity_type_values = VALUES(aws.cloudtrail.user_identity.type),
199 Esql.aws_cloudtrail_user_identity_access_key_id_values = VALUES(aws.cloudtrail.user_identity.access_key_id),
200 Esql.source_ip_values = VALUES(source.ip),
201 Esql.cloud_account_id_values = VALUES(cloud.account.id),
202 Esql.event_provider_values = VALUES(event.provider),
203 Esql.user_agent_name_values = VALUES(user_agent.name),
204 Esql.source_as_organization_name_values = VALUES(source.as.organization.name),
205 Esql.cloud_region_values = VALUES(cloud.region),
206 Esql.data_stream_namespace_values = VALUES(data_stream.namespace)
207 by Esql.time_window_date_trunc, aws.cloudtrail.user_identity.arn
208
209// filter for more than 5 unique API calls per 10s window
210| where Esql.event_action_count_distinct > 5
211'''
212
213
214[[rule.threat]]
215framework = "MITRE ATT&CK"
216[[rule.threat.technique]]
217id = "T1580"
218name = "Cloud Infrastructure Discovery"
219reference = "https://attack.mitre.org/techniques/T1580/"
220
221
222[rule.threat.tactic]
223id = "TA0007"
224name = "Discovery"
225reference = "https://attack.mitre.org/tactics/TA0007/"
226
227[rule.investigation_fields]
228field_names = [
229 "Esql.event_action_count_distinct",
230 "Esql.time_window_date_trunc",
231 "aws.cloudtrail.user_identity.arn",
232 "Esql.aws_cloudtrail_user_identity_type_values",
233 "Esql.aws_cloudtrail_user_identity_access_key_id_values",
234 "Esql.source_ip_values",
235 "Esql.source_as_organization_name_values",
236 "Esql.event_provider_values",
237 "Esql.event_action_values",
238 "Esql.cloud_account_id_values",
239 "Esql.cloud_region_values",
240 "Esql.data_stream_namespace_values"
241 ]
Triage and analysis
Disclaimer: This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.
Investigating AWS Discovery API Calls via CLI from a Single Resource
This rule detects when a single AWS identity executes more than five unique discovery-related API calls (Describe*, List*, Get*, or Generate*) within a 10-second window using the AWS CLI.
High volumes of diverse “read-only” API calls in such a short period can indicate scripted reconnaissance, often an early phase of compromise after credential exposure or access to a compromised EC2 instance.
Possible Investigation Steps
Identify the actor and session context
- Actor ARN (
aws.cloudtrail.user_identity.arn): Determine which IAM user, role, or service principal performed the actions.- Check whether this identity normally performs enumeration activity or belongs to automation infrastructure.
- Identity type (
Esql.aws_cloudtrail_user_identity_arn_type): Validate if the caller is a human IAM user, assumed role, or federated identity. Unusual types (e.g., temporary credentials from an unfamiliar role) may indicate lateral movement. - Access key (
Esql.aws_cloudtrail_user_identity_access_key_id_values) – Identify which specific access key or temporary credential was used.- If multiple suspicious keys are found, use AWS IAM console or
aws iam list-access-keysto determine when they were last used or rotated.
- If multiple suspicious keys are found, use AWS IAM console or
- Account (
Esql.cloud_account_id_values) – Confirm which AWS account was affected and whether it matches the intended operational context (e.g., production vs. sandbox).
Assess the API call pattern and intent
- Distinct action count (
Esql.event_action_count_distinct): Note how many unique API calls occurred within each 10-second window. Counts far above normal operational baselines may indicate scripted reconnaissance. - API actions (
Esql.event_action_values): Review which discovery APIs were invoked.- Focus on services such as EC2 (
DescribeInstances), IAM (ListRoles,ListAccessKeys), S3 (ListBuckets), and KMS (ListKeys), which adversaries frequently query to map assets.
- Focus on services such as EC2 (
- Service providers (
Esql.event_provider_values): Identify which AWS services were targeted.- Multi-service enumeration (IAM + EC2 + S3) suggests broad discovery rather than a specific diagnostic task.
- Time window (
Esql.time_window_date_trunc): Verify whether activity occurred during normal maintenance windows or outside expected hours.
Analyze the source and origin
- Source IP (
Esql.source_ip_values): Check the originating IPs to determine whether the calls came from a known internal host, an EC2 instance, or an unfamiliar external network.- Compare with known corporate CIDR ranges, VPC flow logs, or guardrail baselines.
- Source organization (
Esql.source_as_organization_name_values): Review the associated ASN or organization.- If the ASN belongs to a commercial ISP or VPN service, investigate possible credential compromise or remote attacker usage.
Correlate with additional events
- Search CloudTrail for the same
aws.cloudtrail.user_identity.arnoraws_cloudtrail_user_identity_access_key_id_valueswithin ±30 minutes.- Look for follow-on actions such as
GetCallerIdentity,AssumeRole,CreateAccessKey, or data access (GetObject,CopySnapshot). - Correlate this enumeration with authentication anomalies or privilege-related findings.
- Look for follow-on actions such as
- Cross-reference
Esql.cloud_account_id_valueswith other alerts for lateral or privilege escalation patterns.
False positive analysis
Legitimate, high-frequency API activity may originate from:
- Inventory or compliance automation: Scripts or tools such as AWS Config, Cloud Custodian, or custom CMDB collection performing periodic Describe/List calls.
- Operational monitoring systems: DevOps pipelines, Terraform, or deployment verifiers enumerating resources.
- Security tooling: Security scanners performing asset discovery across services.
Validate by confirming:
- Whether the
aws.cloudtrail.user_identity.arncorresponds to a documented automation or monitoring identity. - That the observed
Esql.event_action_valuesmatch known inventory or cost-reporting workflows. - Timing alignment with approved maintenance schedules.
Response and remediation
If the activity is unexpected or originates from unrecognized credentials, follow AWS’s incident-handling guidance:
1. Contain
- Temporarily disable or rotate the access key (
Esql.aws_cloudtrail_user_identity_access_key_id_values) using IAM. - Restrict outbound connectivity for the instance or resource from which the API calls originated.
2. Investigate
- Retrieve full CloudTrail logs for the actor and
Esql.time_window_date_truncinterval. - Identify any subsequent write or privilege-modification actions.
- Review associated IAM policies for excessive permissions.
3. Recover and Harden
- Rotate credentials, enforce MFA on human users, and tighten IAM role trust policies.
- Implement AWS Config rules or SCPs to monitor and restrict large-scale enumeration.
4. Post-Incident Actions
- Document the finding and response in your organization’s IR management system.
- Update detection logic or allow-lists for known benign automation.
- Validate recovery by confirming no new suspicious discovery bursts occur.
Additional information
- AWS Documentation
- AWS Playbook Resources
References
Related rules
- AWS S3 Object Encryption Using External KMS Key
- AWS EC2 Deprecated AMI Discovery
- AWS EC2 LOLBin Execution via SSM SendCommand
- AWS IAM Principal Enumeration via UpdateAssumeRolePolicy
- AWS RDS DB Instance Made Public