AWS STS GetCallerIdentity Bulk Account Enumeration
editAWS STS GetCallerIdentity Bulk Account Enumeration
editIdentifies three or more distinct AWS principals calling STS "GetCallerIdentity" from the same source IP and autonomous system within a 10-minute window. "GetCallerIdentity" returns the account and identity behind a credential and requires no permissions, so a burst of different non-role identities from one external address is a common credential-validation and account-enumeration step. Assumed roles, Vault OIDC users, and calls from major cloud and carrier networks are excluded.
Rule type: esql
Rule indices: None
Severity: high
Risk score: 73
Runs every: 5m
Searches indices from: now-10m (Date Math format, see also Additional look-back time)
Maximum alerts per execution: 100
References:
Tags:
- Domain: Cloud
- Data Source: AWS
- Data Source: Amazon Web Services
- Data Source: AWS CloudTrail
- Platform: AWS
- Service: AWS STS
- Use Case: Threat Detection
- Tactic: Discovery
- Resources: Investigation Guide
- Rule Type: ES|QL
Version: 1
Rule authors:
- Elastic
Rule license: Elastic License v2
Investigation guide
editTriage and analysis
Investigating AWS STS GetCallerIdentity Bulk Account Enumeration
GetCallerIdentity returns the account and principal for the credentials that called it. No IAM permission is
required. This rule groups successful calls that are not AssumedRole by source IP and source ASN. It alerts when
that group contains at least three distinct user.name values. The rule runs every 5 minutes and looks back 10
minutes, so the threshold is the last 10 minutes of activity. Alerts for the same source.ip are suppressed for
24 hours.
This complements AWS STS GetCallerIdentity API Called for the First Time, which alerts on the first call from one identity. This rule alerts when several identities are checked from one external address.
Possible investigation steps
-
Review
source.ip,source.as.organization.name, andEsql.user_agent_original_values. An AWS CLI, SDK, or unknown client from an unfamiliar ASN is higher priority than a known management host. -
Review
Esql.user_name_valuesandEsql.aws_cloudtrail_user_identity_arn_values. Check whether the identities are unrelated IAM users, include privileged users, or share one access key. -
Compare
Esql.user_name_count_distinctwithEsql.aws_cloudtrail_user_identity_arn_count_distinct. A higher ARN count than user count can mean several keys or federation sessions for the same user names. -
Search CloudTrail for those identities in the surrounding hour for
AssumeRole,GetSessionToken, IAM changes, and discovery calls such asListUsers,ListBuckets, andDescribeInstances. - Determine whether any of the credentials were used successfully after the identity check.
False positive analysis
-
Users named
vault-oidc-*are excluded. -
AssumedRolesessions are excluded. IAM users, federated users, and the root user remain in scope. - Calls whose source ASN is Amazon, Google, Microsoft, Verizon, or AT&T are excluded.
- Shared egress that is not in that ASN list can still reach three users. Exclude the source IP or user agent when the behavior is documented.
Response and remediation
- If the activity is not authorized, disable the access keys for the listed users and revoke active sessions.
- Rotate credentials that were validated from the source IP.
- Review CloudTrail for follow-on use of those identities and contain any resources they touched.
Setup
editSetup
The AWS integration must collect CloudTrail management events into logs-aws.cloudtrail-*.
GetCallerIdentity is a management event logged by default. source.as.organization.name must be populated,
because events missing it are excluded.
Rule query
editfrom logs-aws.cloudtrail-*
| where KQL("""data_stream.dataset: "aws.cloudtrail" and event.provider: "sts.amazonaws.com" and event.action: "GetCallerIdentity" and event.outcome: "success" and not aws.cloudtrail.user_identity.type: "AssumedRole" and source.as.organization.name: * and not user.name: vault-oidc-*""")
and source.ip is not null
and not source.as.organization.name in (
"Amazon.com, Inc.",
"AMAZON-02",
"AMAZON-AES",
"Google LLC",
"Microsoft Corporation",
"Verizon Business",
"AT&T Enterprises, LLC"
)
| stats
Esql.aws_cloudtrail_user_identity_arn_count_distinct = count_distinct(aws.cloudtrail.user_identity.arn),
Esql.user_name_count_distinct = count_distinct(user.name),
Esql.user_name_values = values(user.name),
Esql.user_agent_original_values = values(user_agent.original),
Esql.aws_cloudtrail_user_identity_arn_values = values(aws.cloudtrail.user_identity.arn)
by source.ip, source.as.organization.name
| where Esql.user_name_count_distinct >= 3
| keep
Esql.user_name_count_distinct,
Esql.aws_cloudtrail_user_identity_arn_count_distinct,
source.ip,
source.as.organization.name,
Esql.user_name_values,
Esql.user_agent_original_values,
Esql.aws_cloudtrail_user_identity_arn_values
Framework: MITRE ATT&CKTM
-
Tactic:
- Name: Discovery
- ID: TA0007
- Reference URL: https://attack.mitre.org/tactics/TA0007/
-
Technique:
- Name: Account Discovery
- ID: T1087
- Reference URL: https://attack.mitre.org/techniques/T1087/
-
Sub-technique:
- Name: Cloud Account
- ID: T1087.004
- Reference URL: https://attack.mitre.org/techniques/T1087/004/
-
Technique:
- Name: System Owner/User Discovery
- ID: T1033
- Reference URL: https://attack.mitre.org/techniques/T1033/