Skip to content

Commit 2177135

Browse files
Samirbouseric-forte-elasticMikaayensonshashank-elastic
authored
[New] AWS Rare Source AS Organization Activity (#5957)
* [New] AWS Rare Source AS Organization Activity Surfaces an AWS identity whose successful API traffic is dominated by a small set of large cloud-provider source AS organization labels, yet also shows a very small share of traffic from other AS organization names—including at least one sensitive control-plane, credential, storage, or model-invocation action on that uncommon network path with recent activity from the uncommon path. The intent is to highlight disproportionate “baseline” cloud egress versus sparse use from rarer networks on the same principal, a shape that can appear when automation or CI credentials are reused or pivoted outside their usual hosted-cloud footprint. * Apply suggestion from @eric-forte-elastic Co-authored-by: Eric Forte <119343520+eric-forte-elastic@users.noreply.github.com> * Update initial_access_aws_api_unusual_asn.toml * Update initial_access_aws_api_unusual_asn.toml * Update initial_access_aws_api_unusual_asn.toml --------- Co-authored-by: Eric Forte <119343520+eric-forte-elastic@users.noreply.github.com> Co-authored-by: Mika Ayenson, PhD <Mikaayenson@users.noreply.github.com> Co-authored-by: shashank-elastic <91139415+shashank-elastic@users.noreply.github.com>
1 parent 62076dd commit 2177135

1 file changed

Lines changed: 181 additions & 0 deletions

File tree

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
[metadata]
2+
creation_date = "2026/04/21"
3+
integration = ["aws"]
4+
maturity = "production"
5+
updated_date = "2026/04/21"
6+
7+
[rule]
8+
author = ["Elastic"]
9+
description = """
10+
Surfaces an AWS identity whose successful API traffic is dominated by a small set of large cloud-provider source AS
11+
organization labels, yet also shows a very small share of traffic from other AS organization names—including at least one
12+
sensitive control-plane, credential, storage, or model-invocation action on that uncommon network path with recent
13+
activity from the uncommon path. The intent is to highlight disproportionate “baseline” cloud egress versus sparse use
14+
from rarer networks on the same principal, a shape that can appear when automation or CI credentials are reused or
15+
pivoted outside their usual hosted-cloud footprint.
16+
"""
17+
false_positives = [
18+
"""
19+
Global employees on VPNs, split DNS or proxy paths that change AS labels, regional carrier rebrands, or mobile
20+
hotspots can produce a small non-cloud AS share on the same IAM user as hyperscaler- or SaaS-classified traffic.
21+
Corporate travel, emergency break-glass from a home ISP, and multi-region runners may also widen AS diversity without
22+
malice. Tune thresholds, add account or principal allowlists, or narrow the sensitive-action list after baseline review.
23+
""",
24+
]
25+
from = "now-7d"
26+
interval = "1h"
27+
language = "esql"
28+
license = "Elastic License v2"
29+
name = "AWS Rare Source AS Organization Activity"
30+
note = """## Triage and analysis
31+
32+
### Investigating AWS Rare Source AS Organization Activity After High Cloud-Provider Volume
33+
34+
The rule aggregates roughly seven days of successful CloudTrail per `user.name` and `aws.cloudtrail.user_identity.type`.
35+
It expects a **high count** of events whose GeoIP AS organization matches a short allowlist of large cloud/SaaS providers,
36+
**at least one** event from a different AS organization, a **low ratio** of uncommon-network events to all events, few
37+
**distinct** uncommon AS labels, and **recent** uncommon-network timestamps. It further requires at least one
38+
**sensitive** API from an uncommon network (see query `event.action` list).
39+
40+
#### Possible investigation steps
41+
42+
- Compare `Esql.src_asn_values` to `Esql.user_agent_values` and map each `source.ip` (from raw CloudTrail) to expected
43+
admin paths, pipelines, or offices.
44+
- Pivot on `user.name` and `aws.cloudtrail.user_identity.access_key_id` (from underlying events) for IAM, STS, S3, and
45+
Secrets Manager activity around `Esql.most_recent_low_asn_day`.
46+
- Confirm whether the identity is meant for automation only; if so, rare human ISP ASNs warrant higher scrutiny.
47+
- Review `Esql.untrusted_suspicious_actions` for the mix of discovery versus privilege-changing APIs.
48+
49+
### False positive analysis
50+
51+
- **Threshold sensitivity**: Raise `Esql.trusted_cloud_event_count` or Lower `Esql.rare_asn_ratio` and `Esql.untrusted_event_count` if legitimate rare-ASN
52+
noise persists.
53+
- **MongoDB / other allowlist labels**: Extend `is_trusted_cloud` if your approved automation consistently appears under
54+
another legal-entity string.
55+
56+
### Response and remediation
57+
58+
- If abuse is plausible: rotate credentials for the principal, enforce OIDC or short-lived keys for automation, and
59+
tighten IAM and data-plane permissions.
60+
61+
### Additional information
62+
63+
- [CloudTrail user identity](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-event-reference-user-identity.html)
64+
"""
65+
references = [
66+
"https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-event-reference.html",
67+
]
68+
risk_score = 73
69+
rule_id = "d1b37c0b-4f8b-4cfb-9a1d-639bf8c028b7"
70+
severity = "high"
71+
tags = [
72+
"Domain: Cloud",
73+
"Data Source: AWS",
74+
"Data Source: Amazon Web Services",
75+
"Data Source: AWS CloudTrail",
76+
"Use Case: Threat Detection",
77+
"Tactic: Initial Access",
78+
"Resources: Investigation Guide",
79+
]
80+
timestamp_override = "event.ingested"
81+
type = "esql"
82+
83+
query = '''
84+
FROM logs-aws.cloudtrail-*
85+
| WHERE event.dataset == "aws.cloudtrail"
86+
AND event.outcome == "success"
87+
AND source.as.organization.name IS NOT NULL
88+
AND user.name IS NOT NULL
89+
90+
| EVAL is_trusted_cloud = CASE(
91+
source.as.organization.name LIKE "Amazon*" OR
92+
source.as.organization.name == "Google LLC" OR
93+
source.as.organization.name == "Microsoft Corporation" OR
94+
source.as.organization.name == "MongoDB, Inc.",
95+
true, false
96+
)
97+
98+
| EVAL is_suspicious_action = CASE(
99+
event.action IN (
100+
"GetCallerIdentity", "GetAccountSummary", "ListAccountAliases",
101+
"GetSecretValue", "ListSecrets", "DescribeSecret",
102+
"GetParameter", "GetParameters", "GetParametersByPath",
103+
"AssumeRole", "AssumeRoleWithWebIdentity", "AssumeRoleWithSAML",
104+
"AttachUserPolicy", "AttachRolePolicy",
105+
"PutUserPolicy", "PutRolePolicy",
106+
"CreateAccessKey", "UpdateAccessKey",
107+
"CreateUser", "CreateLoginProfile",
108+
"UpdateLoginProfile", "AddUserToGroup",
109+
"GetObject", "ListBuckets", "ListObjects", "ListObjectsV2",
110+
"InvokeModel", "InvokeModelWithResponseStream", "Converse"
111+
), true, false
112+
)
113+
114+
// Single aggregation — full event count preserved for ratio logic
115+
// suspicious action tracking is additive on top
116+
| STATS
117+
Esql.total_events_all_asns = COUNT(*),
118+
Esql.count_distinct_asns = COUNT_DISTINCT(source.as.organization.name),
119+
Esql.src_asn_values = VALUES(source.as.organization.name),
120+
Esql.user_agent_values = VALUES(user_agent.original),
121+
Esql.related_users = VALUES(user.changes.name),
122+
Esql.source_ip_values = VALUES(source.address),
123+
Esql.has_trusted_cloud_asn = MAX(is_trusted_cloud),
124+
Esql.trusted_cloud_event_count = SUM(CASE(is_trusted_cloud == true, 1, 0)),
125+
Esql.untrusted_event_count = SUM(CASE(is_trusted_cloud == false, 1, 0)),
126+
// Suspicious action visibility from untrusted ASNs — informational only, not a filter
127+
Esql.untrusted_suspicious_count = SUM(CASE(
128+
is_trusted_cloud == false AND is_suspicious_action == true, 1, 0
129+
)),
130+
Esql.untrusted_suspicious_actions = VALUES(CASE(
131+
is_trusted_cloud == false AND is_suspicious_action == true,
132+
event.action, null
133+
)),
134+
Esql.most_recent_low_asn_day = MAX(CASE(
135+
is_trusted_cloud == false, @timestamp, null
136+
))
137+
BY user.name, aws.cloudtrail.user_identity.type
138+
139+
| EVAL Esql.rare_asn_ratio = TO_DOUBLE(Esql.untrusted_event_count) / TO_DOUBLE(Esql.total_events_all_asns),
140+
Esql.unique_action_from_untrusted_asn = MV_COUNT(Esql.untrusted_suspicious_actions)
141+
142+
// Detection thresholds — unchanged, full event counts drive the logic
143+
| WHERE Esql.has_trusted_cloud_asn == true
144+
AND Esql.untrusted_event_count >= 1
145+
AND Esql.trusted_cloud_event_count >= 100
146+
AND Esql.rare_asn_ratio <= 0.01
147+
AND Esql.unique_action_from_untrusted_asn >= 2
148+
AND Esql.count_distinct_asns <= 5
149+
AND Esql.most_recent_low_asn_day >= NOW() - 1 hour
150+
151+
| KEEP user.name,
152+
aws.cloudtrail.user_identity.type,
153+
Esql.*
154+
'''
155+
156+
[rule.investigation_fields]
157+
field_names = [
158+
"user.name",
159+
"aws.cloudtrail.user_identity.type",
160+
"Esql.*"
161+
]
162+
163+
164+
165+
[[rule.threat]]
166+
framework = "MITRE ATT&CK"
167+
168+
[[rule.threat.technique]]
169+
id = "T1078"
170+
name = "Valid Accounts"
171+
reference = "https://attack.mitre.org/techniques/T1078/"
172+
173+
[[rule.threat.technique.subtechnique]]
174+
id = "T1078.004"
175+
name = "Cloud Accounts"
176+
reference = "https://attack.mitre.org/techniques/T1078/004/"
177+
178+
[rule.threat.tactic]
179+
id = "TA0001"
180+
name = "Initial Access"
181+
reference = "https://attack.mitre.org/tactics/TA0001/"

0 commit comments

Comments
 (0)