Response playbooks, investigation guides, and Atomic Red Team tests are Pro-only. Upgrade to unlock the full detection package for THREAT-Recon-DistributedPortScanSweep.
Unlock with Pro - from £29/user/moDetect Distributed Low-and-Slow Port/Service Scanning Sweep in Microsoft Sentinel
Adversaries increasingly avoid classic single-source port scan detection (which alerts on one IP hitting many ports/hosts in a short window) by distributing the sweep across a large pool of source IPs — botnet nodes, residential proxies, or rented scanning infrastructure — with each individual source only touching a handful of destination hosts or ports. No single source ever crosses a per-IP threshold, but the aggregate campaign methodically walks the organization's entire public IP block (T1595.001 — Active Scanning: Scanning IP Blocks) looking for exposed services ahead of exploitation. This is a persistent detection gap because most SIEM scan-detection rules key off a single source IP's touch count within a window; a coordinated low-and-slow sweep spread across dozens or hundreds of source IPs, each staying under that threshold, sails through undetected. Reliable detection requires aggregating perimeter firewall deny/reset telemetry at the destination CIDR level across ALL source IPs in a rolling window, then flagging when a large number of distinct low-touch sources collectively achieve high coverage of the organization's address space — the fingerprint of a coordinated sweep rather than background internet noise.
MITRE ATT&CK
- Tactic
- Reconnaissance
KQL Detection Query
// THREAT: Distributed / Low-and-Slow Port Scan Sweep of Org Perimeter IP Block
// Detects internet-wide or perimeter-wide scanning spread across many distinct source IPs
// (botnet/proxy/rented scan infra) with a LOW per-source touch count, evading classic
// single-source threshold-based scan detection, while collectively sweeping a large
// fraction of the organization's public IP block.
let PerimeterBlocks = dynamic(["203.0.113.0/24", "198.51.100.0/23"]); // TODO: replace with org's registered public CIDR ranges
let LookbackWindow = 24h;
let PerSourceTouchCeiling = 3; // max distinct dest IPs a single source hits and still count as "low-and-slow"
let MinDistinctSources = 25; // minimum distinct low-touch sources to call it a coordinated sweep
let MinSweptHosts = 50; // minimum distinct destination IPs swept in the block to call it broad coverage
let LowTouchSources = CommonSecurityLog
| where TimeGenerated > ago(LookbackWindow)
| where DeviceAction in~ ("deny", "drop", "reset") or Activity has_any ("Deny", "Drop", "Reset")
| where isnotempty(SourceIP) and isnotempty(DestinationIP) and isnotempty(DestinationPort)
| mv-expand Block = PerimeterBlocks to typeof(string)
| where ipv4_is_in_range(DestinationIP, Block)
| summarize DistinctDestIPs = dcount(DestinationIP), DistinctDestPorts = dcount(DestinationPort) by SourceIP, Block
| where DistinctDestIPs <= PerSourceTouchCeiling
| project SourceIP, Block;
CommonSecurityLog
| where TimeGenerated > ago(LookbackWindow)
| where DeviceAction in~ ("deny", "drop", "reset") or Activity has_any ("Deny", "Drop", "Reset")
| where isnotempty(SourceIP) and isnotempty(DestinationIP) and isnotempty(DestinationPort)
| join kind=inner (LowTouchSources) on SourceIP
| where ipv4_is_in_range(DestinationIP, Block)
| summarize
UniqueSources = dcount(SourceIP),
UniqueDestIPsSwept = dcount(DestinationIP),
UniqueDestPorts = dcount(DestinationPort),
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated)
by Block
| where UniqueSources >= MinDistinctSources and UniqueDestIPsSwept >= MinSweptHosts
| extend Signal = "DistributedLowAndSlowScanSweep"
| sort by UniqueDestIPsSwept desc Two-stage Microsoft Sentinel detection over CommonSecurityLog (perimeter firewall deny/drop/reset events). Stage 1 isolates 'low-touch' source IPs that each contact no more than PerSourceTouchCeiling (3) distinct destination hosts within the org's registered public CIDR block(s) — individually invisible to per-source scan thresholds. Stage 2 aggregates across ALL such low-touch sources per CIDR block and flags when a large number of distinct sources (>=25) collectively sweep a large number of distinct destination hosts (>=50) — the signature of a coordinated, distributed reconnaissance sweep of the organization's IP space rather than incidental internet background noise. Requires CIDR matching via ipv4_is_in_range(), not the KQL 'in' operator, since 'in' performs string equality and will not match individual IPs against a CIDR range.
Data Sources
Required Tables
False Positives & Tuning
- Legitimate internet-wide research scanners (Shodan, Censys, Shadowserver, GreyNoise, university research projects) that self-identify via reverse DNS or published IP ranges — maintain an allowlist and exclude their published source ranges
- Distributed uptime/monitoring services (Pingdom, StatusCake, UptimeRobot) probing multiple public endpoints from a rotating pool of monitoring nodes
- CDN or cloud load balancer health-check fleets probing multiple backend IPs from many front-end nodes
- Vulnerability management / attack-surface-management SaaS platforms performing authorized recurring perimeter scans from cloud-hosted scanner pools
Other platforms for THREAT-Recon-DistributedPortScanSweep
Testing Methodology
Validate this detection against 3 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.
- Test 1Simulated Low-Touch Multi-Source Port Probe (Single Host, Multiple Ports)
Expected signal: Perimeter firewall deny/reset log entries for the connection attempts to closed/filtered ports on the lab target, recorded with the source IP and each probed destination port.
- Test 2Simulated Coordinated Sweep (Multiple Scripted Sources, Sequential IP Block Walk)
Expected signal: Firewall deny/reset log entries showing the same source IP touching multiple sequential destination IPs in the lab CIDR block, each with a small number of probed ports.
- Test 3Masscan High-Speed IP Block Sweep (Single Source, Lab Range)
Expected signal: Firewall/NetFlow records showing SYN-only or single-packet connection attempts across every host in the lab /28 range from one source IP.
Unlock playbooks & atomic tests with Pro
Get the full detection package for THREAT-Recon-DistributedPortScanSweep — response playbook and atomic red team tests, plus investigation guidance and hunting queries.
df00tech Pro — £29/user/month