Detect External Vulnerability Scanner Burst/Sweep Against Internet-Facing Assets in IBM QRadar
This detection complements the general T1595.002 Vulnerability Scanning coverage with a focus on a specific behavioral signature: a single external source rapidly sweeping a high volume of distinct URIs, query parameters, or ports against internet-facing web/application assets within a short window. Rather than matching on scanner tool names or user-agent strings (which are trivially spoofed or stripped), this detection keys on rate and breadth — a burst of requests from one source IP hitting many unique paths/params/ports on a public-facing WAF, reverse proxy, or perimeter firewall in a tight time window is a strong behavioral indicator of automated vulnerability scanning regardless of tooling. Sandworm Team, APT41, and Magic Hound have all conducted large-scale internet-facing vulnerability scanning sweeps as a precursor to exploitation of public-facing applications (T1190), and this pattern is equally produced by commodity scanners, bug bounty researchers, and unauthorized red team activity. The detection is intentionally tool-agnostic and behavior-based — no CVE or vulnerability-specific payload matching is performed here since that is scan-target-dependent and better covered by WAF/IDS signature rules.
MITRE ATT&CK
- Tactic
- Reconnaissance
QRadar Detection Query
SELECT
DATEFORMAT(starttime, 'YYYY-MM-dd HH:mm:ss') AS EventTime,
UTF8(sourceip) AS SourceIP,
COUNT(*) AS RequestCount,
UNIQUECOUNT("URL") AS UniqueUris,
UNIQUECOUNT(destinationport) AS UniqueDestPorts
FROM events
WHERE LOGSOURCETYPENAME(logsourceid) IN ('Universal LEEF', 'L7 Firewalls', 'Web Application Firewall')
AND "URL" IS NOT NULL
AND starttime > NOW() - 3600000
GROUP BY SourceIP
HAVING UNIQUECOUNT("URL") >= 40 OR COUNT(*) >= 150
ORDER BY RequestCount DESC
LIMIT 1000 QRadar AQL query aggregating WAF/firewall events by source IP over a 1-hour window, surfacing sources whose unique URI count or total request count exceeds the burst thresholds — the same rate-and-breadth logic as the KQL/SPL versions, expressed as a GROUP BY/HAVING aggregation over QRadar's normalized URL and destination port properties.
Data Sources
Required Tables
False Positives & Tuning
- Authorized vulnerability management scans from documented scanner IP ranges
- Search engine crawlers generating high URI uniqueness during a full site crawl
- Approved bug bounty or pentest engagement traffic
Other platforms for THREAT-Recon-ExternalVulnScannerBurstDetection
Testing Methodology
Validate this detection against 2 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 1Simulate External Burst Scan Against a Web Endpoint with ffuf
Expected signal: WAF/reverse-proxy access log entries showing 60 requests from the local test source in a short window, each with a distinct URI path (/test-path-1 through /test-path-60) and query parameter. If a firewall/CEF-normalized log pipeline is present, this appears as CommonSecurityLog entries with a shared SourceIP and high UniqueUris count within the burst window.
- Test 2Simulate Multi-Port Sweep Against a Single External-Facing Host
Expected signal: Firewall/NetFlow connection logs showing a burst of connection attempts from the source IP to 12 distinct destination ports on the target host within seconds. Sysmon Event ID 3 (Network Connection) on the target if endpoint monitoring is present.
References (5)
- https://attack.mitre.org/techniques/T1595/002/
- https://owasp.org/www-project-automated-threats-to-web-applications/assets/oats/EN/OAT-014_Vulnerability_Scanning
- https://learn.microsoft.com/en-us/azure/sentinel/connect-common-event-format
- https://www.cisa.gov/news-events/cybersecurity-advisories/aa24-249a
- https://github.com/ffuf/ffuf
Response Playbook
Triage
- Pull the SourceIP's full request list for the burst window and inspect the SampleUris/sample_uris field — a mix of admin panels, config files, and framework-specific paths (/actuator, /.env, /wp-login.php, /phpmyadmin) confirms deliberate vulnerability enumeration rather than a crawl or retry-loop artifact
- Check whether the source IP is in your organization's approved scanner IP allowlist (vulnerability management platform scan job ownership) or matches a documented pentest/bug-bounty engagement window
- Perform reverse DNS, WHOIS, and threat intelligence lookups (GreyNoise, Shodan, AbuseIPDB, VirusTotal) on the source IP to distinguish known benign mass-scanner infrastructure (Shodan/Censys/binaryedge crawlers) from unknown or malicious-reputation infrastructure
- Review the response status code distribution — a high ratio of 401/403/404 responses with a small number of 200s indicates broad enumeration with occasional hits, which is higher-priority than a burst that is uniformly 200 (more likely a legitimate crawler or API client)
- Check UniqueDestPorts/unique_dest_ports — a burst hitting a single port (443) with high URI uniqueness is web-path enumeration; a burst hitting many distinct ports from one source is closer to a port/service sweep and should be cross-referenced with T1595.001 (Scanning IP Blocks)
- Correlate the burst window against subsequent authentication attempts, WAF rule triggers, or unusual outbound traffic from the targeted assets in the following 24-72 hours — a scan immediately followed by exploitation attempts is a high-confidence attack chain
- If the same source IP or ASN reappears across multiple burst windows over several days, treat as a persistent reconnaissance campaign rather than a one-off automated crawl
Containment
- If the source IP is not on the scanner allowlist and reputation lookups return unknown or malicious: block the source IP at the WAF/perimeter firewall and document the block with IOC details
- Enable or tighten rate-limiting at the WAF/load balancer for the affected virtual host — cap requests per source IP per minute and auto-block sources exceeding the burst thresholds used in this detection
- If specific high-value paths were repeatedly probed (admin panels, API management endpoints, backup/config file paths), verify those paths are not unintentionally exposed and apply WAF virtual-patching rules if a known vulnerable component was targeted
- If the burst originated from a cloud provider IP range with no known business relationship, consider a temporary geo/ASN-based block at the CDN/WAF layer while the source is investigated
- Notify the application owner of the targeted internet-facing asset so they can confirm whether the surface area probed (paths, ports) matches expected exposure or reveals unintentional exposure
Evidence Collection
- Full WAF/firewall/proxy access log entries for the source IP across the burst window and the surrounding hour, including raw URI, query string, status code, response size, and User-Agent
- Aggregated burst summary (request count, unique URI count, unique port count, requests-per-minute) as computed by this detection, for the incident timeline
- Threat intelligence context — submit the source IP to GreyNoise, Shodan, AbuseIPDB, and VirusTotal; document classification, ASN, and any associated campaign or scanner-infrastructure tagging
- DNS logs showing any reverse PTR lookups performed by the source IP against your public IP ranges prior to the burst, indicating pre-scan reconnaissance
- Any subsequent authentication, exploitation, or anomalous-access events from the same source IP or ASN within 72 hours of the burst
Escalation Criteria
- !The burst targets internet-facing assets with specific high-value paths (admin consoles, API gateways, backup/config file locations) rather than generic crawl patterns
- !The source IP or ASN is attributed to a known nation-state or APT threat actor by threat intelligence, or matches published IOC infrastructure from CISA/sector ISAC advisories
- !The burst is followed within 24-72 hours by exploitation attempts, successful authentication, or anomalous access from the same or a related source against the scanned assets
- !Multiple distinct external source IPs conduct coordinated bursts against the same internet-facing assets within a short window — indicates a distributed or well-resourced scanning campaign attempting to evade single-source rate limits
- !The burst reveals that a sensitive or unintentionally exposed path (internal admin tool, backup directory, staging environment) is reachable from the internet at all, independent of whether the traffic itself is malicious
Investigation Guide
Related Techniques
Forensic Artifacts
- >
WAF/CDN access and block logs (Cloudflare, AWS WAF, Azure Front Door, Akamai) showing per-request detail: raw URI, query string, headers, User-Agent, and block/allow disposition - >
Reverse proxy / load balancer access logs (nginx, HAProxy, F5) at their default log paths, showing the full request sequence from the source IP - >
Perimeter firewall / NetFlow session logs capturing the connection-level view of the burst (source port reuse, TCP flags, connection duration) - >
Threat intelligence platform entries (MISP, OpenCTI) documenting the source IP, burst signature, and any CVE-specific targeting observed in the probed path list - >
SIEM alert history for the source IP/ASN over the preceding 30 days to determine whether this burst is an isolated event or part of an ongoing campaign
Tuning Guidance
Start by building an allowlist of every legitimate high-volume/high-uniqueness source: your own vulnerability management scanner IPs (Nessus/Qualys/Tenable), approved pentest/bug-bounty engagement IP ranges, known search-engine crawler ASNs (Google, Bing, DuckDuckGo), and any synthetic-monitoring or load-testing sources. Suppress all of these on SourceIP/ASN before tuning thresholds further. Set UniqueUriThreshold and RequestCountThreshold relative to your actual internet-facing asset's normal traffic pattern — a small marketing site and a large API gateway will have very different legitimate baselines, so consider per-asset (DestinationHostName) thresholds rather than one global value. Weight alerts higher when the probed path set includes known-sensitive patterns (/.env, /actuator, /wp-login.php, backup/config file extensions) even if the raw volume is below threshold, since a low-and-slow targeted probe of high-value paths can be more dangerous than a loud generic crawl. Periodically feed confirmed-benign source IPs (via GreyNoise or your own investigation history) back into the allowlist to reduce recurring analyst load from known internet-background-noise scanners.
Hunting Queries
Hunts for source IPs producing high-URI-uniqueness bursts against internet-facing assets across two or more distinct days within a 7-day window, distinguishing persistent reconnaissance campaigns from one-off crawler activity or a single opportunistic scan.
// Hunt: Sustained external scanning bursts recurring across multiple days
CommonSecurityLog
| where TimeGenerated > ago(7d)
| where isnotempty(SourceIP) and isnotempty(RequestURL)
| extend UriPath = tostring(split(RequestURL, "?")[0])
| summarize
TotalRequests = count(),
UniqueUris = dcount(UriPath),
UniqueDays = dcount(bin(TimeGenerated, 1d)),
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated)
by SourceIP
| where UniqueDays >= 2 and UniqueUris >= 30
| sort by TotalRequests desc index=waf OR index=firewall OR index=proxy earliest=-7d
| eval uri_path=coalesce(uri_path, mvindex(split(url, "?"), 0), cs_uri_stem)
| eval src_display=coalesce(src_ip, src, clientip, c_ip)
| eval scan_day=strftime(_time, "%Y-%m-%d")
| stats count as total_requests, dc(uri_path) as unique_uris, dc(scan_day) as unique_days,
min(_time) as first_seen, max(_time) as last_seen by src_display
| where unique_days >= 2 AND unique_uris >= 30
| sort - total_requests Atomic Red Team Tests
Uses ffuf to rapidly request a large set of distinct URIs against a target host within a short window, simulating the rate-and-breadth behavioral pattern this detection keys on (many unique paths from one source in a tight time window). Targets localhost to avoid any external network impact; adjust the target only within an authorized test environment.
Command
seq 1 60 | xargs -I{} -P 10 curl -s -o /dev/null -w '%{http_code}\n' "http://127.0.0.1:8080/test-path-{}?probe=1" Cleanup
true Expected Telemetry
WAF/reverse-proxy access log entries showing 60 requests from the local test source in a short window, each with a distinct URI path (/test-path-1 through /test-path-60) and query parameter. If a firewall/CEF-normalized log pipeline is present, this appears as CommonSecurityLog entries with a shared SourceIP and high UniqueUris count within the burst window.
Expected Detection
KQL/SPL burst detection: SourceIP shows UniqueUris >= 40 (at default threshold, may require lowering the test volume/threshold in a lab) and RequestCount >= 60 within the 10-minute bin, with SampleUris reflecting the /test-path-N sequence.
Uses nmap to rapidly probe a range of commonly-exposed service ports on a single target host, simulating the port-breadth dimension of an external vulnerability scanning burst (UniqueDestPorts) as distinct from the URI-breadth dimension covered by the ffuf test above.
Command
nmap -T4 -p 21,22,25,80,443,445,3389,8080,8443,9000,9200,27017 127.0.0.1 -oN /tmp/burst_port_sweep.txt Cleanup
rm -f /tmp/burst_port_sweep.txt Expected Telemetry
Firewall/NetFlow connection logs showing a burst of connection attempts from the source IP to 12 distinct destination ports on the target host within seconds. Sysmon Event ID 3 (Network Connection) on the target if endpoint monitoring is present.
Expected Detection
KQL/SPL burst detection: SourceIP shows UniqueDestPorts elevated within the burst window; in production this correlates with the URI-sweep branch when the same source also probes web paths, and should be cross-referenced against the T1595.001 Scanning IP Blocks detection for the network-sweep angle.
Related Detections
Tactic Hub
Detection Variants (2)
Different telemetry and tradecraft for the same technique — pick the one that matches the data you collect.