Detection rules › Kusto
ADFS DKM Master Key Export
Identifies an export of the ADFS DKM Master Key from Active Directory. References: https://blogs.microsoft.com/on-the-issues/2020/12/13/customers-protect-nation-state-cyberattacks/, https://cloud.google.com/blog/topics/threat-intelligence/evasive-attacker-leverages-solarwinds-supply-chain-compromises-with-sunburst-backdoor To understand further the details behind this detection, please review the details in the original PR and subequent PR update to this: https://github.com/Azure/Azure-Sentinel/pull/1562#issue-551542469 https://github.com/Azure/Azure-Sentinel/pull/1512#issue-543053339
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Collection | T1005 Data from Local System |
Event coverage
| Provider | Event | Title |
|---|---|---|
| Security-Auditing | Event ID 4662 | An operation was performed on an object. |
Rule body kusto
id: 18e6a87e-9d06-4a4e-8b59-3469cd49552d
name: ADFS DKM Master Key Export
description: |
'Identifies an export of the ADFS DKM Master Key from Active Directory.
References: https://blogs.microsoft.com/on-the-issues/2020/12/13/customers-protect-nation-state-cyberattacks/,
https://cloud.google.com/blog/topics/threat-intelligence/evasive-attacker-leverages-solarwinds-supply-chain-compromises-with-sunburst-backdoor
To understand further the details behind this detection, please review the details in the original PR and subequent PR update to this:
https://github.com/Azure/Azure-Sentinel/pull/1562#issue-551542469
https://github.com/Azure/Azure-Sentinel/pull/1512#issue-543053339
'
severity: Medium
requiredDataConnectors:
- connectorId: SecurityEvents
dataTypes:
- SecurityEvents
- connectorId: MicrosoftThreatProtection
dataTypes:
- DeviceEvents
- connectorId: WindowsSecurityEvents
dataTypes:
- SecurityEvents
- connectorId: WindowsForwardedEvents
dataTypes:
- WindowsEvent
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
- Collection
relevantTechniques:
- T1005
tags:
- Solorigate
- NOBELIUM
query: |
(union isfuzzy=true
(SecurityEvent
| where EventID == 4662 // You need to create a SACL on the ADFS Policy Store DKM group for this event to be created.
| where ObjectServer == 'DS'
| where OperationType == 'Object Access'
//| where ObjectName contains '<GUID of ADFS Policy Store DKM Group object' This is unique to the domain. Check description for more details.
| where ObjectType contains '5cb41ed0-0e4c-11d0-a286-00aa003049e2' // Contact Class
| where Properties contains '8d3bca50-1d7e-11d0-a081-00aa006c33ed' // Picture Attribute - Ldap-Display-Name: thumbnailPhoto
| extend AccountName = SubjectUserName, AccountDomain = SubjectDomainName
| extend timestamp = TimeGenerated, DeviceName = Computer
),
( WindowsEvent
| where EventID == 4662 // You need to create a SACL on the ADFS Policy Store DKM group for this event to be created.
| where EventData has_all('Object Access', '5cb41ed0-0e4c-11d0-a286-00aa003049e2','8d3bca50-1d7e-11d0-a081-00aa006c33ed')
| extend ObjectServer = tostring(EventData.ObjectServer)
| where ObjectServer == 'DS'
| extend OperationType = tostring(EventData.OperationType)
| where OperationType == 'Object Access'
//| where ObjectName contains '<GUID of ADFS Policy Store DKM Group object' This is unique to the domain. Check description for more details.
| extend ObjectType = tostring(EventData.ObjectType)
| where ObjectType contains '5cb41ed0-0e4c-11d0-a286-00aa003049e2' // Contact Class
| extend Properties = tostring(EventData.Properties)
| where Properties contains '8d3bca50-1d7e-11d0-a081-00aa006c33ed' // Picture Attribute - Ldap-Display-Name: thumbnailPhoto
| extend AccountName = tostring(EventData.SubjectUserName), AccountDomain = tostring(EventData.SubjectDomainName)
| extend timestamp = TimeGenerated, DeviceName = Computer
),
(DeviceEvents
| where ActionType =~ "LdapSearch"
| where AdditionalFields.AttributeList contains "thumbnailPhoto"
| where AdditionalFields.DistinguishedName contains "CN=ADFS,CN=Microsoft,CN=Program Data" // Filter results to show only hits related to the ADFS AD container
| extend timestamp = TimeGenerated, AccountName = InitiatingProcessAccountName, AccountDomain = InitiatingProcessAccountDomain
)
)
| extend Account = strcat(AccountDomain, "\\", AccountName)
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: Account
- identifier: Name
columnName: AccountName
- identifier: NTDomain
columnName: AccountDomain
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: DeviceName
- entityType: AzureResource
fieldMappings:
- identifier: ResourceId
columnName: _ResourceId
version: 1.2.2
kind: Scheduled
metadata:
source:
kind: Community
author:
name: Microsoft Security Research
support:
tier: Community
categories:
domains: [ "Security - Others", "Identity" ]
Stages and Predicates
union isfuzzy=true (3 sources)
Each leg below queries one source; the rule matches if any leg does. Sources: SecurityEvent, WindowsEvent, DeviceEvents
Leg 1: SecurityEvent
SecurityEvent
| where EventID == 4662
| where ObjectServer == 'DS'
| where OperationType == 'Object Access'
| where ObjectType contains '5cb41ed0-0e4c-11d0-a286-00aa003049e2'
| where Properties contains '8d3bca50-1d7e-11d0-a081-00aa006c33ed'
| extend AccountName = SubjectUserName, AccountDomain = SubjectDomainName
| extend timestamp = TimeGenerated, DeviceName = Computer
Leg 2: WindowsEvent
WindowsEvent
| where EventID == 4662
| where EventData has_all('Object Access', '5cb41ed0-0e4c-11d0-a286-00aa003049e2','8d3bca50-1d7e-11d0-a081-00aa006c33ed')
| extend ObjectServer = tostring(EventData.ObjectServer)
| where ObjectServer == 'DS'
| extend OperationType = tostring(EventData.OperationType)
| where OperationType == 'Object Access'
| extend ObjectType = tostring(EventData.ObjectType)
| where ObjectType contains '5cb41ed0-0e4c-11d0-a286-00aa003049e2'
| extend Properties = tostring(EventData.Properties)
| where Properties contains '8d3bca50-1d7e-11d0-a081-00aa006c33ed'
| extend AccountName = tostring(EventData.SubjectUserName), AccountDomain = tostring(EventData.SubjectDomainName)
| extend timestamp = TimeGenerated, DeviceName = Computer
Leg 3: DeviceEvents
DeviceEvents
| where ActionType =~ "LdapSearch"
| where AdditionalFields.AttributeList contains "thumbnailPhoto"
| where AdditionalFields.DistinguishedName contains "CN=ADFS,CN=Microsoft,CN=Program Data"
| extend timestamp = TimeGenerated, AccountName = InitiatingProcessAccountName, AccountDomain = InitiatingProcessAccountDomain
Applied to the combined result
| extend Account = strcat(AccountDomain, "\\", AccountName)
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 |
|---|---|---|
ActionType | eq |
|
AttributeList | contains |
|
DistinguishedName | contains |
|
EventData | match |
|
EventID | eq |
|
ObjectServer | eq |
|
ObjectType | contains |
|
OperationType | eq |
|
Properties | contains |
|
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 |
|---|---|
AccountDomain | extend |
AccountName | extend |
DeviceName | extend |
timestamp | extend |
ObjectServer | extend |
OperationType | extend |
ObjectType | extend |
Properties | extend |
Account | extend |