Detection rules › Kusto

Non Domain Controller Active Directory Replication

Status
available
Severity
high
Time window
7d
Source
github.com/Azure/Azure-Sentinel

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

TacticTechniques
Credential Access

Telemetry coverage

Rule body

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

These rows show field, operator, and value matches.

FieldKindValuesSearch
AccountTypene
  • Machine
field:"AccountType" kind:ne value:"Machine"
EventIDeq
  • 4624 corpus 29 (splunk 13, kusto 11, chronicle 4, elastic 1)
  • 4662 corpus 15 (splunk 7, kusto 4, elastic 3, chronicle 1)
field:"EventID" kind:eq
LogonTypeeq
  • 3 corpus 41 (splunk 13, sigma 12, elastic 9, kusto 7)
field:"LogonType" kind:eq value:"3"
ObjectServereq
  • DS corpus 2 (kusto 2)
field:"ObjectServer" kind:eq value:"DS"
Propertiesmatch
  • 1131f6aa-9c07-11d1-f79f-00c04fc2dcd2 transforms: term corpus 6 (sigma 3, elastic 2, kusto 1)
  • 1131f6ad-9c07-11d1-f79f-00c04fc2dcd2 transforms: term corpus 6 (sigma 3, elastic 2, kusto 1)
  • 89e95b76-444d-4c62-991a-0facbeda640c transforms: term corpus 6 (sigma 3, elastic 2, kusto 1)
field:"Properties" kind:match

Output fields

These fields are emitted when the rule matches.

FieldSource
Accountproject
Activityproject
Computerproject
Propertiesproject
SubjectLogonIdproject
TimeGeneratedproject
DomainIndexextend
HostNameextend
HostNameDomainextend
AccountNTDomainextend
AccountNameextend