Adversaries may remove Azure Diagnostic settings from a resource to prevent monitoring and evade detection of their activities. SOC teams should proactively hunt for this behavior as it could indicate an attempt to suppress forensic evidence or prepare for a subsequent malicious action.
KQL Query
AzureActivity
| where OperationNameValue =~ "MICROSOFT.INSIGHTS/DIAGNOSTICSETTINGS/DELETE"
| summarize
TimeGenerated = arg_max(TimeGenerated, Properties),
ActivityStatusValue = make_set(ActivityStatusValue, 5),
take_any(Caller, CallerIpAddress, OperationName, ResourceGroup, Resource)
by CorrelationId, _ResourceId, OperationNameValue
| extend ResourceHierarchy = split(_ResourceId, "/")
| extend MonitoredResourcePath = strcat_array(array_slice(ResourceHierarchy, 0, array_length(ResourceHierarchy)-5), "/")
| join kind=leftanti (
AzureActivity
| where OperationNameValue !~ "MICROSOFT.INSIGHTS/DIAGNOSTICSETTINGS/DELETE" and OperationNameValue endswith "/DELETE" and ActivityStatusValue has_any ("Success", "Succeeded")
| project _ResourceId
) on $left.MonitoredResourcePath == $right._ResourceId
| extend
Name = iif(Caller has "@", tostring(split(Caller, "@")[0]), ""),
UPNSuffix = iif(Caller has "@", tostring(split(Caller, "@")[1]), ""),
AadUserId = iif(Caller has "@", "", Caller)
| project TimeGenerated, Caller, CallerIpAddress, OperationNameValue, OperationName, ActivityStatusValue, ResourceGroup, MonitoredResourcePath, Resource, Properties, Name, UPNSuffix, AadUserId, _ResourceId, CorrelationId
id: 6e95aef3-a1e0-4063-8e74-cd59aa59f245
name: Azure Diagnostic settings removed from a resource
description: |
'This query looks for diagnostic settings that are removed from a resource.
This could indicate an attacker or malicious internal trying to evade detection before malicious act is performed.
If the diagnostic settings are being deleted as part of a parent resource deletion, the event is ignores.'
severity: Medium
requiredDataConnectors:
- connectorId: AzureActivity
dataTypes:
- AzureActivity
queryFrequency: 1h
queryPeriod: 2h
triggerOperator: gt
triggerThreshold: 0
tactics:
- DefenseEvasion
relevantTechniques:
- T1562.008
query: |
AzureActivity
| where OperationNameValue =~ "MICROSOFT.INSIGHTS/DIAGNOSTICSETTINGS/DELETE"
| summarize
TimeGenerated = arg_max(TimeGenerated, Properties),
ActivityStatusValue = make_set(ActivityStatusValue, 5),
take_any(Caller, CallerIpAddress, OperationName, ResourceGroup, Resource)
by CorrelationId, _ResourceId, OperationNameValue
| extend ResourceHierarchy = split(_ResourceId, "/")
| extend MonitoredResourcePath = strcat_array(array_slice(ResourceHierarchy, 0, array_length(ResourceHierarchy)-5), "/")
| join kind=leftanti (
AzureActivity
| where OperationNameValue !~ "MICROSOFT.INSIGHTS/DIAGNOSTICSETTINGS/DELETE" and OperationNameValue endswith "/DELETE" and ActivityStatusValue has_any ("Success", "Succeeded")
| project _ResourceId
) on $left.MonitoredResourcePath == $right._ResourceId
| extend
Name = iif(Caller has "@", tostring(split(Caller, "@")[0]), ""),
UPNSuffix = iif(Caller has "@", tostring(split(Caller, "@")[1]), ""),
AadUserId = iif(Caller has "@", "", Caller)
| project TimeGenerated, Caller, CallerIpAddress, OperationNameValue, OperationName, ActivityStatusValue, ResourceGroup, MonitoredResourcePath, Resource, Properties, Name, UPNSuffix, AadUserId, _ResourceId, CorrelationId
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: Caller
- identifier: Name
columnName: Name
- identifier: UPNSuffix
columnName: UPNSuffix
- entityType: Account
fieldMappings:
- identifier: AadUserId
columnName: AadUserId
- entityType: IP
fieldMappings:
- identifier: Address
columnName: CallerIpAddress
version: 1.0.3
kind: Scheduled
metadata:
source:
kind: Community
author:
name: KennethMLdk
support:
tier: Community
categories:
domains: [ "Security - Others", "Platform" ]
| Sentinel Table | Notes |
|---|---|
AzureActivity | Ensure this data connector is enabled |
Scenario: Admin removes diagnostic settings for routine maintenance
Filter/Exclusion: Exclude events where the action is performed by a known admin group (e.g., Azure Active Directory Administrators) or during scheduled maintenance windows.
Example Filter: action.by.serviceprincipal.objectid IN ('admin-object-id') OR activity.log.properties.eventCategory = 'Administrative'
Scenario: Automated script or job configured to clean up diagnostic settings
Filter/Exclusion: Exclude actions initiated by a known automation tool or service (e.g., Azure DevOps, Azure CLI, or a custom PowerShell script).
Example Filter: activity.log.properties.caller = 'Azure CLI' OR activity.log.properties.caller = 'Azure DevOps'
Scenario: Resource is decommissioned and diagnostic settings are removed as part of cleanup
Filter/Exclusion: Exclude events where the resource is marked for deletion or is in a decommissioned state.
Example Filter: activity.log.properties.resourceType = 'Microsoft.Compute/virtualMachines' AND activity.log.properties.resourceName IN ('decommissioned-vm-name')
Scenario: Diagnostic settings are temporarily disabled for performance tuning
Filter/Exclusion: Exclude actions where the diagnostic settings are disabled for a short period and then re-enabled.
Example Filter: activity.log.properties.eventTimestamp > (current time - 1 hour) AND activity.log.properties.eventTimestamp < (current time)
Scenario: User mistakenly removes diagnostic settings during troubleshooting
Filter/Exclusion: Exclude actions performed by users with low privilege or during troubleshooting sessions.
Example Filter: activity.log.properties.userPrincipalName LIKE '%[email protected]%' OR activity.log.properties.userPrincipalName LIKE '%[email protected]%'