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/08/17"
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]
89timestamp_override = "event.ingested"
90type = "new_terms"
91
92query = '''
93data_stream.dataset: azure.platformlogs and
94 azure.platformlogs.identity.type: Anonymous and
95 event.action: (
96 GetBlob or GetBlobMetadata or GetBlobProperties or GetBlockList or
97 GetPageRanges or QueryBlobContents or ListBlobs or
98 GetContainerProperties or GetContainerMetadata or GetContainerAcl
99 )
100'''
101
102
103[[rule.threat]]
104framework = "MITRE ATT&CK"
105[[rule.threat.technique]]
106id = "T1580"
107name = "Cloud Infrastructure Discovery"
108reference = "https://attack.mitre.org/techniques/T1580/"
109
110
111[rule.threat.tactic]
112id = "TA0007"
113name = "Discovery"
114reference = "https://attack.mitre.org/tactics/TA0007/"
115[[rule.threat]]
116framework = "MITRE ATT&CK"
117[[rule.threat.technique]]
118id = "T1530"
119name = "Data from Cloud Storage"
120reference = "https://attack.mitre.org/techniques/T1530/"
121
122
123[rule.threat.tactic]
124id = "TA0009"
125name = "Collection"
126reference = "https://attack.mitre.org/tactics/TA0009/"
127
128[rule.new_terms]
129field = "new_terms_fields"
130value = ["azure.resource.id"]
131[[rule.new_terms.history_window_start]]
132field = "history_window_start"
133value = "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 AKS Potential API Enumeration by User
- Azure AKS Suspicious Self-Subject Review by Service Account or Node Identity
- Azure WireServer HTTP Request from Unexpected User Agent
- Azure WireServer Unusual Process Connection
- Azure AKS Service Account Token Created via TokenRequest API