Azure Storage Anonymous Blob Access to Unusual Resource
Identifies the first time an Azure Storage resource receives an anonymous data-plane read (GetBlob and related Get or List operations). Anonymous requests are used to probe public containers and to test stolen blob URLs before a SAS is appended. First-seen resource ID keeps volume down while still covering WireServer-related probes of status or extension blobs.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2026/08/17"
3integration = ["azure"]
4maturity = "production"
5updated_date = "2026/09/18"
6
7[rule]
8author = ["Elastic"]
9description = """
10Identifies the first time an Azure Storage resource receives an anonymous data-plane read (GetBlob and related Get or
11List operations). Anonymous requests are used to probe public containers and to test stolen blob URLs before a SAS is
12appended. First-seen resource ID keeps volume down while still covering WireServer-related probes of status or extension
13blobs.
14"""
15false_positives = [
16 """
17 Intentionally public containers (static websites, public datasets) generate anonymous GetBlob and ListBlobs.
18 Baseline those storage accounts and exclude `azure.resource.id` after review.
19 """,
20 """
21 Internet-wide scanners will produce first-seen anonymous access on newly created or newly logged accounts. Confirm
22 whether the account is meant to be public.
23 """,
24]
25from = "now-9m"
26index = ["logs-azure.platformlogs-*"]
27language = "kuery"
28license = "Elastic License v2"
29name = "Azure Storage Anonymous Blob Access to Unusual Resource"
30note = """## Triage and analysis
31
32### Investigating Azure Storage Anonymous Blob Access to Unusual Resource
33
34StorageRead platform logs record `AuthenticationType` as Anonymous when no SAS, OAuth, or account key is presented.
35A first-seen `azure.resource.id` (typically the blob service
36`/subscriptions/.../storageAccounts/<account>/blobServices/default`) means this resource has not had anonymous Get or
37List traffic in the history window.
38
39WireServer SAS-replay chains often start with an anonymous GetBlob (HTTP 409/403) against the same object, then a
40SAS 200. This rule does not require guest-agent path strings; those lab container names are not production
41observables.
42
43`source.ip` is often empty. Use `source.address` (`ip:port`).
44
45### Possible investigation steps
46
47- Review `event.action`, `azure.platformlogs.statusCode`, and `azure.platformlogs.uri`.
48- HTTP 200 with Anonymous means the container or blob is publicly readable. HTTP 409/403 is a probe.
49- Identify the account from `azure.resource.id` / `azure.resource.name` and check whether public access is intended.
50- Search for SAS-authenticated GetBlob to the same account from the same source shortly after.
51- If the URI contains `/$system/` or `md-hdd-`, correlate with WireServer access on VMs in the subscription.
52
53### False positive analysis
54
55- Public blob websites and CDN origins. Exclude the `azure.resource.id` for approved public accounts.
56- New accounts that enable StorageRead for the first time will alert on the first scanner hit.
57
58### Response and remediation
59
60- Disable anonymous public access on accounts that should be private.
61- If a follow-on SAS read exists, revoke that SAS and review how the URL was obtained.
62- Keep StorageRead diagnostic logs enabled on storage accounts of interest.
63"""
64references = [
65 "https://learn.microsoft.com/en-us/azure/azure-monitor/reference/tables/storagebloblogs",
66 "https://learn.microsoft.com/en-us/azure/storage/blobs/anonymous-read-access-prevent",
67 "https://cybercx.com.au/blog/azure-ssrf-metadata/",
68 "https://www.netspi.com/blog/technical-blog/cloud-pentesting/decrypting-vm-extension-settings-with-azure-wireserver/",
69]
70risk_score = 47
71rule_id = "eabaf807-e710-4f0f-8943-8d1b436d834a"
72setup = """#### Required Azure Storage Diagnostic Logs
73
74Enable StorageRead diagnostic logs on Azure Storage Accounts and stream them to the Event Hub used by the Azure
75integration. Anonymous vs SAS is `azure.platformlogs.identity.type`.
76"""
77severity = "medium"
78tags = [
79 "Domain: Cloud",
80 "Data Source: Azure",
81 "Data Source: Azure Platform Logs",
82 "Platform: Azure",
83 "Service: Azure Storage",
84 "Use Case: Threat Detection",
85 "Tactic: Discovery",
86 "Tactic: Collection",
87 "Resources: Investigation Guide",
88 "Rule Type: New Terms",
89]
90timestamp_override = "event.ingested"
91type = "new_terms"
92
93query = '''
94data_stream.dataset: azure.platformlogs and
95 azure.platformlogs.identity.type: Anonymous and
96 event.action: (
97 GetBlob or GetBlobMetadata or GetBlobProperties or GetBlockList or
98 GetPageRanges or QueryBlobContents or ListBlobs or
99 GetContainerProperties or GetContainerMetadata or GetContainerAcl
100 )
101'''
102
103
104[[rule.threat]]
105framework = "MITRE ATT&CK"
106[[rule.threat.technique]]
107id = "T1580"
108name = "Cloud Infrastructure Discovery"
109reference = "https://attack.mitre.org/techniques/T1580/"
110
111
112[rule.threat.tactic]
113id = "TA0007"
114name = "Discovery"
115reference = "https://attack.mitre.org/tactics/TA0007/"
116[[rule.threat]]
117framework = "MITRE ATT&CK"
118[[rule.threat.technique]]
119id = "T1530"
120name = "Data from Cloud Storage"
121reference = "https://attack.mitre.org/techniques/T1530/"
122
123
124[rule.threat.tactic]
125id = "TA0009"
126name = "Collection"
127reference = "https://attack.mitre.org/tactics/TA0009/"
128
129[rule.new_terms]
130field = "new_terms_fields"
131value = ["azure.resource.id"]
132[[rule.new_terms.history_window_start]]
133field = "history_window_start"
134value = "now-7d"
Triage and analysis
Investigating Azure Storage Anonymous Blob Access to Unusual Resource
StorageRead platform logs record AuthenticationType as Anonymous when no SAS, OAuth, or account key is presented.
A first-seen azure.resource.id (typically the blob service
/subscriptions/.../storageAccounts/<account>/blobServices/default) means this resource has not had anonymous Get or
List traffic in the history window.
WireServer SAS-replay chains often start with an anonymous GetBlob (HTTP 409/403) against the same object, then a SAS 200. This rule does not require guest-agent path strings; those lab container names are not production observables.
source.ip is often empty. Use source.address (ip:port).
Possible investigation steps
- Review
event.action,azure.platformlogs.statusCode, andazure.platformlogs.uri. - HTTP 200 with Anonymous means the container or blob is publicly readable. HTTP 409/403 is a probe.
- Identify the account from
azure.resource.id/azure.resource.nameand check whether public access is intended. - Search for SAS-authenticated GetBlob to the same account from the same source shortly after.
- If the URI contains
/$system/ormd-hdd-, correlate with WireServer access on VMs in the subscription.
False positive analysis
- Public blob websites and CDN origins. Exclude the
azure.resource.idfor approved public accounts. - New accounts that enable StorageRead for the first time will alert on the first scanner hit.
Response and remediation
- Disable anonymous public access on accounts that should be private.
- If a follow-on SAS read exists, revoke that SAS and review how the URL was obtained.
- Keep StorageRead diagnostic logs enabled on storage accounts of interest.
References
Related rules
- Azure Storage Account Blob Public Access Enabled
- Azure Storage Blob Retrieval via AzCopy
- Azure AD Graph Access with Unusual Client and User
- Azure AKS Potential API Enumeration by User
- Azure AKS Suspicious Self-Subject Review by Service Account or Node Identity