THREAT-Recon-DistributedVulnScanBurst

Distributed Vulnerability Scanning Burst Against Web Infrastructure

Reconnaissance Last updated:

Adversaries and access brokers run automated vulnerability scanners against externally-facing web infrastructure to fingerprint exposed technology and locate exploitable misconfigurations before initial access. Two patterns dominate: a concentrated burst, where a single source IP fires a wide diversity of scanner-signature requests (config file probes, admin panel paths, framework actuator endpoints, path traversal, webshell probes) at a target within minutes; and a low-and-slow variant, where a small rotating pool of source IPs within the same /24 subnet or hosting-provider ASN spreads the same signature diversity across a much longer window to stay under per-IP rate-limit thresholds. Both patterns are typically observed in WAF, reverse-proxy, or perimeter firewall logs rather than endpoint telemetry, since the target is the externally-facing HTTP surface itself. Detection prioritises the diversity of distinct scanner-signature categories touched per source (or per rotating subnet) over raw request volume, since volume alone is indistinguishable from normal crawler/bot traffic while signature diversity is not.

What is THREAT-Recon-DistributedVulnScanBurst Distributed Vulnerability Scanning Burst Against Web Infrastructure?

Distributed Vulnerability Scanning Burst Against Web Infrastructure (THREAT-Recon-DistributedVulnScanBurst) maps to the Reconnaissance tactic — the adversary is trying to gather information they can use to plan future operations in MITRE ATT&CK.

This page provides production-ready detection logic for Distributed Vulnerability Scanning Burst Against Web Infrastructure, covering the data sources and telemetry it touches: WAF logs forwarded as CEF (F5 ASM, Imperva, Fortinet FortiWeb, Palo Alto), Azure Application Gateway / Front Door WAF logs, Reverse proxy / perimeter firewall access logs. The queries below are rated high severity at medium confidence, and ship for 7 SIEM platforms — KQL, SPL, Elastic, QRadar, Sumo, YARA-L, LogScale.

MITRE ATT&CK

Tactic
Reconnaissance
Microsoft Sentinel / Defender
kusto
let ScannerPathSignatures = dynamic([".env", ".git/config", ".git/HEAD", "wp-login.php", "wp-admin/setup-config.php", "xmlrpc.php", "phpmyadmin", "actuator/env", "actuator/health", "console/", "manager/html", "solr/admin", "cgi-bin/", "../../../../etc/passwd", "shell.php", "config.php.bak", "vendor/phpunit", "telescope/requests", "debug/default/view", "server-status", "eval-stdin.php"]);
let ScannerUserAgents = dynamic(["sqlmap", "Nikto", "Nessus", "Acunetix", "masscan", "zgrab", "Nuclei", "dirbuster", "gobuster", "wpscan", "OpenVAS", "Qualys"]);
// Alert 1: Concentrated burst - many distinct scanner signatures from one source IP in a short window
let Burst = CommonSecurityLog
| where TimeGenerated > ago(1h)
| where isnotempty(RequestURL)
| where RequestURL has_any (ScannerPathSignatures) or (isnotempty(RequestClientApplication) and RequestClientApplication has_any (ScannerUserAgents))
| extend MatchedSignature = case(
    RequestURL has ".env", ".env",
    RequestURL has ".git", ".git",
    RequestURL has "wp-login" or RequestURL has "wp-admin", "wordpress_admin",
    RequestURL has "xmlrpc.php", "xmlrpc",
    RequestURL has "actuator", "spring_actuator",
    RequestURL has "phpmyadmin", "phpmyadmin",
    RequestURL has "solr/admin", "solr_admin",
    RequestURL has "manager/html", "tomcat_manager",
    RequestURL has "../../" or RequestURL has "..%2f", "path_traversal",
    RequestURL has "shell.php" or RequestURL has "eval-stdin", "webshell_probe",
    isnotempty(RequestClientApplication) and RequestClientApplication has_any (ScannerUserAgents), "scanner_useragent",
    "other_scanner_signature"
  )
