Detection rules › Kusto
Non Domain Controller Active Directory Replication
This query detects potential attempts by non-computer accounts (non domain controllers) to retrieve/synchronize an active directory object leveraging directory replication services (DRS). A Domain Controller (computer account) would usually be performing these actions in a domain environment. Another detection rule can be created to cover domain controllers accounts doing at rare times. A domain user with privileged permissions to use directory replication services is rare.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Credential Access | T1003.006 OS Credential Dumping: DCSync |
Event coverage
| Provider | Event | Title |
|---|---|---|
| Security-Auditing | Event ID 4624 | An account was successfully logged on. |
| Security-Auditing | Event ID 4662 | An operation was performed on an object. |
Rule body kusto
id: b9d2eebc-5dcb-4888-8165-900db44443ab
name: Non Domain Controller Active Directory Replication
description: |
'This query detects potential attempts by non-computer accounts (non domain controllers) to retrieve/synchronize an active directory object leveraging directory replication services (DRS).
A Domain Controller (computer account) would usually be performing these actions in a domain environment. Another detection rule can be created to cover domain controllers accounts doing at rare times.
A domain user with privileged permissions to use directory replication services is rare.'
severity: High
requiredDataConnectors:
- connectorId: SecurityEvents
dataTypes:
- SecurityEvent
- connectorId: WindowsSecurityEvents
dataTypes:
- SecurityEvent
queryFrequency: 1d
queryPeriod: 7d
triggerOperator: gt
triggerThreshold: 0
status: Available
tactics:
- CredentialAccess
relevantTechniques:
- T1003.006
query: |
// Enter a reference list of hostnames for your DC servers
//let DCServersList = dynamic (["DC01.simulandlabs.com","DC02.simulandlabs.com"]);
SecurityEvent
//| where Computer in (DCServersList)
| where EventID == 4662 and ObjectServer == 'DS'
| where AccountType != 'Machine'
| where Properties has '1131f6aa-9c07-11d1-f79f-00c04fc2dcd2' //DS-Replication-Get-Changes
or Properties has '1131f6ad-9c07-11d1-f79f-00c04fc2dcd2' //DS-Replication-Get-Changes-All
or Properties has '89e95b76-444d-4c62-991a-0facbeda640c' //DS-Replication-Get-Changes-In-Filtered-Set
| project TimeGenerated, Account, Activity, Properties, SubjectLogonId, Computer
| join kind=leftouter
(
SecurityEvent
//| where Computer in (DCServersList)
| where EventID == 4624 and LogonType == 3
| where AccountType != 'Machine'
| project TargetLogonId, IpAddress, Computer
)
on $left.SubjectLogonId == $right.TargetLogonId and $left.Computer == $right.Computer
| project-reorder TimeGenerated, Computer, Account, IpAddress
| extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)
| extend AccountNTDomain = tostring(split(Account, "\\")[0]), AccountName = tostring(split(Account, "\\")[1])
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: Account
- identifier: Name
columnName: AccountName
- identifier: NTDomain
columnName: AccountNTDomain
- entityType: Host
fieldMappings:
- identifier: FullName
columnName: Computer
- identifier: HostName
columnName: HostName
- identifier: NTDomain
columnName: HostNameDomain
- entityType: IP
fieldMappings:
- identifier: Address
columnName: IpAddress
version: 1.0.6
kind: Scheduled
Stages and Predicates
Stage 1: source
SecurityEvent
Stage 2: where
| where EventID == 4662 and ObjectServer == 'DS'
Stage 3: where
| where AccountType != 'Machine'
Stage 4: where
| where Properties has '1131f6aa-9c07-11d1-f79f-00c04fc2dcd2'
or Properties has '1131f6ad-9c07-11d1-f79f-00c04fc2dcd2'
or Properties has '89e95b76-444d-4c62-991a-0facbeda640c'
Stage 5: project
| project TimeGenerated, Account, Activity, Properties, SubjectLogonId, Computer
Stage 6: join
| join kind=leftouter
(
SecurityEvent
| where EventID == 4624 and LogonType == 3
| where AccountType != 'Machine'
| project TargetLogonId, IpAddress, Computer
)
on $left.SubjectLogonId == $right.TargetLogonId and $left.Computer == $right.Computer
Stage 7: project-reorder
| project-reorder TimeGenerated, Computer, Account, IpAddress
Stage 8: extend (3 consecutive steps)
| extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)
| extend AccountNTDomain = tostring(split(Account, "\\")[0]), AccountName = tostring(split(Account, "\\")[1])
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 |
|---|---|---|
AccountType | ne |
|
EventID | eq |
|
LogonType | eq |
|
ObjectServer | eq |
|
Properties | 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 |
|---|---|
Account | project |
Activity | project |
Computer | project |
Properties | project |
SubjectLogonId | project |
TimeGenerated | project |
DomainIndex | extend |
HostName | extend |
HostNameDomain | extend |
AccountNTDomain | extend |
AccountName | extend |