Detection rules › Kusto
Microsoft Entra ID Hybrid Health AD FS Service Delete
This detection uses AzureActivity logs (Administrative category) to identify the deletion of an Microsoft Entra ID Hybrid Health AD FS service instance in a tenant. A threat actor can create a new AD Health ADFS service and create a fake server to spoof AD FS signing logs. The health AD FS service can then be deleted after it is no longer needed via HTTP requests to Azure. More information is available in this blog https://o365blog.com/post/hybridhealthagent/
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Defense Impairment | T1578.003 Modify Cloud Compute Infrastructure: Delete Cloud Instance |
Event coverage
Rules detecting the same action
Other rules on this platform that filter on the same API call or operation.
- Azure Active Directory Hybrid Health AD FS New Server (Sigma)
- Azure Active Directory Hybrid Health AD FS Service Delete (Sigma)
- Azure Subscription Permission Elevation Via AuditLogs (Sigma)
- Detect Custom Script or Run Command deployment by risky user (Kusto)
- Microsoft Entra ID Hybrid Health AD FS New Server (Kusto)
- Microsoft Entra ID Hybrid Health AD FS Suspicious Application (Kusto)
- NRT Microsoft Entra ID Hybrid Health AD FS New Server (Kusto)
Rule body kusto
id: 86a036b2-3686-42eb-b417-909fc0867771
name: Microsoft Entra ID Hybrid Health AD FS Service Delete
description: |
'This detection uses AzureActivity logs (Administrative category) to identify the deletion of an Microsoft Entra ID Hybrid Health AD FS service instance in a tenant.
A threat actor can create a new AD Health ADFS service and create a fake server to spoof AD FS signing logs.
The health AD FS service can then be deleted after it is no longer needed via HTTP requests to Azure.
More information is available in this blog https://o365blog.com/post/hybridhealthagent/'
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: AzureActivity
dataTypes:
- AzureActivity
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
- DefenseEvasion
relevantTechniques:
- T1578.003
tags:
- SimuLand
query: |
AzureActivity
| where CategoryValue =~ 'Administrative'
| where ResourceProviderValue =~ 'Microsoft.ADHybridHealthService'
| where _ResourceId has 'AdFederationService'
| where OperationNameValue =~ 'Microsoft.ADHybridHealthService/services/delete'
| extend claimsJson = parse_json(Claims)
| extend AppId = tostring(claimsJson.appid), AccountName = tostring(claimsJson.name), Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])
| project-away claimsJson
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: Caller
- identifier: Name
columnName: Name
- identifier: UPNSuffix
columnName: UPNSuffix
- entityType: IP
fieldMappings:
- identifier: Address
columnName: CallerIpAddress
version: 2.0.3
kind: Scheduled
Stages and Predicates
Stage 1: source
AzureActivity
Stage 2: where
| where CategoryValue =~ 'Administrative'
Stage 3: where
| where ResourceProviderValue =~ 'Microsoft.ADHybridHealthService'
Stage 4: where
| where _ResourceId has 'AdFederationService'
Stage 5: where
| where OperationNameValue =~ 'Microsoft.ADHybridHealthService/services/delete'
Stage 6: extend
| extend claimsJson = parse_json(Claims)
Stage 7: extend
| extend AppId = tostring(claimsJson.appid), AccountName = tostring(claimsJson.name), Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])
Stage 8: project-away
| project-away claimsJson
Indicators
Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.
| Field | Kind | Values |
|---|---|---|
CategoryValue | eq |
|
OperationNameValue | eq |
|
ResourceProviderValue | eq |
|
_ResourceId | match |
|
Output fields
Fields the rule emits when it matches. Chronicle authors list these in the outcome block; they appear on the detection and $risk_score drives alerting. Sentinel / Defender XDR rules build them up through project / summarize / extend stages. Sentinel maps these into alert fields via entityMappings and customDetails; Defender XDR custom detections surface them as alert fields directly.
| Field | Source |
|---|---|
AccountName | extend |
AppId | extend |
Name | extend |
UPNSuffix | extend |