Skip to main content
emnode
Compliance

Harden Azure Storage accounts

One capability across Blob, File, Table and Queue: make sure no storage account is reachable from, or shareable with, the public internet, and that nothing it serves travels unencrypted, unless you genuinely intend it.

14 min·10 sections·AZURE

Last reviewed

Hardening storage accounts: the basics

What does an exposed Azure Storage account actually look like?

A storage account is the most data-dense object in an Azure subscription, and exposure shows up in a handful of distinct shapes rather than one setting. Anonymous public read can be left enabled so a container is downloadable without credentials. Secure transfer can be off so the account still answers plain HTTP. The account firewall can be open to all networks instead of restricted to a private endpoint or a known set of addresses. Encryption can rely on the platform key when a regulated workload needs a customer-managed key. Each is its own Defender for Cloud recommendation, but the underlying risk is the same: a store of data that more of the internet can reach, or read in transit, than you meant.

Microsoft Defender for Cloud turns each of these into its own recommendation, which is why one storage-heavy subscription can fail several storage checks at once. 'Storage accounts should prevent anonymous public read access' and 'Secure transfer to storage accounts should be enabled' are the two that close the widest doors, and they pair with private-endpoint, network-restriction and customer-managed-key recommendations to form a single capability. They read as separate problems on the report, but they are one job: close the doors you did not mean to leave open, and encrypt what you serve.

Most of this exposure is drift, not intent. A storage account created before anonymous access was disabled by default, a module that never set secure transfer, a firewall left open because a quick test needed it and nobody closed it again. The work is to find every account that is reachable or readable more widely than intended, decide which handful are public on purpose, route those through a controlled front door such as Azure Front Door, and lock the rest down.

In this lesson you will learn how Azure Storage expresses public reachability and in-transit protection, how to find every over-exposed account in a subscription, and how to lock them down without breaking the few that are public on purpose. The Controls this lesson covers section lists every Defender for Cloud recommendation in this capability, each linking to a deep page with the exact check and a copy-and-paste fix.

Fun fact

The blob that briefed the breach

Misconfigured cloud storage has been behind some of the largest data exposures on record, and Azure Blob containers left open for anonymous read have appeared in their share of them, from leaked recruitment data to exposed internal documents. The pattern is always the same: a container that could be made public was made public by accident, then found by an automated scanner long before anyone noticed. Azure now disables anonymous access by default on new accounts, but every account created before that default still needs to be checked and locked explicitly.

Finding storage exposure across a subscription

Sam is the security lead at a scale-up preparing for its first ISO 27001 audit. Defender for Cloud shows storage findings spread across a dozen accounts in two subscriptions that pre-date the team's current guardrails.

Rather than work the findings one by one, Sam starts by listing which accounts still allow anonymous access and which still accept plain HTTP, so the genuinely public stores can be separated from drift before anything changes.

Start by listing the accounts that still allow anonymous public read. These are the widest-open doors.

$ az storage account list --query "[?allowBlobPublicAccess].{name:name, https:enableHttpsTrafficOnly}" -o table
Name Https
------------------ -------
custexportsprod False
analyticsstaging True
# custexportsprod allows anonymous read AND answers plain HTTP. Close it first.

An account that is both anonymously readable and plain-HTTP is the highest-value target in this group. Fix these first.

How Defender for Cloud decides a storage account is exposeddeep dive

Most storage recommendations resolve to one of three properties on the account. The first is 'allowBlobPublicAccess': when it is true, a container can be set to anonymous read, so the account can serve data without credentials. The second is 'supportsHttpsTrafficOnly': when it is false, the REST endpoints still answer plain HTTP, so requests and any shared access signature token in the URL travel unencrypted. The third is the network rule set: when default action is Allow, the account is reachable from any network rather than restricted to a private endpoint or an approved address range.

