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.arn and aws.cloudtrail.user_identity.type. Confirm whether this identity is expected to read instance user data at fleet scale.
  • Review Esql.count_distinct_instance_id and Esql.aws_request_parameters_values. Extract the instanceId values and check whether the instances belong to sensitive workloads.
  • Review source.ip, source.as.organization.name, and Esql.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-*), and AWSReservedSSO_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:DescribeInstanceAttribute to principals that need it.

References

Related rules

to-top