| summarize DistinctSignatures = dcount(MatchedSignature), DistinctPaths = dcount(RequestURL), TotalRequests = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated), Signatures = make_set(MatchedSignature), TargetHosts = make_set(DestinationHostName) by SourceIP
| where DistinctSignatures >= 6 and DistinctPaths >= 10
| extend BurstDurationMinutes = datetime_diff('minute', LastSeen, FirstSeen)
| extend DetectionType = "ConcentratedBurst", RiskScore = case(DistinctSignatures >= 15, 95, DistinctSignatures >= 10, 88, 78);
// Alert 2: Low-and-slow - rotating source IPs within the same /24 spreading scanner signatures across a long window
let LowAndSlow = CommonSecurityLog
| where TimeGenerated > ago(24h)
| where isnotempty(RequestURL)
| where RequestURL has_any (ScannerPathSignatures) or (isnotempty(RequestClientApplication) and RequestClientApplication has_any (ScannerUserAgents))
| extend Subnet24 = strcat(tostring(split(SourceIP, ".")[0]), ".", tostring(split(SourceIP, ".")[1]), ".", tostring(split(SourceIP, ".")[2]), ".0/24")
| extend MatchedSignature = case(
    RequestURL has ".env", ".env",
    RequestURL has ".git", ".git",
    RequestURL has "wp-login" or RequestURL has "wp-admin", "wordpress_admin",
    RequestURL has "xmlrpc.php", "xmlrpc",
    RequestURL has "actuator", "spring_actuator",
    RequestURL has "phpmyadmin", "phpmyadmin",
    RequestURL has "solr/admin", "solr_admin",
    RequestURL has "manager/html", "tomcat_manager",
    RequestURL has "../../" or RequestURL has "..%2f", "path_traversal",
    RequestURL has "shell.php" or RequestURL has "eval-stdin", "webshell_probe",
    isnotempty(RequestClientApplication) and RequestClientApplication has_any (ScannerUserAgents), "scanner_useragent",
    "other_scanner_signature"
  )
| summarize DistinctSignatures = dcount(MatchedSignature), DistinctSourceIPs = dcount(SourceIP), DistinctPaths = dcount(RequestURL), TotalRequests = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated), SourceIPs = make_set(SourceIP), Signatures = make_set(MatchedSignature) by Subnet24
| where DistinctSourceIPs >= 3 and DistinctSourceIPs <= 25 and DistinctSignatures >= 8
| extend DetectionType = "LowAndSlowSubnetRotation", RiskScore = case(DistinctSignatures >= 15, 92, DistinctSignatures >= 10, 82, 72);
union Burst, LowAndSlow
| sort by RiskScore desc, DistinctSignatures desc

Two-alert KQL detection over CommonSecurityLog (WAF/reverse-proxy/firewall CEF telemetry): (1) ConcentratedBurst flags a single source IP touching >=6 distinct scanner-signature categories across >=10 distinct paths within a 1-hour window; (2) LowAndSlowSubnetRotation flags 3-25 distinct source IPs within the same /24 subnet collectively touching >=8 distinct scanner-signature categories across a 24-hour window, indicating rotation to evade per-IP rate limiting. RiskScore scales with signature diversity.

high severity medium confidence

Data Sources

WAF logs forwarded as CEF (F5 ASM, Imperva, Fortinet FortiWeb, Palo Alto) Azure Application Gateway / Front Door WAF logs Reverse proxy / perimeter firewall access logs

Required Tables

CommonSecurityLog

False Positives

  • Authorized internal or contracted vulnerability management scans (Qualys, Nessus, Tenable, Rapid7) running against production on an approved scanning schedule
  • Bug bounty researchers or penetration testers operating within an approved rules-of-engagement window
  • Uptime/synthetic monitoring services (Pingdom, UptimeRobot, StatusCake) or health-check bots hitting many paths from a small set of monitoring IPs
  • SEO crawlers, CDN health probes, or archival bots (Googlebot, Bingbot, Wayback Machine) traversing many URL paths that incidentally overlap scanner signature patterns
  • Load testing tools or CI/CD smoke tests hitting numerous endpoints rapidly from a shared build-agent IP address

Sigma rule & cross-platform mapping

The detection logic for Distributed Vulnerability Scanning Burst Against Web Infrastructure (THREAT-Recon-DistributedVulnScanBurst) above is provided in a vendor-neutral form so you can deploy it on any SIEM. The same logic is shipped here as native KQL (Microsoft Sentinel / Defender), SPL (Splunk), Elastic (Elastic Security (EQL)), QRadar (IBM QRadar (AQL)), Sumo (Sumo Logic CSE), YARA-L (Google Chronicle / SecOps), LogScale (CrowdStrike LogScale (CQL)) queries. In Sigma terms, this detection targets the following logsource:

logsource:
  category: network_connection
  product: windows

