Skip to content
← Rule library
high KQL Windows

Interactive RDP Fan-Out From a Single Source

One source opening interactive sessions to many hosts in an hour. Counts distinct destinations, because admins revisit a few machines and lateral movement touches many once.

Rule source

rdp-lateral-burst.kql
// Interactive RDP Fan-Out From a Single Source
// T1021.001 - Remote Services: Remote Desktop Protocol
// One workstation opening interactive sessions to many hosts in a short window.
// Counts distinct destinations, not session volume - an admin touches a few
// machines repeatedly, lateral movement touches many machines once.

let window       = 1h;
let min_targets  = 6;

SecurityEvent
| where TimeGenerated > ago(window)
| where EventID == 4624 and LogonType in (10, 7)          // RemoteInteractive, unlock
| where AccountType == "User"
| where IpAddress !in ("-", "127.0.0.1", "::1")
| summarize
      Targets      = dcount(Computer),
      TargetSample = make_set(Computer, 15),
      Sessions     = count(),
      FirstSeen    = min(TimeGenerated),
      LastSeen     = max(TimeGenerated)
    by Account, IpAddress
| where Targets >= min_targets
| extend SessionsPerTarget = round(todouble(Sessions) / Targets, 2)
| join kind=leftanti (
    // Jump hosts and VDI brokers fan out by design - maintain this as a watchlist.
    _GetWatchlist('ApprovedJumpHosts') | project IpAddress = tostring(SearchKey)
  ) on IpAddress
| order by Targets desc

Required telemetry

SecurityEvent - Event ID 4624, LogonType 10 and 7

Confirm this source is arriving before you judge the rule. A detection built on telemetry you do not collect looks identical to one that simply never fires.

Known false positives

  • Jump hosts and VDI brokers - maintained as a watchlist, not inline exclusions
  • Patch windows where an engineer legitimately sweeps an estate

Validation

Six-host RDP sweep from a lab workstation, confirmed fires at threshold

Re-run quarterly. Rules decay because the environment moves underneath them - agent upgrades, schema changes and config edits all break detections silently.