RULE 20 Storage Immutability Removed
Query
// Rule : Azure - Storage Immutability Policy or Legal Hold Removed
// Severity: High
// Tactics : Impact, DefenseEvasion
// MITRE : T1490
// Freq : PT1H Period: PT2H
//==========================================================================================
// Blob immutability policies and legal holds are the primary anti-ransomware / anti-tamper
// guardrails in Azure Storage. Their removal (or unlock of a locked-mode policy) is a
// pre-cursor to ransomware encryption / mass-delete campaigns and to insider evidence
// destruction. This complements RULE-14 (NSG delete) and RULE-11 (mass delete) by covering
// the specific "inhibit system recovery" (T1490) TTP.
//
// Operations covered (AzureActivity):
// * MICROSOFT.STORAGE/STORAGEACCOUNTS/BLOBSERVICES/CONTAINERS/IMMUTABILITYPOLICIES/DELETE
// * MICROSOFT.STORAGE/STORAGEACCOUNTS/BLOBSERVICES/CONTAINERS/IMMUTABILITYPOLICIES/EXTEND/ACTION
// (extend/action with shorter retention == de-facto weakening)
// * MICROSOFT.STORAGE/STORAGEACCOUNTS/BLOBSERVICES/CONTAINERS/LEGALHOLDS/CLEAR/ACTION
// * MICROSOFT.STORAGE/STORAGEACCOUNTS/BLOBSERVICES/CONTAINERS/DELETE (soft-delete disabled)
// * MICROSOFT.STORAGE/STORAGEACCOUNTS/DELETE (whole account teardown)
//
// FP mitigations:
// * IaC/pipeline caller patterns excluded (data-lifecycle tools legitimately delete).
// * Azure platform IPs excluded.
// * Success-only.
// * Any single event fires — these operations are inherently high-signal.
let ImmutabilityOps = dynamic([
"MICROSOFT.STORAGE/STORAGEACCOUNTS/BLOBSERVICES/CONTAINERS/IMMUTABILITYPOLICIES/DELETE",
"MICROSOFT.STORAGE/STORAGEACCOUNTS/BLOBSERVICES/CONTAINERS/IMMUTABILITYPOLICIES/EXTEND/ACTION",
"MICROSOFT.STORAGE/STORAGEACCOUNTS/BLOBSERVICES/CONTAINERS/LEGALHOLDS/CLEAR/ACTION",
"MICROSOFT.STORAGE/STORAGEACCOUNTS/BLOBSERVICES/DEFAULT/DELETE"
]);
let KnownIaCPatterns = dynamic(["terraform", "bicep", "pipeline", "github", "pulumi",
"devops", "arm-deployment", "lifecycle"]);
AzureActivity
| where TimeGenerated > ago(2h)
| where ActivityStatusValue =~ "Success"
| where OperationNameValue has_any (ImmutabilityOps)
| where not(tolower(Caller) has_any (KnownIaCPatterns))
| where isnotempty(CallerIpAddress)
| where CallerIpAddress !startswith "168.63." and CallerIpAddress !startswith "169.254."
| extend StorageAccount = tostring(split(ResourceId, "/")[8])
| extend ContainerName = iff(array_length(split(ResourceId, "/")) > 12,
tostring(split(ResourceId, "/")[12]), "")
| extend ActionKind = case(
OperationNameValue has "IMMUTABILITYPOLICIES/DELETE", "ImmutabilityPolicyDeleted",
OperationNameValue has "IMMUTABILITYPOLICIES/EXTEND/ACTION", "ImmutabilityPolicyExtended",
OperationNameValue has "LEGALHOLDS/CLEAR/ACTION", "LegalHoldCleared",
OperationNameValue has "BLOBSERVICES/DEFAULT/DELETE", "BlobServiceSettingsDeleted",
"Other")
| summarize
EventCount = count(),
DistinctActions = dcount(ActionKind),
Actions = make_set(ActionKind, 5),
AffectedContainers = make_set(strcat(StorageAccount, "/", ContainerName), 20),
AffectedAccounts = make_set(StorageAccount, 10),
Operations = make_set(OperationNameValue, 5),
ResourceGroups = make_set(ResourceGroup, 5),
SourceIPs = make_set(CallerIpAddress, 5),
CallerIP = any(CallerIpAddress),
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated)
by Caller, SubscriptionId
| extend
AccountName = tostring(split(Caller, "@")[0]),
AccountUPNSuffix = tostring(split(Caller, "@")[1])Explanation
This query is designed to detect and summarize potentially suspicious activities related to the removal or weakening of security measures on Azure Storage accounts, specifically focusing on immutability policies and legal holds. Here's a simplified breakdown:
-
Purpose: The query aims to identify high-severity actions that could indicate attempts to tamper with or compromise data integrity, such as removing or altering immutability policies or legal holds on Azure Storage accounts. These actions are often precursors to ransomware attacks or insider threats.
-
Monitored Operations: It looks for specific operations in Azure Activity logs, such as:
- Deleting immutability policies.
- Extending immutability policies with shorter retention (considered a weakening action).
- Clearing legal holds.
- Deleting blob service settings.
-
Exclusions: To reduce false positives, the query excludes:
- Operations initiated by known Infrastructure as Code (IaC) tools (e.g., Terraform, Bicep) that might legitimately perform these actions.
- Actions from Azure platform IP addresses.
- Only considers successful operations.
-
Time Frame: The query examines activities within the last 2 hours.
-
Data Extraction: For each detected action, it extracts and summarizes:
- The number and types of actions performed.
- Affected storage accounts and containers.
- Source IP addresses of the callers.
- The time range during which these actions were observed.
-
Output: The results are grouped by the caller and subscription ID, providing details such as:
- The caller's account name and domain.
- A list of distinct actions and affected resources.
- The first and last time the actions were seen.
Overall, this query helps security teams quickly identify and investigate potential security incidents involving Azure Storage accounts, focusing on actions that could compromise data protection mechanisms.
Details

David Alonso
Released: July 27, 2026
Tables
Keywords
Operators
MITRE Techniques