Detection rules › Kusto

Detection Opportunities for Certighost (CVE-2026-54121)

Author
Cyb3rMonk
Source
github.com/Cyb3r-Monk/Threat-Hunting-and-Detection

Telemetry coverage

Rule body

DeviceNetworkEvents
| where ActionType == "ListeningConnectionCreated"
| where LocalPort == 389
| where DeviceName !in~ ("list of domain controllers")

// Author: Cyb3rMonk(https://twitter.com/Cyb3rMonk, https://academy.bluraven.io)
//
let domain_controllers = pack_array("list of domain controllers");
let domain_controller_ips = pack_array("IP addresses of domain controllers");
DeviceLogonEvents
| where AccountName has_any (domain_controllers)
| where isnotempty(RemoteIP)
| where RemoteIP !in ("::1", "127.0.0.1", "-")
| where RemoteIP !startswith "fe80::"
| where RemoteIP !in (domain_controller_ips)

// Author: Cyb3rMonk(https://twitter.com/Cyb3rMonk, https://academy.bluraven.io)
//
let domain_controllers = pack_array("list of domain controllers");
let domain_controller_ips = pack_array("IP addresses of domain controllers");
SecurityEvent
| where EventID == 4624
| where TargetUserName has_any (domain_controllers)
| where isnotempty(IpAddress)
| where IpAddress !in ("::1", "127.0.0.1", "-")
| where IpAddress !startswith "fe80::"
| where IpAddress !in (domain_controller_ips)
| project-reorder TimeGenerated, Computer, TargetUserName, IpAddress

let domain_controller_fqdns = pack_array("list of domain controller fqdns");
let domain_controller_ips = pack_array("IP addresses of domain controllers");
SecurityEvent
| where EventID in (4886, 4887, 4888)
| extend cdc = extract(@'cdc:(\S+)', 1, Attributes), rmd = extract(@'rmd:(\S+)', 1, Attributes)
| where not (cdc in~ (domain_controller_ips) or cdc in~ (domain_controller_fqdns))

Stages and Predicates

Stage 1: source

DeviceNetworkEvents

Stage 2: where

where ActionType =~ "ListeningConnectionCreated"

Stage 3: where

where LocalPort == 389

Stage 4: where

where not (DeviceName =~ "list of domain controllers")

Stage 5: source

DeviceLogonEvents

Stage 6: where

where AccountName contains "domain_controllers"

Stage 7: where

where isnotempty(RemoteIP)

Stage 8: where

where not (RemoteIP in~ ("-", "127.0.0.1", "::1"))

Stage 9: where

where not (RemoteIP startswith "fe80::")

Stage 10: where

where not (RemoteIP =~ "domain_controller_ips")

Stage 11: source

SecurityEvent

Stage 12: where

where EventID == 4624

Stage 13: where

where TargetUserName contains "domain_controllers"

Stage 14: where

where isnotempty(IpAddress)

Stage 15: where

where not (IpAddress in~ ("-", "127.0.0.1", "::1"))

Stage 16: where

where not (IpAddress startswith "fe80::")

Stage 17: where

where not (IpAddress =~ "domain_controller_ips")

Stage 18: project-reorder

project-reorder

Stage 19: source

SecurityEvent

Stage 20: where

where EventID in~ (4886, 4887, 4888)

Stage 21: extend

extend cdc, rmd

Stage 22: where

where not ((cdc =~ "domain_controller_fqdns" or cdc =~ "domain_controller_ips"))

Exclusions

The rule actively suppresses these predicates.

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
AccountNamematch
  • domain_controllers transforms: term
field:"user" kind:match value:"domain_controllers"
ActionTypeeq
  • ListeningConnectionCreated corpus 3 (kusto 3)
field:"ActionType" kind:eq value:"ListeningConnectionCreated"
EventIDeq
  • 4624 corpus 29 (splunk 13, kusto 11, chronicle 4, elastic 1)
field:"EventID" kind:eq value:"4624"
EventIDin
  • 4886 corpus 2 (splunk 2)
  • 4887 corpus 3 (splunk 3)
  • 4888
field:"EventID" kind:in
IpAddressis_not_null
  • (no value, null check)
field:"src_ip" kind:is_not_null
LocalPorteq
  • 389
field:"SourcePort" kind:eq value:"389"
RemoteIPis_not_null
  • (no value, null check)
field:"DestinationIp" kind:is_not_null
TargetUserNamematch
  • domain_controllers transforms: term
field:"TargetUserName" kind:match value:"domain_controllers"