Detection rules › Kusto

Missing Domain Controller Heartbeat

Severity
high
Time window
2h
Group by
Computer
Author
Jose Sebastian Canos
Source
github.com/Azure/Azure-Sentinel

'This detection will go over the heartbeats received from the agents of Domain Controllers over the last hour, and will create alerts if the last heartbeats were received an hour ago.'

MITRE ATT&CK coverage

Rule body kusto

id: b8b8ba09-1e89-45a1-8bd7-691cd23bfa32
name: Missing Domain Controller Heartbeat
description: |
  'This detection will go over the heartbeats received from the agents of Domain Controllers over the last hour, and will create alerts if the last heartbeats were received an hour ago.'
severity: High
requiredDataConnectors: []
queryFrequency: 15m
queryPeriod: 2h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Impact
  - DefenseEvasion
relevantTechniques:
  - T1499
  - T1564
query: |
  let query_frequency = 15m;
  let missing_period = 1h;
  //Enter a reference list of hostnames for your DC servers
  let DCServersList = dynamic (["DC01.simulandlabs.com","DC02.simulandlabs.com"]);
  //Alternatively, a Watchlist can be used
  //let DCServersList = _GetWatchlist('HostName-DomainControllers') | project HostName;
  Heartbeat
  | summarize arg_max(TimeGenerated, *) by Computer
  | where Computer in (DCServersList)
  //You may specify the OS type of your Domain Controllers
  //| where OSType == 'Windows'
  | where TimeGenerated between (ago(query_frequency + missing_period) .. ago(missing_period))
  | project TimeGenerated, Computer, OSType, Version, ComputerEnvironment, Type, Solutions
  | sort by TimeGenerated asc
entityMappings:
  - entityType: Host
    fieldMappings:
      - identifier: HostName
        columnName: Computer
version: 1.0.5
kind: Scheduled
metadata:
    source:
        kind: Community
    author:
        name: Jose Sebastian Canos
    support:
        tier: Community
    providers: Microsoft
    categories:
        domains: [ "Security - Others" ]

Stages and Predicates

Parameters

let query_frequency = 15m;
let missing_period = 1h;
let DCServersList = dynamic (["DC01.simulandlabs.com","DC02.simulandlabs.com"]);

Stage 1: source

Heartbeat

Stage 2: summarize

| summarize arg_max(TimeGenerated, *) by Computer

Stage 3: where

| where Computer in (DCServersList)

Stage 4: where

| where TimeGenerated between (ago(query_frequency + missing_period) .. ago(missing_period))

Stage 5: project

| project TimeGenerated, Computer, OSType, Version, ComputerEnvironment, Type, Solutions

Stage 6: sort

| sort by TimeGenerated asc

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
Computerin
  • DC01.simulandlabs.com transforms: cased
  • DC02.simulandlabs.com transforms: cased

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
Computerproject
ComputerEnvironmentproject
OSTypeproject
Solutionsproject
TimeGeneratedproject
Typeproject
Versionproject