Detection rules › Kusto

New EXE deployed via Default Domain or Default Domain Controller Policies

Status
available
Severity
high
Time window
14d
Group by
CommandLine, Computer, NewProcessName, Process
Source
github.com/Azure/Azure-Sentinel

This detection highlights executables deployed to hosts via either the Default Domain or Default Domain Controller Policies. These policies apply to all hosts or Domain Controllers and best practice is that these policies should not be used for deployment of files. A threat actor may use these policies to deploy files or scripts to all hosts in a domain.

MITRE ATT&CK coverage

Event coverage

Rule body kusto

id: 05b4bccd-dd12-423d-8de4-5a6fb526bb4f
name: New EXE deployed via Default Domain or Default Domain Controller Policies
description: |
  'This detection highlights executables deployed to hosts via either the Default Domain or Default Domain Controller Policies. These policies apply to all hosts or Domain Controllers and best practice is that these policies should not be used for deployment of files.
  A threat actor may use these policies to deploy files or scripts to all hosts in a domain.'
severity: High
requiredDataConnectors:
  - connectorId: SecurityEvents
    dataTypes:
      - SecurityEvent
  - connectorId: WindowsSecurityEvents
    dataTypes:
      - SecurityEvent
queryFrequency: 1d
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
status: Available
tactics:
  - Execution
  - LateralMovement
relevantTechniques:
  - T1072
  - T1570
query: |
  let known_processes = (
    SecurityEvent
    // If adjusting Query Period or Frequency update these
    | where TimeGenerated between(ago(14d)..ago(1d))
    | where EventID == 4688
    | where NewProcessName has_any ("Policies\\{6AC1786C-016F-11D2-945F-00C04fB984F9}", "Policies\\{31B2F340-016D-11D2-945F-00C04FB984F9}")
    | summarize by Process);
    SecurityEvent
    // If adjusting Query Period or Frequency update these
    | where TimeGenerated > ago(1d)
    | where EventID == 4688
    | where NewProcessName has_any ("Policies\\{6AC1786C-016F-11D2-945F-00C04fB984F9}", "Policies\\{31B2F340-016D-11D2-945F-00C04FB984F9}")
    | where Process !in (known_processes)
    // This will likely apply to multiple hosts so summarize these data
    | summarize FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated) by Process, NewProcessName, CommandLine, Computer
    | extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))
    | extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)
entityMappings:
  - entityType: Host
    fieldMappings:
      - identifier: FullName
        columnName: Computer
      - identifier: HostName
        columnName: HostName
      - identifier: DnsDomain
        columnName: HostNameDomain
version: 1.0.2
kind: Scheduled

Stages and Predicates

Let binding: known_processes

let known_processes = (
  SecurityEvent
  | where TimeGenerated between(ago(14d)..ago(1d))
  | where EventID == 4688
  | where NewProcessName has_any ("Policies\\{6AC1786C-016F-11D2-945F-00C04fB984F9}", "Policies\\{31B2F340-016D-11D2-945F-00C04FB984F9}")
  | summarize by Process);

Stage 1: source

let known_processes

Stage 2: source

SecurityEvent

Stage 3: where

| where TimeGenerated > ago(1d)

Stage 4: where

| where EventID == 4688

Stage 5: where

| where NewProcessName has_any ("Policies\\{6AC1786C-016F-11D2-945F-00C04fB984F9}", "Policies\\{31B2F340-016D-11D2-945F-00C04FB984F9}")

Stage 6: where

| where Process !in (known_processes)

References known_processes (defined above).

Stage 7: summarize

| summarize FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated) by Process, NewProcessName, CommandLine, Computer

Stage 8: extend

| extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))

Stage 9: extend

| extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)
HostNameDomain =
ifDomainIndex != -1substring(Computer, (DomainIndex + 1))
elseComputer

Exclusions

Top-level NOT(...) conjuncts: predicates this rule actively suppresses.

FieldKindExcluded values
Processeqknown_processes

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.

FieldKindValues
EventIDeq
  • 4688 transforms: cased corpus 313 (splunk 283, kusto 30)
NewProcessNamematch
  • Policies\\{31B2F340-016D-11D2-945F-00C04FB984F9}
  • Policies\\{6AC1786C-016F-11D2-945F-00C04fB984F9}

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.

FieldSource
CommandLinesummarize
Computersummarize
FirstSeensummarize
LastSeensummarize
NewProcessNamesummarize
Processsummarize
DomainIndexextend
HostNameextend
HostNameDomainextend