Defender for Cloud evaluates these against the Microsoft Cloud Security Benchmark on a periodic cycle, so a fix does not flip the recommendation to Healthy instantly. The control-plane change itself is immediate, but the posture catches up on the next assessment. This matters when you are gathering audit evidence against a deadline.

The strongest position combines the account setting with an Azure Policy backstop: a deny policy on 'allowBlobPublicAccess' and on secure transfer means no individual account can be created in the open state again. Turning those policies on is the difference between checking that nothing is exposed today and guaranteeing that nothing can be exposed tomorrow.

What is the impact of leaving storage exposed?

The direct impact is data exposure. An anonymously readable container is reachable by anyone who finds it, and internet-facing stores are found quickly by automated scanners. An account answering plain HTTP leaks request data and any SAS token in the URL to anyone able to observe the traffic, and a stolen SAS token grants whatever it allows until it expires. The overwhelming majority of storage incidents were accidents: a setting that could be left open was left open by a module or a flag nobody intended.

The second-order impact is blast radius. Every open account and plain-HTTP endpoint is attack surface that has to be defended continuously. Locking storage down shrinks that surface to the handful of front doors you actually operate, which are the ones you can monitor, rate-limit and put a web application firewall in front of.

On the compliance side, every modern framework, ISO 27001, SOC 2, HIPAA, PCI DSS and the UK and EU data-protection regimes, expects evidence that data stores are not publicly readable and that data in transit is encrypted. A passing set of storage recommendations across every subscription is the cheapest and most defensible artefact you can hand an auditor.

How do you lock storage down safely?

Work the capability as one loop rather than chasing individual findings. The order matters: find the legitimate public stores before you start closing things, so you do not take a live service offline.

1. Inventory every account by exposure

List the accounts that allow anonymous public read, that accept plain HTTP, and that have an open network rule set. Treat this inventory as the source of truth, not the Defender finding count, because one account can trigger several recommendations at once.

2. Separate genuine public stores from drift

Most exposure is unintended. For each account, decide whether it is public on purpose. Genuine public content, such as a static site or a public download store, belongs behind Azure Front Door over a private origin, never exposed directly. Everything else is drift and can be closed.

3. Close the doors, highest impact first

Disable anonymous access, require secure transfer, set a minimum TLS version of 1.2, and switch the network default action to Deny with a private endpoint or an approved address range. Prioritise accounts that hold data over empty ones. Each change is a single command per account and takes effect immediately.

4. Ratchet it shut with Azure Policy

Assign deny policies so no new account can be created with anonymous access enabled or secure transfer off, and audit for private-endpoint use. Back this with customer-managed keys for the regulated workloads that need them, so the safe configuration is enforced rather than merely encouraged.

# Close the highest-impact storage exposure first: anonymous read AND plain HTTP.
for acct in $(az storage account list \
    --query "[?allowBlobPublicAccess].name" -o tsv); do
  az storage account update --name "$acct" \
    --allow-blob-public-access false \
    --https-only true \
    --min-tls-version TLS1_2
  echo "$acct: anonymous access disabled, secure transfer required, min TLS 1.2"
done

# Ratchet it shut: deny any future account that allows anonymous access.
az policy assignment create \
  --name deny-anon-blob \
  --policy 13e6c4f1-e83f-4b50-a677-2cf6e2b9c885 \
  --scope "/subscriptions/00000000-0000-0000-0000-000000000000"

Quick quiz

Question 1 of 5

Defender for Cloud shows storage findings across anonymous access, secure transfer and network rules on several accounts. What is the most efficient way to think about them?

You can now treat Azure Storage as one capability rather than a scatter of findings: inventory what is reachable or readable too widely, separate the genuine public stores and route them through a controlled front door, close the rest highest-impact first, and ratchet the estate shut with Azure Policy. The Controls this lesson covers section below links every recommendation in this group to its deep page and fix.

Back to the library

Controls this lesson covers

One capability, many Microsoft Defender for Cloud recommendations. This lesson is the shared playbook; each control below keeps its own deep page with the exact check, severity and a copy-and-paste fix.