Detects Azure storage account misconfigurations including public blob containers, missing encryption, broad SAS tokens, disabled logging, and network access violations using Azure CLI, PowerShell, and Microsoft Defender for Storage. Use for security audits, compliance, or data exposure investigations.
npx claudepluginhub killvxk/cybersecurity-skills-zhThis skill uses the workspace's default tool permissions.
- 对订阅中的 Azure 存储账户进行安全审计时
Detects Azure Storage misconfigurations like public blob access, missing encryption, permissive SAS tokens, disabled logging, and network violations using Azure CLI, PowerShell, and Defender for Storage.
Detects misconfigured Azure Storage accounts including public blob containers, missing encryption, permissive SAS tokens, disabled logging, and network violations using Azure CLI, PowerShell, and Defender for Storage. For security audits and compliance.
Audits Azure Blob and ADLS storage accounts for public access exposure, weak/long SAS tokens, missing encryption, disabled HTTPS-only traffic, and outdated TLS using azure-mgmt-storage Python SDK.
Share bugs, ideas, or general feedback.
不适用于:Azure SQL 或 Cosmos DB 安全审计(使用专用数据库安全工具)、存储操作的实时威胁检测(使用 Defender for Storage),或在不做相应调整的情况下对 Azure Files 或 Data Lake Gen2 进行专项审计。
az login 完成认证,具备读者和存储账户贡献者角色Install-Module Az.Storage)列出跨订阅的所有存储账户,评估其基线安全设置。
# 列出所有订阅的存储账户
az storage account list \
--query "[].{Name:name, ResourceGroup:resourceGroup, Location:location, Kind:kind, Sku:sku.name, HttpsOnly:enableHttpsTrafficOnly, MinTLS:minimumTlsVersion, PublicAccess:allowBlobPublicAccess}" \
-o table
# 使用 Resource Graph 进行跨订阅枚举
az graph query -q "
Resources
| where type == 'microsoft.storage/storageaccounts'
| project name, resourceGroup, subscriptionId, location,
properties.allowBlobPublicAccess,
properties.enableHttpsTrafficOnly,
properties.minimumTlsVersion,
properties.networkAcls.defaultAction
" -o table
识别允许匿名公开访问 blob 数据的存储账户和容器。
# 检查每个存储账户的公开 blob 访问设置
for account in $(az storage account list --query "[].name" -o tsv); do
public=$(az storage account show --name "$account" --query "allowBlobPublicAccess" -o tsv)
echo "$account: allowBlobPublicAccess=$public"
done
# 列出已设置公开访问级别的容器
for account in $(az storage account list --query "[?allowBlobPublicAccess==true].name" -o tsv); do
key=$(az storage account keys list --account-name "$account" --query "[0].value" -o tsv)
echo "=== $account ==="
az storage container list \
--account-name "$account" \
--account-key "$key" \
--query "[?properties.publicAccess!='off' && properties.publicAccess!=null].{Container:name, PublicAccess:properties.publicAccess}" \
-o table 2>/dev/null
done
# 测试对已发现公开容器的匿名访问
curl -s "https://ACCOUNT.blob.core.windows.net/CONTAINER?restype=container&comp=list" | head -50
检查存储账户是否对所有网络开放,还是限制在特定 VNet 或 IP 范围内。
# 查找默认网络操作设置为 Allow(对所有网络开放)的存储账户
az storage account list \
--query "[?networkRuleSet.defaultAction=='Allow'].{Name:name, DefaultAction:networkRuleSet.defaultAction, VNetRules:networkRuleSet.virtualNetworkRules}" \
-o table
# 详细的网络规则审计
for account in $(az storage account list --query "[].name" -o tsv); do
echo "=== $account ==="
az storage account show --name "$account" \
--query "{DefaultAction:networkRuleSet.defaultAction, IPRules:networkRuleSet.ipRules[*].ipAddressOrRange, VNetRules:networkRuleSet.virtualNetworkRules[*].virtualNetworkResourceId, Bypass:networkRuleSet.bypass}" \
-o json
done
# 查找具有私有端点的存储账户
az network private-endpoint list \
--query "[?privateLinkServiceConnections[0].groupIds[0]=='blob'].{Name:name, Storage:privateLinkServiceConnections[0].privateLinkServiceId}" \
-o table
确保所有存储账户使用静态加密,并采用适当的密钥管理方式(Microsoft 管理的密钥或客户管理的密钥)。
# 检查所有存储账户的加密配置
for account in $(az storage account list --query "[].name" -o tsv); do
echo "=== $account ==="
az storage account show --name "$account" \
--query "{Encryption:encryption.services, KeySource:encryption.keySource, KeyVaultUri:encryption.keyVaultProperties.keyVaultUri, InfraEncryption:encryption.requireInfrastructureEncryption}" \
-o json
done
# 查找未启用基础设施加密(双重加密)的账户
az storage account list \
--query "[?encryption.requireInfrastructureEncryption!=true].{Name:name, KeySource:encryption.keySource}" \
-o table
# 检查 TLS 版本低于 1.2 的账户
az storage account list \
--query "[?minimumTlsVersion!='TLS1_2'].{Name:name, TLS:minimumTlsVersion}" \
-o table
识别权限过于宽泛的 SAS 令牌,并检查访问密钥使用模式。
# 检查存储账户密钥的上次轮换时间
for account in $(az storage account list --query "[].name" -o tsv); do
echo "=== $account ==="
az storage account keys list \
--account-name "$account" \
--query "[].{KeyName:keyName, CreationTime:creationTime}" \
-o table
done
# 检查存储账户是否允许共享密钥访问(应禁用,改用仅 AAD)
az storage account list \
--query "[].{Name:name, AllowSharedKeyAccess:allowSharedKeyAccess}" \
-o table
# 审查容器上的存储访问策略(SAS 治理)
for account in $(az storage account list --query "[].name" -o tsv); do
key=$(az storage account keys list --account-name "$account" --query "[0].value" -o tsv 2>/dev/null)
for container in $(az storage container list --account-name "$account" --account-key "$key" --query "[].name" -o tsv 2>/dev/null); do
policies=$(az storage container policy list --container-name "$container" --account-name "$account" --account-key "$key" 2>/dev/null)
[ -n "$policies" ] && echo "$account/$container: $policies"
done
done
验证是否启用了存储分析日志记录和 Azure Monitor 诊断设置。
# 检查存储账户的诊断设置
for account in $(az storage account list --query "[].name" -o tsv); do
rg=$(az storage account show --name "$account" --query "resourceGroup" -o tsv)
echo "=== $account ==="
az monitor diagnostic-settings list \
--resource "/subscriptions/$(az account show --query id -o tsv)/resourceGroups/$rg/providers/Microsoft.Storage/storageAccounts/$account" \
--query "[].{Name:name, Logs:logs[*].category, Metrics:metrics[*].category}" \
-o json 2>/dev/null || echo " 未配置诊断设置"
done
# 检查 blob 服务日志记录属性
for account in $(az storage account list --query "[].name" -o tsv); do
key=$(az storage account keys list --account-name "$account" --query "[0].value" -o tsv 2>/dev/null)
az storage logging show \
--account-name "$account" \
--account-key "$key" \
--services b 2>/dev/null
done
| 术语 | 定义 |
|---|---|
| Blob 公开访问(Blob Public Access) | 存储账户设置,允许匿名读取 blob 容器及其内容,无需身份验证 |
| 共享访问签名(Shared Access Signature) | 带有嵌入式身份验证令牌的有时限 URI,授予对 Azure 存储资源的委托访问权限和特定权限 |
| 网络 ACL 默认操作(Network ACL Default Action) | 存储防火墙设置,决定是否默认允许或拒绝流量,特定 IP 和 VNet 可设为例外 |
| 客户管理的密钥(Customer-Managed Key) | 存储在 Azure Key Vault 中、由客户控制的加密密钥,用于存储加密而不是使用 Microsoft 管理的密钥 |
| 存储访问策略(Stored Access Policy) | 容器上命名的策略,定义 SAS 权限、起止时间,可独立撤销而不影响单个 SAS 令牌 |
| Defender for Storage | Microsoft Defender 计划,为异常存储访问模式、恶意软件上传和数据泄露提供威胁检测 |
场景背景:开发人员为 Web 应用创建存储账户,并启用 blob 公开访问以提供静态文件服务。他们不小心将 API 密钥和数据库连接字符串存储在可公开访问的容器中。
方法:
az storage account list 过滤 allowBlobPublicAccess=trueblob 或 container 的容器allowBlobPublicAccess 设置为 false常见陷阱:立即禁用 blob 公开访问会破坏公开提供内容的应用程序。应与开发团队协调,在禁用公开访问前先实施 Azure CDN。密钥轮换前生成的 SAS 令牌在过期前仍然有效,除非重新生成底层存储密钥。
Azure 存储安全审计报告
======================================
订阅: 生产环境(SUB-ID)
评估日期: 2026-02-23
已审计存储账户: 24 个
严重发现:
[STOR-001] 已启用公开 Blob 访问
账户: webapp-static-prod
容器: uploads(PublicAccess: blob)
风险: 匿名用户可读取容器中的所有 blob
内容: 1,247 个文件,包含 .env 和 config.json
修复建议: 禁用 allowBlobPublicAccess,改用带 SAS 的 Azure CDN
[STOR-002] 存储账户对所有网络开放
账户: data-lake-analytics
默认操作: Allow(无网络限制)
风险: 可从任何网络(包括互联网)访问
修复建议: 将默认操作设置为 Deny,添加 VNet 规则
摘要:
已启用公开 blob 访问: 3 / 24
对所有网络开放: 8 / 24
缺少基础设施加密: 12 / 24
TLS 版本低于 1.2: 2 / 24
未启用诊断日志: 10 / 24
已启用共享密钥访问: 18 / 24
密钥未在 90 天内轮换: 14 / 24