AWS EC2 Bulk User Data Enumeration
Identifies when the same AWS principal, from the same source IP, successfully calls EC2 "DescribeInstanceAttribute" for the "userData" attribute against more than 20 distinct instances within a 10-minute lookback. Instance user data often contains bootstrap scripts and hardcoded credentials, so retrieving it across many instances in a short window can indicate reconnaissance or credential harvesting. Known CSPM roles, AWS service invocations, and Terraform calls from major cloud and carrier networks are excluded.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2026/11/01"
3integration = ["aws"]
4maturity = "production"
5updated_date = "2026/11/01"
6
7[rule]
8author = ["Elastic"]
9description = """
10Identifies when the same AWS principal, from the same source IP, successfully calls EC2
11"DescribeInstanceAttribute" for the "userData" attribute against more than 20 distinct instances within a 10-minute
12lookback. Instance user data often contains bootstrap scripts and hardcoded credentials, so retrieving it across many
13instances in a short window can indicate reconnaissance or credential harvesting. Known CSPM roles, AWS service
14invocations, and Terraform calls from major cloud and carrier networks are excluded.
15"""
16false_positives = [
17 """
18 Inventory jobs, configuration management, and security scanners that are not in the exclusion list may read
19 `userData` across a large fleet. Confirm the principal ARN, source IP, ASN, and user agent against approved
20 automation before treating the activity as malicious.
21 """,
22 """
23 Terraform running from an ASN other than Amazon, Google, Microsoft, Verizon, or AT&T is still in scope. A
24 large apply or refresh can exceed 20 instances.
25 """,
26]
27from = "now-10m"
28language = "esql"
29license = "Elastic License v2"
30name = "AWS EC2 Bulk User Data Enumeration"
31note = """## Triage and analysis
32
33### Investigating AWS EC2 Bulk User Data Enumeration
34
35EC2 `userData` is returned by `DescribeInstanceAttribute` when `attribute` is `userData`. It is frequently used for
36bootstrap scripts and sometimes contains credentials or tokens. This rule alerts when one principal
37(`aws.cloudtrail.user_identity.arn`), identity type, source IP, and source ASN reads that attribute for more than 20
38distinct `aws.cloudtrail.request_parameters` values in the 10-minute lookback. For this API those values correspond to
39distinct instance requests.
40
41### Possible investigation steps
42
43- Review `aws.cloudtrail.user_identity.arn` and `aws.cloudtrail.user_identity.type`. Confirm whether this identity is
44 expected to read instance user data at fleet scale.
45- Review `Esql.count_distinct_instance_id` and `Esql.aws_request_parameters_values`. Extract the `instanceId` values and
46 check whether the instances belong to sensitive workloads.
47- Review `source.ip`, `source.as.organization.name`, and `Esql.user_agent_values`. Unexpected ASNs or clients such as
48 the AWS CLI or an SDK from an unfamiliar network are higher priority than a known automation host.
49- Search CloudTrail for the same principal and source IP in the surrounding hour for `ModifyInstanceAttribute`,
50 `RunInstances`, `GetPasswordData`, `AssumeRole`, and IAM changes.
51- If the instances are still available, inspect their current user data for secrets. Prefer AWS Secrets Manager or
52 Parameter Store over credentials stored in user data.
53
54### False positive analysis
55
56- Approved CSPM and inventory tools. This rule already excludes principal names matching CrowdStrike CSPM, Orca
57 Security, Aikido Security, Stream Security (`streamsec-*`), and `AWSReservedSSO_Poweruser`.
58- Calls invoked by AWS Internal, CloudFormation, AI DevOps, EMR, or AIOps.
59- Terraform user agents whose source ASN is Amazon, Google, Microsoft, Verizon, or AT&T.
60- Add further exceptions by principal ARN or user agent when the behavior is documented and recurring.
61
62### Response and remediation
63
64- If the activity is not authorized, revoke the role session or disable the access key and restrict the source IP.
65- Rotate any credentials found in the retrieved user data and remove secrets from instance user data.
66- Limit `ec2:DescribeInstanceAttribute` to principals that need it.
67"""
68references = [
69 "https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeInstanceAttribute.html",
70 "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html",
71 "https://hackingthe.cloud/aws/exploitation/local_ec2_priv_esc_through_user_data",
72]
73risk_score = 73
74rule_id = "7f6bc52c-fb52-46b5-8081-b78db15af501"
75setup = """## Setup
76
77The AWS integration must collect CloudTrail management events into `logs-aws.cloudtrail-*`.
78`DescribeInstanceAttribute` is a management event logged by default. `source.ip` and
79`source.as.organization.name` must be populated, because events missing either field are excluded.
80"""
81severity = "high"
82tags = [
83 "Domain: Cloud",
84 "Data Source: AWS",
85 "Data Source: Amazon Web Services",
86 "Data Source: AWS CloudTrail",
87 "Platform: AWS",
88 "Service: AWS EC2",
89 "Use Case: Threat Detection",
90 "Tactic: Discovery",
91 "Tactic: Credential Access",
92 "Resources: Investigation Guide",
93 "Rule Type: ES|QL",
94]
95timestamp_override = "event.ingested"
96type = "esql"
97
98query = '''
99from logs-aws.cloudtrail-*
100| where KQL("""event.provider: "ec2.amazonaws.com" and event.action: "DescribeInstanceAttribute" and event.outcome: "success" and aws.cloudtrail.flattened.request_parameters.attribute: "userData" and source.ip: * and source.as.organization.name: * and not user.name: (*CrowdStrikeCSPMReader* or *OrcaSecurityRole* or *AikidoSecurityRole* or *streamsec-*) and not aws.cloudtrail.user_identity.invoked_by: ("AWS Internal" or "cloudformation.amazonaws.com" or "aidevops.amazonaws.com" or "elasticmapreduce.amazonaws.com" or "aiops.amazonaws.com")""")
101 and not (
102 user_agent.original like "*Terraform*"
103 and source.as.organization.name in (
104 "Amazon.com, Inc.",
105 "Google LLC",
106 "Microsoft Corporation",
107 "Verizon Business",
108 "AT&T Enterprises, LLC"
109 )
110 )
111| grok aws.cloudtrail.request_parameters """instanceId=(?<Esql.instance_id>[^,}\]]+)"""
112| where Esql.instance_id is not null
113| stats
114 Esql.count_distinct_instance_id = count_distinct(Esql.instance_id),
115 Esql.aws_request_parameters_values = values(aws.cloudtrail.request_parameters),
116 Esql.user_agent_values = values(user_agent.original)
117 by
118 data_stream.namespace,
119 aws.cloudtrail.user_identity.arn,
120 aws.cloudtrail.user_identity.type,
121 source.as.organization.name,
122 source.ip,
123 source.`as`.number
124| where Esql.count_distinct_instance_id > 20
125| keep
126 Esql.count_distinct_instance_id,
127 data_stream.namespace,
128 aws.cloudtrail.user_identity.arn,
129 aws.cloudtrail.user_identity.type,
130 source.ip,
131 source.`as`.number,
132 source.as.organization.name,
133 Esql.aws_request_parameters_values,
134 Esql.user_agent_values
135'''
136
137
138[[rule.threat]]
139framework = "MITRE ATT&CK"
140[[rule.threat.technique]]
141id = "T1580"
142name = "Cloud Infrastructure Discovery"
143reference = "https://attack.mitre.org/techniques/T1580/"
144
145
146[rule.threat.tactic]
147id = "TA0007"
148name = "Discovery"
149reference = "https://attack.mitre.org/tactics/TA0007/"
150[[rule.threat]]
151framework = "MITRE ATT&CK"
152[[rule.threat.technique]]
153id = "T1552"
154name = "Unsecured Credentials"
155reference = "https://attack.mitre.org/techniques/T1552/"
156[[rule.threat.technique.subtechnique]]
157id = "T1552.005"
158name = "Cloud Instance Metadata API"
159reference = "https://attack.mitre.org/techniques/T1552/005/"
160
161
162
163[rule.threat.tactic]
164id = "TA0006"
165name = "Credential Access"
166reference = "https://attack.mitre.org/tactics/TA0006/"
167
168[rule.investigation_fields]
169field_names = [
170 "Esql.count_distinct_instance_id",
171 "aws.cloudtrail.user_identity.arn",
172 "aws.cloudtrail.user_identity.type",
173 "source.ip",
174 "source.`as`.number",
175 "source.as.organization.name",
176 "Esql.aws_request_parameters_values",
177 "Esql.user_agent_values",
178 "data_stream.namespace",
179]
Triage and analysis
Investigating AWS EC2 Bulk User Data Enumeration
EC2 userData is returned by DescribeInstanceAttribute when attribute is userData. It is frequently used for
bootstrap scripts and sometimes contains credentials or tokens. This rule alerts when one principal
(aws.cloudtrail.user_identity.arn), identity type, source IP, and source ASN reads that attribute for more than 20
distinct aws.cloudtrail.request_parameters values in the 10-minute lookback. For this API those values correspond to
distinct instance requests.
Possible investigation steps
- Review
aws.cloudtrail.user_identity.arnandaws.cloudtrail.user_identity.type. Confirm whether this identity is expected to read instance user data at fleet scale. - Review
Esql.count_distinct_instance_idandEsql.aws_request_parameters_values. Extract theinstanceIdvalues and check whether the instances belong to sensitive workloads. - Review
source.ip,source.as.organization.name, andEsql.user_agent_values. Unexpected ASNs or clients such as the AWS CLI or an SDK from an unfamiliar network are higher priority than a known automation host. - Search CloudTrail for the same principal and source IP in the surrounding hour for
ModifyInstanceAttribute,RunInstances,GetPasswordData,AssumeRole, and IAM changes. - If the instances are still available, inspect their current user data for secrets. Prefer AWS Secrets Manager or Parameter Store over credentials stored in user data.
False positive analysis
- Approved CSPM and inventory tools. This rule already excludes principal names matching CrowdStrike CSPM, Orca
Security, Aikido Security, Stream Security (
streamsec-*), andAWSReservedSSO_Poweruser. - Calls invoked by AWS Internal, CloudFormation, AI DevOps, EMR, or AIOps.
- Terraform user agents whose source ASN is Amazon, Google, Microsoft, Verizon, or AT&T.
- Add further exceptions by principal ARN or user agent when the behavior is documented and recurring.
Response and remediation
- If the activity is not authorized, revoke the role session or disable the access key and restrict the source IP.
- Rotate any credentials found in the retrieved user data and remove secrets from instance user data.
- Limit
ec2:DescribeInstanceAttributeto principals that need it.
References
Related rules
- AWS Lateral Movement from Kubernetes SA via AssumeRoleWithWebIdentity
- AWS Bedrock Model Invocation From High Number of Countries
- AWS Bedrock Model Invocation Impossible Travel
- AWS EC2 CreateKeyPair by New Principal from Non-Cloud AS Organization
- AWS EC2 LOLBin Execution via SSM SendCommand