Browse the community-maintained Sigma rules for this technique:


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.

  1. Test 1Scanner Signature Path Sweep (Concentrated Burst)

    Expected signal: WAF/reverse-proxy logs show >=10 distinct scanner-signature paths requested within seconds from the tester's single source IP, User-Agent 'AtomicTest-VulnScan/1.0'.

  2. Test 2Known Scanner Tool User-Agent Sweep

    Expected signal: WAF logs show dozens of distinct paths (config, admin, CGI, backup file probes) and User-Agent containing 'Nikto' from the tester's source IP within minutes.

  3. Test 3Low-and-Slow Subnet-Rotated Scan Simulation

    Expected signal: WAF logs show 4 distinct source IPs within 198.51.100.0/24, each issuing 2 scanner-signature requests spread across several hours, collectively covering >=8 distinct signature categories.


Response Playbook

Triage

  1. Confirm whether the source IP(s)/subnet correspond to a known, authorized scanner (internal vulnerability-management platform, contracted pentest firm, bug bounty program) by checking IP allowlists and scanning calendars before treating this as hostile.
  2. Review the specific signature categories matched (config-file probes, admin-panel paths, framework actuator endpoints, path traversal, webshell probes) to assess whether the actor is doing broad fingerprinting or targeting a vulnerability class relevant to your actual stack.
  3. Check WAF/reverse-proxy response codes for the matched requests: a 200 or 500 response on a scanner-signature path indicates the probed resource may genuinely exist and warrants an immediate deep-dive, versus uniform 403/404 broad blind probing.
  4. For the low-and-slow variant, pivot on the /24 subnet or ASN of the rotating source IPs to determine whether they belong to a cloud-hosting provider commonly used for scanning infrastructure, or to a residential/proxy range indicating botnet-driven scanning.
  5. Cross-reference the scanned paths against your actual technology stack (CMS, frameworks, app servers in use) — probes for irrelevant technology (e.g. WordPress paths against a pure API service) indicate blind broad-spectrum internet scanning rather than targeted recon of your environment specifically.

Containment

  1. Rate-limit or block the offending source IP(s) / subnet at the WAF/CDN edge (Cloudflare, Azure Front Door, F5) once authorization has been ruled out.
  2. If low-and-slow subnet rotation is confirmed against a hosting-provider ASN, apply an ASN-level or geo-based rate limit rather than single-IP blocks, since the actor will continue rotating source addresses within the range.
  3. Immediately lock down or remove any endpoint confirmed to exist via a 200/500 response on a sensitive config/debug/admin/webshell-probe path — the recon itself already revealed the exposure.
  4. Notify the vulnerability-management or pentest-coordination owner to confirm or rule out an authorized scanning window before escalating further.

Evidence Collection

  1. Full WAF/reverse-proxy access logs for the source IP(s)/subnet spanning the detection window, including request path, query string, headers, User-Agent, and response code/size for every request.
  2. Whois/ASN lookup and threat-intelligence enrichment (GreyNoise, AbuseIPDB, Shodan) on the source IP(s) to classify known-scanner infrastructure versus a likely-compromised host.
  3. A chronological timeline of distinct signature categories observed, to reconstruct the scanner's fingerprinting sequence and identify what technology it believes it found.
  4. Any downstream alerts (WAF blocks, IDS/IPS hits, application error logs) correlated to the same source IP/subnet and time window.

Escalation Criteria

  • ! Any scanner-signature request returns HTTP 200 or 500 against a config/debug/admin/webshell-probe path, indicating the probed resource may actually exist.
  • ! The same source IP or subnet pivots from broad vulnerability scanning to authentication attempts (login POST requests) or exploitation payloads (SQLi/RCE strings) within the same session, indicating recon has transitioned to active exploitation.
  • ! Distinct-signature count exceeds 20 in a single burst window, or the low-and-slow pattern persists across multiple consecutive 24-hour windows, indicating a dedicated persistent actor rather than opportunistic internet-wide noise.
  • ! The scanning activity is not attributable to any authorized internal or contracted scanning program after checking allowlists and calendars.

Investigation Guide

Forensic Artifacts

  • > WAF/reverse-proxy access logs: request path, query string, headers, User-Agent, and response code/size per request
  • > CDN edge logs (Cloudflare, Azure Front Door, Akamai) distinguishing edge cache-hit from origin-forwarded requests from the scanning source
  • > Threat-intel enrichment records (GreyNoise, Shodan, AbuseIPDB) classifying the source IP/ASN at the time of the scan
  • > Downstream IDS/IPS or application error logs correlated to the same source and time window

Tuning Guidance

