AWS Discovery API Calls from VPN ASN for the First Time by Identity
Flags the first time a given IAM principal invokes a narrow set of high-signal discovery APIs (credential check,
account and IAM enumeration, bucket and compute inventory, logging introspection) from a source IP whose autonomous
system number (ASN) matches a curated set commonly associated with consumer VPN brands, VPN-heavy hosting, and provider
networks referenced in public reporting on TeamPCP activity (for example 31173 Services AB AS39351 and Oy Crea Nova
Hosting Solution Ltd). Broad List*/Describe* patterns are intentionally omitted to reduce noise. Hosting ASNs are
heavily dual-use; validate source.as.number in your data and extend event.action only when your baseline allows it.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2026/04/03"
3integration = ["aws"]
4maturity = "production"
5updated_date = "2026/04/03"
6
7[rule]
8author = ["Elastic"]
9description = """
10Flags the first time a given IAM principal invokes a narrow set of high-signal discovery APIs (credential check,
11account and IAM enumeration, bucket and compute inventory, logging introspection) from a source IP whose autonomous
12system number (ASN) matches a curated set commonly associated with consumer VPN brands, VPN-heavy hosting, and provider
13networks referenced in public reporting on TeamPCP activity (for example 31173 Services AB AS39351 and Oy Crea Nova
14Hosting Solution Ltd). Broad `List*`/`Describe*` patterns are intentionally omitted to reduce noise. Hosting ASNs are
15heavily dual-use; validate `source.as.number` in your data and extend `event.action` only when your baseline allows it.
16"""
17false_positives = [
18 """
19 Administrators, developers, CI runners, and SaaS egress often exit through Datacamp, M247, Vultr, Linode, or
20 brand-name VPN ASNs. Expect more noise on hosting ASNs than on VPN-only registrations. Exclude approved principals,
21 accounts, CIDRs, or ASNs after review. GeoIP and ASN enrichment gaps (`source.as.number` unset) will skip events
22 entirely. Maintain the ASN list with local intelligence (for example RIPE, BGPView, or peeringdb).
23 """,
24]
25from = "now-6m"
26index = ["filebeat-*", "logs-aws.cloudtrail-*"]
27language = "kuery"
28license = "Elastic License v2"
29name = "AWS Discovery API Calls from VPN ASN for the First Time by Identity"
30note = """## Triage and analysis
31
32### Investigating AWS Discovery API Calls from VPN ASN for the First Time by Identity
33
34This rule applies a [New Terms](https://www.elastic.co/guide/en/security/current/rules-ui-create.html#create-new-terms-rule) condition on **`source.as.number`** and **`aws.cloudtrail.user_identity.arn`**. It fires the first time a specific principal is observed calling discovery-like APIs from an IP geolocated to one of the ASNs in the rule query (within the 10-day history window).
35
36**High-signal `event.action` values** (explicit allowlist in the rule query): `GetCallerIdentity`; IAM `ListUsers`,
37`ListRoles`, `ListAccessKeys`, `GetAccountSummary`, `ListAccountAliases`, `ListGroups`, `ListMFADevices`; S3 `ListBuckets`;
38EC2 `DescribeInstances`, `DescribeRegions`, `DescribeVpcs`, `DescribeSecurityGroups`; Lambda `ListFunctions`; RDS
39`DescribeDBInstances`, `DescribeDBSnapshots`; DynamoDB `ListTables`; KMS `ListKeys`, `ListAliases`; CloudTrail
40`DescribeTrails`, `LookupEvents`. Clone the rule to add actions (for example ELB or Secrets Manager) if needed.
41
42**Curated VPN-oriented ASNs (verify locally)** — examples this rule matches (subject to registry and enrichment updates):
43
44| ASN | Commonly associated operator (reference only) |
45|-----|-----------------------------------------------|
46| 216025 | Mullvad VPN AB |
47| 57138 | Mullvad supporting infrastructure |
48| 207137 | Tefincom S.A. (NordVPN-related) |
49| 212238 | Nord / Nord Security class VPN egress in many datasets |
50| 199218 | ProtonVPN |
51| 209103 | Proton AG (VPN; confirm in your enrichment source) |
52| 209854 | Surfshark Ltd. |
53| 141039, 147049 | Packet-style VPN/colocation pools often tied to large VPN footprints |
54| 53314 | ExpressVPN-related registration in some registries (often small; validate) |
55| 60068 | Datacamp Limited — CDN/hosting; used by several VPN brands and many legitimate workloads (**high dual-use**) |
56| 9009 | M247 Ltd — colocation and connectivity; common VPN/proxy exit (**high dual-use**) |
57| 20473 | Choopa / Vultr (The Constant Company) — VPS; frequent VPN exit and automation (**high dual-use**) |
58| 63949 | Linode LLC (Akamai cloud) — VPS; VPN exits and dev workloads (**dual-use**) |
59| 39351 | 31173 Services AB (Sweden) — colocation/hosting; cited in TeamPCP-related reporting (**dual-use**). Not the same as **AS31173** (unrelated Ukrainian ISP). |
60| 51765 | Oy Crea Nova Hosting Solution Ltd (Finland) — hosting; cited in TeamPCP-related reporting (**dual-use**) |
61| 204187 | Oy Crea Nova Hosting Solution Ltd — related network under the same operator (**dual-use**) |
62
63Other ASNs sometimes seen for VPN or reseller egress (not in this rule by default) include **16276** (OVH), **14061**
64(DigitalOcean), **24940** (Hetzner), **51167** (Contabo), and **49453** (Global Layer). Add them only if your baseline
65shows manageable false-positive volume.
66
67#### Possible investigation steps
68
69- Confirm `aws.cloudtrail.user_identity.arn`, `aws.cloudtrail.user_identity.type`, and `aws.cloudtrail.user_identity.access_key_id`.
70- Review `event.action` and `event.provider` in the alert; several distinct allowlisted actions from the same session suggest broader enumeration.
71- Compare `source.ip`, `source.as.organization.name`, and `source.as.number` against your asset inventory and approved remote-access patterns.
72- Hunt ±30 minutes for privilege changes, data access (`GetObject`, snapshot sharing), or credential operations.
73
74### False positive analysis
75
76- First-time legitimate VPN or hosting egress per identity produces a single alert per ASN until the term ages out of the window.
77- **Datacamp (60068), M247 (9009), and Vultr (20473)** are especially noisy; consider dropping them locally if alerts exceed capacity.
78- **31173 Services AB (39351)** and **Crea Nova (51765, 204187)** are legitimate hosting providers; only escalation-worthy when paired with unexpected identities or follow-on impact.
79
80### Response and remediation
81
82- If unexpected, rotate keys, revoke sessions, and tighten IAM; add exceptions only after documented approval.
83
84### Additional information
85
86- [CloudTrail userIdentity](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-event-reference-user-identity.html)
87- [BGP / ASN lookup](https://bgp.tools/) (third-party) for validating AS registrations
88"""
89references = [
90 "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-event-reference.html",
91 "https://attack.mitre.org/techniques/T1526/",
92 "https://github.com/bountyyfi/bad-asn-list/blob/main/all.txt"
93]
94risk_score = 47
95rule_id = "e3c7a891-4b2d-4e8c-a1f0-9d8e7c6b5a4d"
96severity = "medium"
97tags = [
98 "Domain: Cloud",
99 "Domain: Identity",
100 "Data Source: AWS",
101 "Data Source: Amazon Web Services",
102 "Data Source: AWS CloudTrail",
103 "Use Case: Threat Detection",
104 "Tactic: Discovery",
105 "Resources: Investigation Guide",
106]
107timestamp_override = "event.ingested"
108type = "new_terms"
109
110query = '''
111event.dataset: "aws.cloudtrail"
112 and event.outcome: "success"
113 and aws.cloudtrail.user_identity.arn:(* and not *AWSServiceRoleForConfig*)
114 and not aws.cloudtrail.user_identity.type: "AWSService"
115 and event.provider: (
116 "sts.amazonaws.com" or
117 "iam.amazonaws.com" or
118 "s3.amazonaws.com" or
119 "ec2.amazonaws.com" or
120 "lambda.amazonaws.com" or
121 "rds.amazonaws.com" or
122 "dynamodb.amazonaws.com" or
123 "kms.amazonaws.com" or
124 "cloudtrail.amazonaws.com"
125 )
126 and event.action: (
127 "GetCallerIdentity" or
128 "ListUsers" or
129 "ListRoles" or
130 "ListAccessKeys" or
131 "GetAccountSummary" or
132 "ListAccountAliases" or
133 "ListGroups" or
134 "ListMFADevices" or
135 "ListBuckets" or
136 "DescribeInstances" or
137 "DescribeRegions" or
138 "DescribeVpcs" or
139 "DescribeSecurityGroups" or
140 "ListFunctions" or
141 "DescribeDBInstances" or
142 "DescribeDBSnapshots" or
143 "ListTables" or
144 "ListKeys" or
145 "ListAliases" or
146 "DescribeTrails" or
147 "LookupEvents"
148 )
149 and source.as.number: (
150 216025 or
151 57138 or
152 207137 or
153 212238 or
154 199218 or
155 209103 or
156 209854 or
157 141039 or
158 147049 or
159 53314 or
160 60068 or
161 9009 or
162 20473 or
163 63949 or
164 39351 or
165 51765 or
166 204187 or
167 29066 or
168 206092
169 )
170'''
171
172[rule.investigation_fields]
173field_names = [
174 "@timestamp",
175 "user.name",
176 "user_agent.original",
177 "source.ip",
178 "source.as.number",
179 "source.as.organization.name",
180 "aws.cloudtrail.user_identity.arn",
181 "aws.cloudtrail.user_identity.type",
182 "aws.cloudtrail.user_identity.access_key_id",
183 "event.provider",
184 "event.action",
185 "event.outcome",
186 "cloud.account.id",
187 "cloud.region",
188]
189
190[[rule.threat]]
191framework = "MITRE ATT&CK"
192
193[[rule.threat.technique]]
194id = "T1526"
195name = "Cloud Service Discovery"
196reference = "https://attack.mitre.org/techniques/T1526/"
197
198[[rule.threat.technique]]
199id = "T1580"
200name = "Cloud Infrastructure Discovery"
201reference = "https://attack.mitre.org/techniques/T1580/"
202
203[rule.threat.tactic]
204id = "TA0007"
205name = "Discovery"
206reference = "https://attack.mitre.org/tactics/TA0007/"
207
208[rule.new_terms]
209field = "new_terms_fields"
210value = ["source.as.number", "user.name", "cloud.account.id"]
211[[rule.new_terms.history_window_start]]
212field = "history_window_start"
213value = "now-10d"
Triage and analysis
Investigating AWS Discovery API Calls from VPN ASN for the First Time by Identity
This rule applies a New Terms condition on source.as.number and aws.cloudtrail.user_identity.arn. It fires the first time a specific principal is observed calling discovery-like APIs from an IP geolocated to one of the ASNs in the rule query (within the 10-day history window).
High-signal event.action values (explicit allowlist in the rule query): GetCallerIdentity; IAM ListUsers,
ListRoles, ListAccessKeys, GetAccountSummary, ListAccountAliases, ListGroups, ListMFADevices; S3 ListBuckets;
EC2 DescribeInstances, DescribeRegions, DescribeVpcs, DescribeSecurityGroups; Lambda ListFunctions; RDS
DescribeDBInstances, DescribeDBSnapshots; DynamoDB ListTables; KMS ListKeys, ListAliases; CloudTrail
DescribeTrails, LookupEvents. Clone the rule to add actions (for example ELB or Secrets Manager) if needed.
Curated VPN-oriented ASNs (verify locally) — examples this rule matches (subject to registry and enrichment updates):
| ASN | Commonly associated operator (reference only) |
|---|---|
| 216025 | Mullvad VPN AB |
| 57138 | Mullvad supporting infrastructure |
| 207137 | Tefincom S.A. (NordVPN-related) |
| 212238 | Nord / Nord Security class VPN egress in many datasets |
| 199218 | ProtonVPN |
| 209103 | Proton AG (VPN; confirm in your enrichment source) |
| 209854 | Surfshark Ltd. |
| 141039, 147049 | Packet-style VPN/colocation pools often tied to large VPN footprints |
| 53314 | ExpressVPN-related registration in some registries (often small; validate) |
| 60068 | Datacamp Limited — CDN/hosting; used by several VPN brands and many legitimate workloads (high dual-use) |
| 9009 | M247 Ltd — colocation and connectivity; common VPN/proxy exit (high dual-use) |
| 20473 | Choopa / Vultr (The Constant Company) — VPS; frequent VPN exit and automation (high dual-use) |
| 63949 | Linode LLC (Akamai cloud) — VPS; VPN exits and dev workloads (dual-use) |
| 39351 | 31173 Services AB (Sweden) — colocation/hosting; cited in TeamPCP-related reporting (dual-use). Not the same as AS31173 (unrelated Ukrainian ISP). |
| 51765 | Oy Crea Nova Hosting Solution Ltd (Finland) — hosting; cited in TeamPCP-related reporting (dual-use) |
| 204187 | Oy Crea Nova Hosting Solution Ltd — related network under the same operator (dual-use) |
Other ASNs sometimes seen for VPN or reseller egress (not in this rule by default) include 16276 (OVH), 14061 (DigitalOcean), 24940 (Hetzner), 51167 (Contabo), and 49453 (Global Layer). Add them only if your baseline shows manageable false-positive volume.
Possible investigation steps
- Confirm
aws.cloudtrail.user_identity.arn,aws.cloudtrail.user_identity.type, andaws.cloudtrail.user_identity.access_key_id. - Review
event.actionandevent.providerin the alert; several distinct allowlisted actions from the same session suggest broader enumeration. - Compare
source.ip,source.as.organization.name, andsource.as.numberagainst your asset inventory and approved remote-access patterns. - Hunt ±30 minutes for privilege changes, data access (
GetObject, snapshot sharing), or credential operations.
False positive analysis
- First-time legitimate VPN or hosting egress per identity produces a single alert per ASN until the term ages out of the window.
- Datacamp (60068), M247 (9009), and Vultr (20473) are especially noisy; consider dropping them locally if alerts exceed capacity.
- 31173 Services AB (39351) and Crea Nova (51765, 204187) are legitimate hosting providers; only escalation-worthy when paired with unexpected identities or follow-on impact.
Response and remediation
- If unexpected, rotate keys, revoke sessions, and tighten IAM; add exceptions only after documented approval.
Additional information
- CloudTrail userIdentity
- BGP / ASN lookup (third-party) for validating AS registrations
References
Related rules
- AWS Account Discovery By Rare User
- AWS EC2 Role GetCallerIdentity from New Source AS Organization
- AWS S3 Rapid Bucket Posture API Calls from a Single Principal
- AWS AssumeRoleWithWebIdentity from Kubernetes SA and External ASN
- AWS Lateral Movement from Kubernetes SA via AssumeRoleWithWebIdentity