Black Shard

Insights3 April 2026

The Azure Storage Account That Was Public All Along

The storage account answered to the whole internet from the day it was created, and nobody had ever been asked to decide otherwise. Why Azure defaults are open windows, and how to close them without breaking production.

Half-raised roller door on a dark warehouse spilling cold cyan light

The window was built open

The cloud data exposure that keeps turning up in Australian environments is not the result of an attack. It is a storage account that was reachable from the entire internet on the day it was created, and stayed that way because nobody was ever asked to decide otherwise. When a public blob container turns up, the language of breach doesn't fit. Nothing was penetrated. There was never a perimeter around that data to begin with.

A default is a decision your vendor made for you, and cloud vendors optimise defaults for onboarding friction, not for your threat model. Every Azure storage account answers on a globally resolvable public hostname the moment it exists. The controls that change that (network rules, anonymous access switches, shared key restrictions) are all opt-in. That is the modern open window: not a control that failed, but a control that was never engaged, sitting in plain view of anyone who cares to look.

How a blob container ends up public

Anonymous blob access in Azure is gated by two switches that have to agree. The account-level property allows or disallows public access outright, and each container then carries its own access level: private, blob, or container. The blob level lets an unauthenticated caller read any object whose URL they know. The container level is worse: it lets them list the container, so they don't need to know a single filename. They ask for the index and the platform hands it over.

Microsoft now creates new accounts with anonymous access disallowed, which is the right call, but accounts created before that change keep whatever setting they were born with, and settings travel silently through infrastructure-as-code templates cloned from old projects. Most Azure estates are not young. A storage account provisioned years ago for a static website or a quick file handoff still holds its original posture, long after everyone who remembers why has moved on.

Discovery costs an attacker almost nothing. Storage account names are globally unique DNS labels, three to twenty-four characters, lowercase letters and numbers only, resolving under blob.core.windows.net. That makes an estate enumerable by wordlist: company name plus prod, backup, data, static, uploads. And every blob URL that ships inside a mobile app, a JavaScript bundle or a shared document confirms an account exists and invites probing of its neighbouring containers.

SAS tokens: delegation without an off switch

Shared access signatures are the second window, and they're subtler because they look like security. A SAS is a bearer credential embedded in a URL. Whoever holds the string is you, from any network, with no further challenge. URLs are the most promiscuous data type in computing: they land in proxy logs, browser histories, referrer headers, support tickets, wiki pages, chat threads and git history. A SAS pasted once to unblock a colleague can outlive the project it served.

The failure pattern is consistent. The token grants read, write, delete and list because working out which permissions were actually needed took effort. It's scoped to the whole account because that option came first in the dialog. And it expires years from now because rotation kept breaking a downstream job. Worst of all, account SAS and ordinary service SAS are signed with the account key, so a single leaked token cannot be revoked on its own. The only lever is rotating the key itself, which invalidates every other token and connection string signed by it, so nobody ever pulls that lever.

The fixes exist in the platform. User delegation SAS is signed with Entra ID credentials rather than the account key, capped at seven days, and revocable. Stored access policies give service SAS a server-side handle you can shorten or revoke without touching the key. Short expiries plus automated reissue beat long expiries plus hope.

The network default is everyone

Storage firewalls default to enabled from all networks. Teams with disciplined hub-and-spoke virtual networks and private endpoints for their compute routinely assume the storage behind an application sits inside that perimeter. It doesn't, unless someone made it so. The account keeps answering on its public endpoint regardless of your network architecture until public network access is explicitly disabled or restricted to selected networks and private endpoints.

Shared key authorisation deserves the same scrutiny. It's enabled by default, and an account key is root on the data plane: it bypasses Entra ID, conditional access, MFA and every role assignment you've curated. Disabling shared key access where workloads permit, and moving services onto managed identities, converts storage authentication from a static-secret problem into an identity problem, which is the problem Azure is actually good at solving.

Finding the open windows

Configuration review from inside the portal is necessary but not sufficient, because the portal tells you what the settings say, not what the internet sees. Audit from both directions: sweep the configuration inside, then verify from outside as an anonymous stranger would.

The logging step below matters most. The difference between an afternoon's hardening and a production incident is knowing which legacy integration is quietly reading a container anonymously at two in the morning.

  • Query Azure Resource Graph across every subscription for accounts that allow public blob access, open network access or shared key authorisation, and treat each hit as a decision to make, not noise to accept.
  • Probe your own blob endpoints from outside your network with no credentials, including container list attempts, and reconcile the results against what the portal claims.
  • Search code, pipelines, wikis and exported tickets for sig= and core.windows.net to surface long-lived SAS tokens already in the wild.
  • Enable diagnostic logging on blob endpoints; the logs record the authentication type of every request, so a few weeks of data shows who genuinely depends on anonymous or key access before you switch anything off.

Close it, then make it stay closed

Sequence the remediation. Observe first, using request logs to map real consumers. Then disallow anonymous access at the account level, restrict public network access, and migrate consumers to managed identities or user delegation SAS with short expiries. If you found leaked tokens, rotate the account keys and absorb the breakage; a key you cannot bring yourself to rotate is a key you must assume is compromised. Finally, apply Azure Policy with deny effects at the management group so the next storage account cannot be created open. Advisory dashboards surface these findings and get ignored; a deny at creation time is the only control that doesn't rely on someone reading a report.

There's a regulatory edge to this in Australia. If an anonymously readable container held personal information, that isn't a hygiene item, it's a potential eligible data breach under the Privacy Act 1988, with the Notifiable Data Breaches scheme's assessment obligations and APP 11's security requirement in play. The question of whether the data was actually accessed is much harder to answer for a resource that was never logging.

The takeaway is a posture, not a checklist: treat every cloud default as an unreviewed decision someone else made about your data, and replace it with an explicit one. Enumerate your own estate from the public internet on a schedule, because that is precisely what other people are doing. That outside-in pass is the first thing we run in an Azure security review, and it finds something more often than anyone likes.

Put a security lead at your table.

Australia-wide, from our Brisbane head office. Someone will contact you as soon as possible.

Open a briefinfo@blackshard.com.au