Maintain an allowlist of known-authorized vulnerability scanner and monitoring IP ranges (internal Qualys/Nessus/Tenable appliances, contracted pentest firm ranges, uptime-monitoring services) and exclude them at the top of both queries — legitimate scheduled scans will otherwise trip both ConcentratedBurst and LowAndSlowSubnetRotation on every scan cycle. Tune the DistinctSignatures/DistinctPaths thresholds (currently 6/10 for the burst, 8 signatures across 3-25 distinct source IPs for low-and-slow) upward for high-traffic public sites with heavy legitimate crawler/bot diversity, and downward for low-traffic internal-facing apps where any signature diversity is anomalous. Prioritise alerts where a scanner-signature request returned 200/500 over uniform 403/404, since those indicate the probed resource genuinely exists.


Hunting Queries

Once a source IP is confirmed malicious, pivot across the full environment (all sites/tenants behind the WAF) over the prior 7 days to identify every other host it touched — distributed scanners frequently probe multiple properties from the same infrastructure before or after the detected burst.

Hunting — KQL
kql
CommonSecurityLog
| where TimeGenerated > ago(7d)
| where SourceIP == "REPLACE_WITH_CONFIRMED_SCANNER_IP"
| summarize RequestCount = count(), DistinctTargets = dcount(DestinationHostName), Targets = make_set(DestinationHostName), Paths = make_set(RequestURL) by SourceIP, bin(TimeGenerated, 1h)
| sort by TimeGenerated asc
Hunting — SPL
spl
index=waf OR index=firewall src_ip="REPLACE_WITH_CONFIRMED_SCANNER_IP" earliest=-7d
| stats count AS RequestCount, dc(dest_host) AS DistinctTargets, values(dest_host) AS Targets, values(uri_path) AS Paths BY src_ip, span=1h
| sort _time

Atomic Red Team Tests

Test 1 Scanner Signature Path Sweep (Concentrated Burst)
linux

Rapidly requests a set of known vulnerability-scanner-signature paths (config files, admin panels, framework actuator endpoints, CGI probes) against a target from a single source IP within seconds, simulating the ConcentratedBurst detection pattern.

Command

bash
for p in /.env /.git/config /wp-login.php /xmlrpc.php /actuator/env /phpmyadmin/ /solr/admin/ /manager/html /cgi-bin/test.cgi /server-status; do curl -s -o /dev/null -A "AtomicTest-VulnScan/1.0" "https://TARGET_HOST$p"; done

Cleanup

bash
unset p

Expected Telemetry

WAF/reverse-proxy logs show >=10 distinct scanner-signature paths requested within seconds from the tester's single source IP, User-Agent 'AtomicTest-VulnScan/1.0'.

Expected Detection

Fires ConcentratedBurst with DistinctSignatures >= 6, DistinctPaths >= 10, RiskScore >= 78.

Test 2 Known Scanner Tool User-Agent Sweep
linux

Runs Nikto against the target, generating a wide diversity of scanner-signature path probes and a fingerprinted scanner User-Agent string in a single short-lived session.

Command

bash
nikto -h https://TARGET_HOST -o /tmp/nikto_out.txt -Tuning 123456789

Cleanup

bash
rm -f /tmp/nikto_out.txt

Expected Telemetry

WAF logs show dozens of distinct paths (config, admin, CGI, backup file probes) and User-Agent containing 'Nikto' from the tester's source IP within minutes.

Expected Detection

Fires ConcentratedBurst with DistinctSignatures well above the 6-category threshold; RiskScore >= 88 given high signature diversity.

Test 3 Low-and-Slow Subnet-Rotated Scan Simulation
linux

Simulates distributed low-and-slow scanning by issuing scanner-signature requests from multiple source addresses within the same /24 test range (e.g. via a local proxy/interface pool), spreading the same signature diversity across several hours to stay under a per-IP burst threshold.

Command

bash
for ip in 198.51.100.10 198.51.100.11 198.51.100.12 198.51.100.13; do curl -s -o /dev/null --interface $ip -A "AtomicTest-VulnScan/1.0" "https://TARGET_HOST/.env"; curl -s -o /dev/null --interface $ip -A "AtomicTest-VulnScan/1.0" "https://TARGET_HOST/actuator/env"; sleep 3600; done

Cleanup

bash
unset ip

Expected Telemetry

WAF logs show 4 distinct source IPs within 198.51.100.0/24, each issuing 2 scanner-signature requests spread across several hours, collectively covering >=8 distinct signature categories.

Expected Detection

Fires LowAndSlowSubnetRotation once the 24h window accumulates DistinctSourceIPs between 3-25 and DistinctSignatures >= 8; RiskScore >= 72.

Related Detections