Detecting Azure Storage Account Misconfigurations
Overview
Azure Storage accounts are a frequent target for attackers due to misconfigured public access, long-lived SAS tokens, missing encryption, and outdated TLS versions. This skill uses the azure-mgmt-storage Python SDK with StorageManagementClient to enumerate all storage accounts in a subscription, inspect their security properties, list blob containers for public access settings, and generate a risk-scored audit report identifying critical misconfigurations.
When to Use
- When investigating security incidents that require detecting azure storage account misconfigurations
- When building detection rules or threat hunting queries for this domain
- When SOC analysts need structured procedures for this analysis type
- When validating security monitoring coverage for related attack techniques
Detection Gaps & Validation
Where azure-mgmt-storage audits give false assurance:
- Container ACLs override the account flag.
allow_blob_public_access=Falseon the account still leaves containers whosepublic_accessisBlob/Containerexposed — you must enumerateblob_containers.list()and check each container'spublic_access, not justStorageAccount.allow_blob_public_access. minimum_tls_version == Noneon older API versions means the defaultTLS1_0, i.e. non-compliant, not "unknown" — treat null as a finding.- SAS issuance is invisible to this SDK.
StorageManagementClientcannot see account-SAS / user-delegation SAS tokens or their scope/lifetime — that requires Storage Analytics logs or Defender for Storage. network_rule_set.default_action == 'Deny'withbypassincludingAzureServicesstill exposes data to trusted Microsoft services across tenants.require_infrastructure_encryptiondefaults toNone/False— absence is not "double-encrypted."
Validate: assert the service principal holds Reader on every target subscription (a mis-scoped SP makes storage_accounts.list() return empty silently, faking a clean result); cross-check one supposedly private container with an anonymous GET .../container?restype=container&comp=list (200 + XML listing = real exposure).
Prerequisites
- Python 3.9+ with
azure-mgmt-storage,azure-identity - Azure service principal with Reader role on target subscription
- Environment variables: AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_CLIENT_SECRET, AZURE_SUBSCRIPTION_ID
Key Detection Areas
- Public blob access —
allow_blob_public_accessenabled on storage account or individual containers set to Blob/Container access level - HTTPS enforcement —
enable_https_traffic_onlydisabled, allowing unencrypted HTTP traffic - Minimum TLS version — accounts accepting TLS 1.0 or TLS 1.1 instead of minimum TLS 1.2
- Encryption at rest — storage service encryption not enabled or missing customer-managed keys
- Network rules — default action set to Allow instead of Deny, exposing storage to all networks
- SAS token risks — account-level SAS with overly broad permissions or excessive lifetime
Output
JSON report with per-account findings, severity ratings (Critical/High/Medium/Low), and remediation recommendations aligned with CIS Azure Benchmark controls.