AWS Access Token Used from Multiple Addresses
This rule identifies potentially suspicious activity by detecting instances where a single IAM user's temporary session token is accessed from multiple IP addresses within a short time frame. Such behavior may suggest that an adversary has compromised temporary credentials and is utilizing them from various locations. To enhance detection accuracy and minimize false positives, the rule incorporates criteria that evaluate unique IP addresses, user agents, cities, and networks. These additional checks help distinguish between legitimate distributed access patterns and potential credential misuse. Detected activities are classified into different types based on the combination of unique indicators, with each classification assigned a fidelity score reflecting the likelihood of malicious behavior. High fidelity scores are given to patterns most indicative of threats, such as multiple unique IPs, networks, cities, and user agents. Medium and low fidelity scores correspond to less severe patterns, enabling security teams to effectively prioritize alerts.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2025/04/11"
3integration = ["aws"]
4maturity = "production"
5updated_date = "2025/07/16"
6
7[rule]
8author = ["Elastic"]
9description = """
10This rule identifies potentially suspicious activity by detecting instances where a single IAM user's temporary session
11token is accessed from multiple IP addresses within a short time frame. Such behavior may suggest that an adversary has
12compromised temporary credentials and is utilizing them from various locations. To enhance detection accuracy and
13minimize false positives, the rule incorporates criteria that evaluate unique IP addresses, user agents, cities, and
14networks. These additional checks help distinguish between legitimate distributed access patterns and potential
15credential misuse. Detected activities are classified into different types based on the combination of unique
16indicators, with each classification assigned a fidelity score reflecting the likelihood of malicious behavior. High
17fidelity scores are given to patterns most indicative of threats, such as multiple unique IPs, networks, cities, and
18user agents. Medium and low fidelity scores correspond to less severe patterns, enabling security teams to effectively
19prioritize alerts.
20"""
21false_positives = [
22 """
23 Highly distributed environments (e.g., globally deployed automation or edge nodes) may cause a single IAM user to
24 appear from multiple IPs. Review the geolocation, network context, and user agent patterns to rule out benign use.
25 """,
26]
27from = "now-32m"
28interval = "5m"
29language = "esql"
30license = "Elastic License v2"
31name = "AWS Access Token Used from Multiple Addresses"
32note = """## Triage and Analysis
33
34### Investigating AWS Access Token Used from Multiple Addresses
35
36Access tokens are bound to a single user. Usage from multiple IP addresses may indicate the token was stolen and used elsewhere. By correlating this with additional detection criteria like multiple user agents, different cities, and different networks, we can improve the fidelity of the rule and help to eliminate false positives associated with expected behavior, like dual-stack IPV4/IPV6 usage.
37
38#### Possible Investigation Steps
39
40- **Identify the IAM User**: Examine the `aws.cloudtrail.user_identity.arn` stored in `user_id` and correlate with the `source.ips` stored in `ip_list` and `unique_ips` count to determine how widely the token was used.
41- **Correlate Additional Detection Context**: Examine `activity_type` and `fidelity_score` to determine additional cities, networks or user agents associated with the token usage.
42- **Determine Access Key Type**: Examine the `access_key_id` to determine whether the token is short-term (beginning with ASIA) or long-term (beginning with AKIA).
43- **Check Recent MFA Events**: Determine whether the user recently enabled MFA, registered devices, or assumed a role using this token.
44- **Review Workload Context**: Confirm whether the user was expected to be active across multiple cities, networks or user agent environments.
45- **Trace Adversary Movement**: Pivot to related actions (e.g., `s3:ListBuckets`, `iam:ListUsers`, `sts:GetCallerIdentity`) to track further enumeration.
46
47### False Positive Analysis
48
49- Automation frameworks that rotate through multiple IPs or cloud functions with dynamic egress IPs may cause this alert to fire.
50- Confirm geolocation and workload context before escalating.
51
52### Response and Remediation
53
54- **Revoke the Token**: Disable or rotate the IAM credentials and invalidate the temporary session token.
55- **Audit the Environment**: Look for signs of lateral movement or data access during the token's validity.
56- **Strengthen Controls**: Require MFA for high-privilege actions, restrict access via policy conditions (e.g., IP range or device).
57
58### References
59
60- [IAM Long-Term Credentials](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html)
61- [STS Temporary Credentials](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html)
62- [Using MFA with Temporary Credentials](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html)
63- [AWS Threat Detection Use Cases](https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-standards-fsbp-controls.html)
64"""
65references = ["https://www.sygnia.co/blog/sygnia-investigation-bybit-hack/"]
66risk_score = 47
67rule_id = "0d92d30a-5f3e-4b71-bc3d-4a0c4914b7e0"
68severity = "medium"
69tags = [
70 "Domain: Cloud",
71 "Data Source: AWS",
72 "Data Source: Amazon Web Services",
73 "Data Source: AWS IAM",
74 "Data Source: AWS CloudTrail",
75 "Tactic: Initial Access",
76 "Use Case: Identity and Access Audit",
77 "Resources: Investigation Guide",
78]
79timestamp_override = "event.ingested"
80type = "esql"
81
82query = '''
83from logs-aws.cloudtrail* metadata _id, _version, _index
84| where @timestamp > now() - 30 minutes
85 and event.dataset == "aws.cloudtrail"
86 and aws.cloudtrail.user_identity.arn is not null
87 and aws.cloudtrail.user_identity.type == "IAMUser"
88 and source.ip is not null
89 and not (
90 user_agent.original like "%Terraform%" or
91 user_agent.original like "%Ansible%" or
92 user_agent.original like "%Pulumni%"
93 )
94 and `source.as.organization.name` != "AMAZON-AES"
95 and event.provider not in (
96 "health.amazonaws.com", "monitoring.amazonaws.com", "notifications.amazonaws.com",
97 "ce.amazonaws.com", "cost-optimization-hub.amazonaws.com",
98 "servicecatalog-appregistry.amazonaws.com", "securityhub.amazonaws.com"
99 )
100
101| eval
102 Esql.time_window_date_trunc = date_trunc(30 minutes, @timestamp),
103 Esql.aws_cloudtrail_user_identity_arn = aws.cloudtrail.user_identity.arn,
104 Esql.aws_cloudtrail_user_identity_access_key_id = aws.cloudtrail.user_identity.access_key_id,
105 Esql.source_ip = source.ip,
106 Esql.user_agent_original = user_agent.original,
107 Esql.source_ip_string = to_string(source.ip),
108 Esql.source_ip_user_agent_pair = concat(Esql.source_ip_string, " - ", user_agent.original),
109 Esql.source_ip_city_pair = concat(Esql.source_ip_string, " - ", source.geo.city_name),
110 Esql.source_geo_city_name = source.geo.city_name,
111 Esql.event_timestamp = @timestamp,
112 Esql.source_network_org_name = `source.as.organization.name`
113
114| stats
115 Esql.event_action_values = values(event.action),
116 Esql.event_provider_values = values(event.provider),
117 Esql.aws_cloudtrail_user_identity_access_key_id_values = values(Esql.aws_cloudtrail_user_identity_access_key_id),
118 Esql.aws_cloudtrail_user_identity_arn_values = values(Esql.aws_cloudtrail_user_identity_arn),
119 Esql.source_ip_values = values(Esql.source_ip),
120 Esql.user_agent_original_values = values(Esql.user_agent_original),
121 Esql.source_ip_user_agent_pair_values = values(Esql.source_ip_user_agent_pair),
122 Esql.source_geo_city_name_values = values(Esql.source_geo_city_name),
123 Esql.source_ip_city_pair_values = values(Esql.source_ip_city_pair),
124 Esql.source_network_org_name_values = values(Esql.source_network_org_name),
125 Esql.source_ip_count_distinct = count_distinct(Esql.source_ip),
126 Esql.user_agent_original_count_distinct = count_distinct(Esql.user_agent_original),
127 Esql.source_geo_city_name_count_distinct = count_distinct(Esql.source_geo_city_name),
128 Esql.source_network_org_name_count_distinct = count_distinct(Esql.source_network_org_name),
129 Esql.timestamp_first_seen = min(Esql.event_timestamp),
130 Esql.timestamp_last_seen = max(Esql.event_timestamp),
131 Esql.event_count = count()
132 by Esql.time_window_date_trunc, Esql.aws_cloudtrail_user_identity_access_key_id
133
134| eval
135 Esql.activity_type = case(
136 Esql.source_ip_count_distinct >= 2 and Esql.source_network_org_name_count_distinct >= 2 and Esql.source_geo_city_name_count_distinct >= 2 and Esql.user_agent_original_count_distinct >= 2, "multiple_ip_network_city_user_agent",
137 Esql.source_ip_count_distinct >= 2 and Esql.source_network_org_name_count_distinct >= 2 and Esql.source_geo_city_name_count_distinct >= 2, "multiple_ip_network_city",
138 Esql.source_ip_count_distinct >= 2 and Esql.source_geo_city_name_count_distinct >= 2, "multiple_ip_and_city",
139 Esql.source_ip_count_distinct >= 2 and Esql.source_network_org_name_count_distinct >= 2, "multiple_ip_and_network",
140 Esql.source_ip_count_distinct >= 2 and Esql.user_agent_original_count_distinct >= 2, "multiple_ip_and_user_agent",
141 "normal_activity"
142 ),
143 Esql.activity_fidelity_score = case(
144 Esql.activity_type == "multiple_ip_network_city_user_agent", "high",
145 Esql.activity_type == "multiple_ip_network_city", "high",
146 Esql.activity_type == "multiple_ip_and_city", "medium",
147 Esql.activity_type == "multiple_ip_and_network", "medium",
148 Esql.activity_type == "multiple_ip_and_user_agent", "low"
149 )
150
151| keep
152 Esql.time_window_date_trunc,
153 Esql.activity_type,
154 Esql.activity_fidelity_score,
155 Esql.event_count,
156 Esql.timestamp_first_seen,
157 Esql.timestamp_last_seen,
158 Esql.aws_cloudtrail_user_identity_arn_values,
159 Esql.aws_cloudtrail_user_identity_access_key_id_values,
160 Esql.event_action_values,
161 Esql.event_provider_values,
162 Esql.source_ip_values,
163 Esql.user_agent_original_values,
164 Esql.source_ip_user_agent_pair_values,
165 Esql.source_geo_city_name_values,
166 Esql.source_ip_city_pair_values,
167 Esql.source_network_org_name_values,
168 Esql.source_ip_count_distinct,
169 Esql.user_agent_original_count_distinct,
170 Esql.source_geo_city_name_count_distinct,
171 Esql.source_network_org_name_count_distinct
172
173| where Esql.activity_type != "normal_activity"
174'''
175
176
177[[rule.threat]]
178framework = "MITRE ATT&CK"
179[[rule.threat.technique]]
180id = "T1078"
181name = "Valid Accounts"
182reference = "https://attack.mitre.org/techniques/T1078/"
183[[rule.threat.technique.subtechnique]]
184id = "T1078.004"
185name = "Cloud Accounts"
186reference = "https://attack.mitre.org/techniques/T1078/004/"
187
188
189
190[rule.threat.tactic]
191id = "TA0001"
192name = "Initial Access"
193reference = "https://attack.mitre.org/tactics/TA0001/"
Triage and Analysis
Investigating AWS Access Token Used from Multiple Addresses
Access tokens are bound to a single user. Usage from multiple IP addresses may indicate the token was stolen and used elsewhere. By correlating this with additional detection criteria like multiple user agents, different cities, and different networks, we can improve the fidelity of the rule and help to eliminate false positives associated with expected behavior, like dual-stack IPV4/IPV6 usage.
Possible Investigation Steps
- Identify the IAM User: Examine the
aws.cloudtrail.user_identity.arn
stored inuser_id
and correlate with thesource.ips
stored inip_list
andunique_ips
count to determine how widely the token was used. - Correlate Additional Detection Context: Examine
activity_type
andfidelity_score
to determine additional cities, networks or user agents associated with the token usage. - Determine Access Key Type: Examine the
access_key_id
to determine whether the token is short-term (beginning with ASIA) or long-term (beginning with AKIA). - Check Recent MFA Events: Determine whether the user recently enabled MFA, registered devices, or assumed a role using this token.
- Review Workload Context: Confirm whether the user was expected to be active across multiple cities, networks or user agent environments.
- Trace Adversary Movement: Pivot to related actions (e.g.,
s3:ListBuckets
,iam:ListUsers
,sts:GetCallerIdentity
) to track further enumeration.
False Positive Analysis
- Automation frameworks that rotate through multiple IPs or cloud functions with dynamic egress IPs may cause this alert to fire.
- Confirm geolocation and workload context before escalating.
Response and Remediation
- Revoke the Token: Disable or rotate the IAM credentials and invalidate the temporary session token.
- Audit the Environment: Look for signs of lateral movement or data access during the token's validity.
- Strengthen Controls: Require MFA for high-privilege actions, restrict access via policy conditions (e.g., IP range or device).
References
References
Related rules
- AWS IAM Virtual MFA Device Registration Attempt with Session Token
- AWS IAM AdministratorAccess Policy Attached to Group
- AWS IAM AdministratorAccess Policy Attached to Role
- AWS IAM AdministratorAccess Policy Attached to User
- AWS IAM Login Profile Added for Root