
Incident Response Lab: Azure Storage Breach Containment
Investigate and contain credential abuse against Azure Storage accounts, pivoting from unified audit logs to live containment with Logic Apps and Defender for Cloud.
These home labs are placeholder scenarios while I document the full walkthroughs. The environments, objectives, and tooling reflect my real-world practice runs, and I'm actively expanding the playbooks with screenshots, scripts, and validation data.
Incident Response Lab: Azure Storage Breach Containment
You will relive a real-world credential abuse incident I handled in a production Azure tenant. The goal: piece together how a leaked Shared Access Signature led to data exfiltration, then build an automated containment workflow.
π§© Lab Scenario
- A developer accidentally published a Storage Account connection string in a public repository.
- An attacker enumerated containers and exfiltrated sensitive blobs over 30 minutes.
- Defender for Cloud raised an anomaly but no automated response was configured.
πΊοΈ Phase 1 β Evidence Collection
- Configure Diagnostic Settings in the Storage Account:
bash
az monitor diagnostic-settings create \ --name storage-ir \ --resource $(az storage account show --name --query id -o tsv) \ --logs '[{"category":"StorageRead","enabled":true}]' \ --metrics '[{"category":"Transaction","enabled":true}]' \ --workspace - Run the pre-built KQL notebook
kql/storage_sas_breach.kqlinside Sentinel to load baseline queries. - Export a copy of the unified audit log to your evidence folder (
./evidence/raw).
π Phase 2 β Timeline Reconstruction
Use KQL to rebuild the incident. Focus on three attack milestones.
1. Initial Enumeration
// Enumerate LIST operations per client IP
table("StorageBlobLogs")
| where OperationName == "ListBlob"
| summarize Count = count() by CallerIpAddress, bin(TimeGenerated, 5m)
| order by Count desc
2. Exfiltration Burst
// Identify high-volume downloads per container
StorageBlobLogs
| where OperationName == "GetBlob"
| summarize Downloads = count(), DataOut = sum(TotalIngress) by ContainerName, bin(TimeGenerated, 5m)
| order by Downloads desc
3. Key Enumeration
// Track calls to key listing endpoints
AzureActivity
| where OperationNameValue has_any("ListKeys", "ListAccountSas")
| project TimeGenerated, Caller, CallerIpAddress, OperationNameValue
Capture screenshots or export results for the report archive.
π οΈ Phase 3 β Automatic Containment
- Deploy the containment Logic App with Bicep:
bash
az deployment group create \ --resource-group \ --template-file infra/logicapp-lockkeys.bicep \ --parameters storageAccountName= - Connect Sentinel analytics rule "Storage Account Shared Key Access" to the playbook.
- Test by creating a Shared Access Signature; verify the Logic App rotates keys and disables the SAS within 60 seconds.
π‘οΈ Phase 4 β Hardening & Lessons Learned
- Apply Defender for Storage Prevent policy to block anonymous access.
- Rotate storage account keys and purge any persisted credentials from configuration files.
- Enforce Azure AD authentication for applications instead of account keys.
- Update the Secure Development playbook with pipeline checks for secrets.
π Deliverables
report/timeline.mdincluding the KQL outputs and IoCs.- Logic App deployment screenshot + JSON export.
- Sentinel analytics rule update referencing the containment playbook.
- Ticket template for production hand-off.
Run this lab whenever new engineers join incident response so they absorb both the investigative process and the automation mindset.