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

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

These rows show field, operator, and value matches.

FieldKindValuesSearch
Computerin
  • DC01.simulandlabs.com
  • DC02.simulandlabs.com
field:"Computer" kind:in

Output fields

These fields are emitted when the rule matches.

FieldSource
Computerproject
ComputerEnvironmentproject
OSTypeproject
Solutionsproject
TimeGeneratedproject
Typeproject
Versionproject