diff --git a/rules/integrations/aws/discovery_ec2_multi_region_describe_instances.toml b/rules/integrations/aws/discovery_ec2_multi_region_describe_instances.toml deleted file mode 100644 index cdf6c4d7929..00000000000 --- a/rules/integrations/aws/discovery_ec2_multi_region_describe_instances.toml +++ /dev/null @@ -1,135 +0,0 @@ -[metadata] -creation_date = "2024/08/26" -integration = ["aws"] -maturity = "production" -updated_date = "2025/07/16" - -[rule] -author = ["Elastic"] -description = """ -Identifies when a single AWS resource is making `DescribeInstances` API calls in more than 10 regions within a 30-second -window. This could indicate a potential threat actor attempting to discover the AWS infrastructure across multiple -regions 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. -""" -false_positives = [ - """ - Legitimate use of the `DescribeInstances` API call by an AWS resource that requires information about instances in - multiple regions. - """, - "Scheduled tasks or scripts that require information about instances in multiple regions.", -] -from = "now-9m" -language = "esql" -license = "Elastic License v2" -name = "AWS EC2 Multi-Region DescribeInstances API Calls" -note = """## Triage and analysis - -### Investigating AWS EC2 Multi-Region DescribeInstances API Calls - -This rule detects instances where a single AWS resource makes `DescribeInstances` API calls in over 10 regions within a 30-second window. This could indicate an adversary using compromised credentials or an exploited resource to enumerate AWS infrastructure across multiple regions. Attackers often leverage multi-region enumeration to assess the overall cloud environment and find potential targets for further exploitation. - -#### Possible Investigation Steps - -- **Identify the Resource and Actor**: - - **Actor ARN**: Check `aws.cloudtrail.user_identity.arn` to determine the exact identity performing the enumeration. Validate if the user is expected to perform region-wide `DescribeInstances` actions across multiple regions or if it seems unusual. - - **Account and Role Details**: Examine `cloud.account.id` and `aws.cloudtrail.user_identity.session_context.session_issuer` for information about the AWS account and specific role associated with the action. - -- **Analyze API Call Patterns**: - - **Frequency and Scope**: Review `cloud.region` field and confirm if this specific resource commonly performs `DescribeInstances` calls across multiple regions. - - **Time Window Context**: Compare the timing of the API calls within the `target_time_window` to determine if this burst pattern aligns with expected system usage or is potentially malicious. - -- **Check User Agent and Tooling**: - - **Source and User Agent**: Verify `user_agent.original` to determine if the request was made through expected tooling (e.g., AWS CLI or SDK) or a third-party tool that might indicate non-standard access. - - **Source IP Address**: Look into `source.address` to identify the origin of the calls. Unusual IP addresses, especially those outside expected ranges, may indicate compromised access. - -- **Evaluate for Potential Reconnaissance Behavior**: - - **Account and Region Enumeration**: Adversaries may use region-wide `DescribeInstances` requests to discover resources within an account across different regions. Confirm if this access aligns with operational practices or represents excessive access. - - **Permissions and Roles**: Investigate the permissions associated with the user role. Excessive permissions on a compromised role may allow broader enumeration, which should be restricted. - -- **Review Related CloudTrail Events**: - - **Additional Describe or List Actions**: Identify any associated `Describe` or `List` API calls that may indicate further enumeration of other AWS services within the same timeframe. - - **Potential Preceding Events**: Look for preceding login or access events from the same actor, as these may indicate potential credential compromise or unauthorized escalation of privileges. - -### False Positive Analysis - -- **Expected Enumeration**: Certain administrative or automation scripts may conduct broad `DescribeInstances` API calls for inventory purposes. Review usage patterns or consult relevant teams to validate the purpose. -- **Automated Cloud Management**: Some automated services may perform regional checks for compliance or backup operations. If this rule is triggered repeatedly by a known service, consider whitelisting or tuning accordingly. - -### Response and Remediation - -- **Review IAM Policies and Role Permissions**: Limit the permissions of roles associated with this resource, restricting unnecessary multi-region enumeration access. -- **Enforce Least Privilege Access**: Ensure that permissions for DescribeInstances are tightly controlled and restricted to specific roles or accounts that require multi-region access. -- **Increase Monitoring and Alerts**: Set up additional monitoring on this role or account for further signs of unauthorized activity or lateral movement attempts. -- **Access Review**: Conduct a review of users and entities with `DescribeInstances` permissions, especially for multi-region capabilities, and ensure these permissions are necessary for their functions. - -### Additional Information - -For further information on AWS `DescribeInstances` permissions and best practices, refer to the [AWS DescribeInstances API documentation](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeInstances.html). -""" -references = [ - "https://www.sentinelone.com/labs/exploring-fbot-python-based-malware-targeting-cloud-and-payment-services/", - "https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeInstances.html", -] -risk_score = 21 -rule_id = "393ef120-63d1-11ef-8e38-f661ea17fbce" -severity = "low" -tags = [ - "Domain: Cloud", - "Data Source: AWS", - "Data Source: AWS EC2", - "Resources: Investigation Guide", - "Use Case: Threat Detection", - "Tactic: Discovery", -] -timestamp_override = "event.ingested" -type = "esql" - -query = ''' -from logs-aws.cloudtrail-* - -// filter for DescribeInstances API calls -| where event.dataset == "aws.cloudtrail" - and event.provider == "ec2.amazonaws.com" - and event.action == "DescribeInstances" - -// truncate the timestamp to a 30-second window -| eval Esql.time_window_date_trunc = date_trunc(30 seconds, @timestamp) - -// keep only the relevant raw fields -| keep Esql.time_window_date_trunc, aws.cloudtrail.user_identity.arn, cloud.region - -// count the number of unique regions and total API calls within the 30-second window -| stats - Esql.cloud_region_count_distinct = count_distinct(cloud.region), - Esql.event_count = count(*) - by Esql.time_window_date_trunc, aws.cloudtrail.user_identity.arn - -// filter for resources making DescribeInstances API calls in more than 10 regions within the 30-second window -| where Esql.cloud_region_count_distinct >= 10 and Esql.event_count >= 10 - -// sort the results by time window in descending order -| sort Esql.time_window_date_trunc desc -''' - -[rule.investigation_fields] -field_names = [ - "aws.cloudtrail.user_identity.arn", - "target_time_window", - "region_count", - "window_count" -] - -[[rule.threat]] -framework = "MITRE ATT&CK" -[[rule.threat.technique]] -id = "T1580" -name = "Cloud Infrastructure Discovery" -reference = "https://attack.mitre.org/techniques/T1580/" - - -[rule.threat.tactic] -id = "TA0007" -name = "Discovery" -reference = "https://attack.mitre.org/tactics/TA0007/" - diff --git a/rules/integrations/aws/discovery_ec2_multiple_discovery_api_calls_via_cli.toml b/rules/integrations/aws/discovery_ec2_multiple_discovery_api_calls_via_cli.toml deleted file mode 100644 index 8aeac9ba3d7..00000000000 --- a/rules/integrations/aws/discovery_ec2_multiple_discovery_api_calls_via_cli.toml +++ /dev/null @@ -1,155 +0,0 @@ -[metadata] -creation_date = "2024/11/04" -integration = ["aws"] -maturity = "production" -updated_date = "2025/07/16" - -[rule] -author = ["Elastic"] -description = """ -Detects when a single AWS resource is running multiple `Describe` and `List` 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. -""" -false_positives = [ - """ - Administrators or automated systems may legitimately perform multiple `Describe` and `List` API calls in a short - time frame. Verify the user identity and the purpose of the API calls to determine if the behavior is expected. - """, -] -from = "now-9m" -language = "esql" -license = "Elastic License v2" -name = "AWS Discovery API Calls via CLI from a Single Resource" -note = """## Triage and analysis - -### Investigating AWS Discovery API Calls via CLI from a Single Resource - -This rule detects multiple discovery-related API calls (`Describe`, `List`, or `Get` actions) within a short time window (30 seconds) from a single AWS resource. High volumes of such calls may indicate attempts to enumerate AWS infrastructure for reconnaissance purposes, which is often a tactic used by adversaries with compromised credentials or unauthorized access. - -#### Possible Investigation Steps - -- **Identify the Actor and Resource**: - - **User Identity and Resource**: Examine `aws.cloudtrail.user_identity.arn` to identify the actor making the discovery requests. Verify the user or resource associated with these actions to ensure they are recognized and expected. - - **User Agent and Tooling**: Check `user_agent.name` to confirm whether the `aws-cli` tool was used for these requests. Use of the CLI in an atypical context might indicate unauthorized or automated access. - -- **Evaluate the Context and Scope of API Calls**: - - **API Action Types**: Look into the specific actions under `event.action` for API calls like `Describe*`, `List*`, or `Get*`. Note if these calls are targeting sensitive services, such as `EC2`, `IAM`, or `S3`, which may suggest an attempt to identify high-value assets. - - **Time Pattern Analysis**: Review the `time_window` and `unique_api_count` to assess whether the frequency of these calls is consistent with normal patterns for this resource or user. - -- **Analyze Potential Compromise Indicators**: - - **Identity Type**: Review `aws.cloudtrail.user_identity.type` to determine if the calls originated from an assumed role, a root user, or a service role. Unusual identity types for discovery operations may suggest misuse or compromise. - - **Source IP and Geographic Location**: Examine the `source.ip` and `source.geo` fields to identify any unusual IP addresses or locations associated with the activity, which may help confirm or rule out external access. - -- **Examine Related CloudTrail Events**: - - **Pivot for Related Events**: Identify any additional IAM or CloudTrail events tied to the same actor ARN. Activities such as `AssumeRole`, `GetSessionToken`, or `CreateAccessKey` in proximity to these discovery calls may signal an attempt to escalate privileges. - - **Look for Anomalous Patterns**: Determine if this actor or resource has performed similar discovery actions previously, or if these actions coincide with other alerts related to credential use or privilege escalation. - -### False Positive Analysis - -- **Expected Discovery Activity**: Regular discovery or enumeration API calls may be conducted by security, automation, or monitoring scripts to maintain an inventory of resources. Validate if this activity aligns with known automation or inventory tasks. -- **Routine Admin or Automated Access**: If specific roles or resources, such as automation tools or monitoring services, regularly trigger this rule, consider adding exceptions for these known, benign users to reduce false positives. - -### Response and Remediation - -- **Confirm Authorized Access**: If the discovery activity appears unauthorized, consider immediate steps to restrict the user or resource’s permissions. -- **Review and Remove Unauthorized API Calls**: If the actor is not authorized to perform discovery actions, investigate and potentially disable their permissions or access keys to prevent further misuse. -- **Enhance Monitoring for Discovery Patterns**: Consider additional logging or alerting for high-frequency discovery API calls, especially if triggered from new or unrecognized resources. -- **Policy Review and Updates**: Review IAM policies associated with the actor, ensuring restrictive permissions and MFA enforcement where possible to prevent unauthorized discovery. - -### Additional Information - -For further guidance on AWS infrastructure discovery and best practices, refer to [AWS CloudTrail documentation](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-event-reference.html) and MITRE ATT&CK’s [Cloud Infrastructure Discovery](https://attack.mitre.org/techniques/T1580/). -""" -references = ["https://stratus-red-team.cloud/attack-techniques/AWS/aws.discovery.ec2-enumerate-from-instance/"] -risk_score = 21 -rule_id = "74f45152-9aee-11ef-b0a5-f661ea17fbcd" -severity = "low" -tags = [ - "Domain: Cloud", - "Data Source: AWS", - "Data Source: AWS EC2", - "Data Source: AWS IAM", - "Data Source: AWS S3", - "Use Case: Threat Detection", - "Tactic: Discovery", - "Resources: Investigation Guide", -] -timestamp_override = "event.ingested" -type = "esql" - -query = ''' -from logs-aws.cloudtrail* - -// create time window buckets of 10 seconds -| eval Esql.time_window_date_trunc = date_trunc(10 seconds, @timestamp) -| where - event.dataset == "aws.cloudtrail" - - // filter on CloudTrail audit logs for IAM, EC2, S3, etc. - and event.provider in ( - "iam.amazonaws.com", - "ec2.amazonaws.com", - "s3.amazonaws.com", - "rds.amazonaws.com", - "lambda.amazonaws.com", - "dynamodb.amazonaws.com", - "kms.amazonaws.com", - "cloudfront.amazonaws.com", - "elasticloadbalancing.amazonaws.com" - ) - - // ignore AWS service actions - and aws.cloudtrail.user_identity.type != "AWSService" - - // filter for aws-cli specifically - and user_agent.name == "aws-cli" - - // exclude DescribeCapacityReservations events related to AWS Config - and not event.action in ("DescribeCapacityReservations") - -// filter for Describe, Get, List, and Generate API calls -| where true in ( - starts_with(event.action, "Describe"), - starts_with(event.action, "Get"), - starts_with(event.action, "List"), - starts_with(event.action, "Generate") -) - -// extract owner, identity type, and actor from the ARN -| 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}" -| where starts_with(Esql.aws_cloudtrail_user_identity_arn_roles, "AWSServiceRoleForConfig") != true - -// keep relevant fields (preserving ECS fields and computed time window) -| keep @timestamp, Esql.time_window_date_trunc, event.action, aws.cloudtrail.user_identity.arn - -// count the number of unique API calls per time window and actor -| stats - Esql.event_action_count_distinct = count_distinct(event.action) - by Esql.time_window_date_trunc, aws.cloudtrail.user_identity.arn - -// filter for more than 5 unique API calls per 10s window -| where Esql.event_action_count_distinct > 5 - -// sort the results by the number of unique API calls in descending order -| sort Esql.event_action_count_distinct desc -''' - - -[[rule.threat]] -framework = "MITRE ATT&CK" -[[rule.threat.technique]] -id = "T1580" -name = "Cloud Infrastructure Discovery" -reference = "https://attack.mitre.org/techniques/T1580/" - - -[rule.threat.tactic] -id = "TA0007" -name = "Discovery" -reference = "https://attack.mitre.org/tactics/TA0007/" - -[rule.investigation_fields] -field_names = ["time_window", "aws.cloudtrail.user_identity.arn", "unique_api_count"] - diff --git a/rules/integrations/aws/discovery_multiple_discovery_api_calls_via_cli.toml b/rules/integrations/aws/discovery_multiple_discovery_api_calls_via_cli.toml new file mode 100644 index 00000000000..d74659d2749 --- /dev/null +++ b/rules/integrations/aws/discovery_multiple_discovery_api_calls_via_cli.toml @@ -0,0 +1,221 @@ +[metadata] +creation_date = "2024/11/04" +integration = ["aws"] +maturity = "production" +updated_date = "2025/10/21" + +[rule] +author = ["Elastic"] +description = """ +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. +""" +false_positives = [ + """ + Administrators or automated systems may legitimately perform multiple `Describe`, `List`, `Get` and `Generate` API calls in a short + time frame. Verify the user identity and the purpose of the API calls to determine if the behavior is expected. + """, +] +from = "now-6m" +language = "esql" +license = "Elastic License v2" +name = "AWS Discovery API Calls via CLI from a Single Resource" +note = """## 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-keys` to determine when they were last used or rotated. +- **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. +- **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.arn` or `aws_cloudtrail_user_identity_access_key_id_values` within ±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. +- Cross-reference `Esql.cloud_account_id_values` with 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.arn` corresponds to a documented automation or monitoring identity. +- That the observed `Esql.event_action_values` match 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_trunc` interval. +- 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** + - [CloudTrail Event Reference](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-event-reference.html) + - [AWS Security Incident Response Guide](https://docs.aws.amazon.com/whitepapers/latest/aws-security-incident-response-guide/aws-security-incident-response-guide.pdf) +- **AWS Playbook Resources** + - [AWS Incident Response Playbooks](https://github.com/aws-samples/aws-incident-response-playbooks/tree/c151b0dc091755fffd4d662a8f29e2f6794da52c/playbooks) + - [AWS Customer Playbook Framework](https://github.com/aws-samples/aws-customer-playbook-framework) + +""" +references = ["https://stratus-red-team.cloud/attack-techniques/AWS/aws.discovery.ec2-enumerate-from-instance/"] +risk_score = 21 +rule_id = "74f45152-9aee-11ef-b0a5-f661ea17fbcd" +severity = "low" +tags = [ + "Domain: Cloud", + "Data Source: AWS", + "Data Source: AWS EC2", + "Data Source: AWS IAM", + "Data Source: AWS S3", + "Use Case: Threat Detection", + "Tactic: Discovery", + "Resources: Investigation Guide", +] +timestamp_override = "event.ingested" +type = "esql" + +query = ''' +from logs-aws.cloudtrail* +// create time window buckets of 10 seconds +| eval Esql.time_window_date_trunc = date_trunc(10 seconds, @timestamp) + +| where + event.dataset == "aws.cloudtrail" + // filter on CloudTrail audit logs for IAM, EC2, S3, etc. + and event.provider in ( + "iam.amazonaws.com", + "ec2.amazonaws.com", + "s3.amazonaws.com", + "rds.amazonaws.com", + "lambda.amazonaws.com", + "dynamodb.amazonaws.com", + "kms.amazonaws.com", + "cloudfront.amazonaws.com", + "elasticloadbalancing.amazonaws.com", + "cloudtrail.amazonaws.com", + "sts.amazonaws.com", + "ses.amazonaws.com" + ) + // ignore AWS service actions + and aws.cloudtrail.user_identity.type != "AWSService" + // filter for aws-cli specifically + and user_agent.name == "aws-cli" + // exclude DescribeCapacityReservations events related to AWS Config + and not event.action in ("DescribeCapacityReservations") + +// filter for Describe, Get, List, and Generate API calls +| where true in ( + starts_with(event.action, "Describe"), + starts_with(event.action, "Get"), + starts_with(event.action, "List"), + starts_with(event.action, "Generate") +) + +// extract owner, identity type, and actor from the ARN +| 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}" + +| where starts_with(Esql.aws_cloudtrail_user_identity_arn_roles, "AWSServiceRoleForConfig") != true + +// keep relevant fields (preserving ECS fields and computed time window) +| keep @timestamp, Esql.time_window_date_trunc, event.action, aws.cloudtrail.user_identity.arn, aws.cloudtrail.user_identity.type, aws.cloudtrail.user_identity.access_key_id, source.ip, cloud.account.id, event.provider, user_agent.name, source.as.organization.name, cloud.region + +// count the number of unique API calls per time window and actor +| stats + Esql.event_action_count_distinct = count_distinct(event.action), + Esql.event_action_values = VALUES(event.action), + Esql.event_timestamp_values = VALUES(@timestamp), + Esql.aws_cloudtrail_user_identity_type_values = VALUES(aws.cloudtrail.user_identity.type), + Esql.aws_cloudtrail_user_identity_access_key_id_values = VALUES(aws.cloudtrail.user_identity.access_key_id), + Esql.source_ip_values = VALUES(source.ip), + Esql.cloud_account_id_values = VALUES(cloud.account.id), + Esql.event_provider_values = VALUES(event.provider), + Esql.user_agent_name_values = VALUES(user_agent.name), + Esql.source_as_organization_name_values = VALUES(source.as.organization.name), + Esql.cloud_region_values = VALUES(cloud.region) + by Esql.time_window_date_trunc, aws.cloudtrail.user_identity.arn + +// filter for more than 5 unique API calls per 10s window +| where Esql.event_action_count_distinct > 5 + +// sort the results by the number of unique API calls in descending order +| sort Esql.event_action_count_distinct desc +''' + + +[[rule.threat]] +framework = "MITRE ATT&CK" +[[rule.threat.technique]] +id = "T1580" +name = "Cloud Infrastructure Discovery" +reference = "https://attack.mitre.org/techniques/T1580/" + + +[rule.threat.tactic] +id = "TA0007" +name = "Discovery" +reference = "https://attack.mitre.org/tactics/TA0007/" + +[rule.investigation_fields] +field_names = [ + "Esql.event_action_count_distinct", + "Esql.time_window_date_trunc", + "aws.cloudtrail.user_identity.arn", + "Esql.aws_cloudtrail_user_identity_arn_type_values", + "Esql.aws_cloudtrail_user_identity_access_key_id_values", + "Esql.source_ip_values", + "Esql.source_as_organization_name_values", + "Esql.event_provider_values", + "Esql.event_action_values", + "Esql.cloud_region_values", + "Esql.cloud_account_id_values" + ] + diff --git a/rules_building_block/discovery_ec2_multi_region_describe_instances.toml b/rules_building_block/discovery_ec2_multi_region_describe_instances.toml new file mode 100644 index 00000000000..0f000e6cb58 --- /dev/null +++ b/rules_building_block/discovery_ec2_multi_region_describe_instances.toml @@ -0,0 +1,177 @@ +[metadata] +bypass_bbr_timing = true +creation_date = "2024/08/26" +integration = ["aws"] +maturity = "production" +updated_date = "2025/10/20" + +[rule] +author = ["Elastic"] +building_block_type = "default" +description = """ +Identifies when a single AWS resource is making `DescribeInstances` API calls in more than 10 regions within a 30-second +window. This could indicate a potential threat actor attempting to discover the AWS infrastructure across multiple +regions 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. +""" +false_positives = [ + """ + Legitimate use of the `DescribeInstances` API call by an AWS resource that requires information about instances in + multiple regions. + """, + "Scheduled tasks or scripts that require information about instances in multiple regions.", +] +from = "now-6m" +language = "esql" +license = "Elastic License v2" +name = "AWS EC2 Multi-Region DescribeInstances API Calls" +note = """## Triage and analysis + +### Investigating AWS EC2 Multi-Region DescribeInstances API Calls + +This rule flags when the `DescribeInstances` API is executed across multiple AWS regions within a short timeframe. While benign in some cases (e.g., asset inventory, legitimate multi-region management), this pattern can indicate a reconnaissance phase in which an adversary enumerates EC2 instances in all regions to identify potential targets across the environment. + +Because the signal can generate significant noise in dynamic or large AWS environments, this rule should be treated as a Building Block Rule (BBR), not a stand-alone alert requiring immediate incident response. Instead, it is best used for hunting, enrichment, correlation, and escalation when combined with other signals. + +### How to use this rule (hunting & correlation guide) + +This rule is most effective when paired with other detection rules or data sources. Use it to answer questions such as: + +- Did a newly created or unknown principal call `DescribeInstances` across many regions? Pair this with a new terms or first-time principal rule (e.g., `GetCallerIdentity`, `AssumeRole`, or `aws.cloudtrail.user_identity.session_context.session_issuer.arn`). +- Was the same principal also observed making other discovery or enumeration calls (e.g., `DescribeSnapshots`, `DescribeVolumes`, `DescribeImages`, `DescribeSecurityGroups`) in a short timeframe? +- Did the multi-region calls precede or coincide with higher-risk actions such as: + - Snapshot creation or shared snapshot modifications (`CreateSnapshot`, `ModifySnapshotAttribute`) + - AMI export/copy operations (`ExportImage`, `CopyImage`) + - Access key creation, role assumption, or IAM permission changes + - Unexpected S3 bucket or data transfer activity (e.g., large data egress, new S3 bucket writes) +- Did the activity span regions normally unused or outside the organization's typical operational footprint? + +#### Possible investigation steps: + +- **Review the principal and session trace**: + - Identify `aws.cloudtrail.user_identity.arn`, `aws.cloudtrail.user_identity.access_key_id`, and determine whether the principal is known, recently onboarded, or unusual (e.g., a service role used in rare cases). + - Examine `user_agent.original` and `source.ip` for anomalies (e.g., new CLI/SDK versions, IAM roles from unexpected hosts, geolocation outside expected range). + +- **Evaluate region distribution and timing**: + - Inspect the regions contacted by `DescribeInstances` within the alert window. Are some regions rarely used in your org? + - Look at the timeline: did the calls occur in rapid succession or spread out? A burst suggests automated reconnaissance rather than manual usage. + +- **Correlate with other detection signals & data access patterns**: + - Query for other CloudTrail events by the same principal in the ±30 minutes window: enumeration APIs (`Describe*`), snapshot/AMI events, `CopySnapshot`, `ExportImage`, `StartInstances`, etc. + - Cross-validate with SIEM or data egress logs: did large volumes of data leave the environment after the enumeration? + - Review IAM activity for privilege elevation, new access keys, or role chaining that could support the enumeration action. + +- **Assess intent and operational context**: + - Determine whether the enumeration aligns with known asset-inventory or management tasks (Recurring scans, DevOps automation, IT health checks). + - If this principal is known for asset management, verify the timing, region list, and audit logs for existing tickets/change-records. + - If the activity is unexpected, low legitimacy, or tied to other suspicious events, escalate. + +### False positive analysis: + +Because many organizations have legitimate multi-region cloud operations, this rule may generate false positives. Common benign scenarios include: + +- DevOps or cloud-ops automation that inventories EC2 instances across all regions (for cost, compliance, or multi-region deployment verification). +- Large-scale migrations or disaster-recovery tests that touch many regions in a short time. +- Security or audit team enumeration of the environment (e.g., internal red-team, internal asset scanning). +- Cross-account management tools in AWS Organizations that routinely query multiple regions. + +To manage these, consider: +- Whitelisting known automation roles/principals (with caution). +- Tagging and excluding known “inventory scan” sessions (based on user agent, IP range, timing). +- Using this rule only as a correlation trigger and not as a direct alert. + +### Response and escalation: + +Because this rule is a BBR, its detection alone does not usually warrant full incident response. Instead: + +- **Document the finding** in your hunt log, noting principal, regions, timestamp, and correlation flags (other events). +- If correlation reveals additional suspicious activity (e.g., snapshot share, data export, IAM privilege change) escalate to full incident response. +- If the enumeration is determined benign (e.g., approved internal scan), add context (ticket number, owner, justification) and suppress/annotate this principal in future hunts for a defined interval. +- Update your detection playbooks to reflect this rule’s role as a recon-indicator, and train analysts to use it as a pivot point. + +### Additional information + +For further information on AWS `DescribeInstances` permissions and best practices, refer to the [AWS DescribeInstances API documentation](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeInstances.html). +""" +references = [ + "https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeInstances.html", +] +risk_score = 21 +rule_id = "393ef120-63d1-11ef-8e38-f661ea17fbce" +severity = "low" +tags = [ + "Domain: Cloud", + "Data Source: AWS", + "Data Source: AWS EC2", + "Resources: Investigation Guide", + "Rule Type: BBR", + "Use Case: Threat Detection", + "Tactic: Discovery", +] +timestamp_override = "event.ingested" +type = "esql" + +query = ''' +from logs-aws.cloudtrail-* + +// filter for DescribeInstances API calls +| where event.dataset == "aws.cloudtrail" + and event.provider == "ec2.amazonaws.com" + and event.action == "DescribeInstances" + +// truncate the timestamp to a 30-second window +| eval Esql.time_window_date_trunc = date_trunc(30 seconds, @timestamp) + +// keep only the relevant raw fields +| keep + Esql.time_window_date_trunc, + aws.cloudtrail.user_identity.arn, + cloud.region, + cloud.account.id, + aws.cloudtrail.user_identity.access_key_id, + aws.cloudtrail.user_identity.type, + user_agent.original, + source.ip, + @timestamp + +// count the number of unique regions and total API calls within the 30-second window +| stats + Esql.cloud_region_count_distinct = count_distinct(cloud.region), + Esql.event_count = count(*) + by Esql.time_window_date_trunc, aws.cloudtrail.user_identity.arn + +// filter for resources making DescribeInstances API calls in more than 10 regions within the 30-second window +| where Esql.cloud_region_count_distinct >= 10 and Esql.event_count >= 10 + +// sort the results by time window in descending order +| sort Esql.time_window_date_trunc desc +''' + + +[[rule.threat]] +framework = "MITRE ATT&CK" +[[rule.threat.technique]] +id = "T1580" +name = "Cloud Infrastructure Discovery" +reference = "https://attack.mitre.org/techniques/T1580/" + + +[rule.threat.tactic] +id = "TA0007" +name = "Discovery" +reference = "https://attack.mitre.org/tactics/TA0007/" + +[rule.investigation_fields] +field_names = [ + "aws.cloudtrail.user_identity.arn", + "target_time_window", + "region_count", + "window_count", + "cloud.account.id", + "aws.cloudtrail.user_identity.access_key_id", + "aws.cloudtrail.user_identity.type", + "user_agent.original", + "source.ip", + "@timestamp", +] +