Detect Automated Vulnerability Scanner Sweep Against External Attack Surface in Google Chronicle
Before exploitation, most intrusions begin with active scanning of the target's external attack surface using automated vulnerability scanning tools such as sqlmap, Nikto, Nuclei, Acunetix, Nessus, OpenVAS, or WPScan. Attackers run these tools against internet-facing web applications, APIs, and edge devices to fingerprint software versions, enumerate misconfigurations, and identify exploitable CVEs before committing to an intrusion attempt. This scanning is typically noisy at the HTTP layer: high-volume requests for known vulnerable paths (e.g. /.env, /.git/config, /wp-login.php, /actuator/health, /phpmyadmin), distinctive scanner user-agent strings, and rapid sequential probing of many distinct URIs from a single source in a short window. Nation-state actors such as Volt Typhoon and APT41 routinely scan edge devices and web infrastructure ahead of exploitation attempts, while eCrime groups like FIN7 and Scattered Spider use commodity scanning frameworks to identify soft targets at scale. Detecting the scanning phase gives defenders a window to harden or patch before the attacker moves to Initial Access.
MITRE ATT&CK
- Tactic
- Reconnaissance
YARA-L Detection Query
rule automated_vuln_scanner_sweep {
meta:
author = "df00tech"
description = "Detects automated vulnerability scanner tool signatures and sensitive path probing against WAF-protected web infrastructure"
severity = "MEDIUM"
priority = "MEDIUM"
mitre_attack_tactic = "Reconnaissance"
mitre_attack_technique = "T1595.002"
version = "1.0"
events:
$req.metadata.event_type = "NETWORK_HTTP"
$req.target.application = /(?i)(f5|imperva|fortiweb|akamai|cloudflare|netscaler)/
(
$req.network.http.user_agent = /(?i)(sqlmap|nikto|nuclei|acunetix|nessus|openvas|wpscan|dirbuster|gobuster)/
OR $req.target.url = /(?i)(\.env|\.git\/config|wp-login\.php|actuator\/env|phpmyadmin|\.aws\/credentials)/
)
$req.principal.ip = $src_ip
match:
$src_ip over 5m
outcome:
$request_count = count_distinct($req.metadata.id)
$distinct_uris = count_distinct($req.target.url)
$sample_uris = array_distinct($req.target.url)
condition:
#req >= 1
} YARA-L 2.0 rule for Google Chronicle SIEM detecting known vulnerability scanner user-agent strings or sensitive-path requests against WAF-protected HTTP infrastructure within a 5-minute window.
Data Sources
Required Tables
False Positives & Tuning
- Authorised vulnerability management scans not yet excluded via allowlist
- Bug bounty or authorised penetration testing traffic
- Synthetic monitoring tools with unusual but benign user-agent strings
Other platforms for THREAT-Recon-AutomatedVulnScannerSweep
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 1Vulnerability Scanner User-Agent Simulation via curl
Expected signal: WAF/reverse-proxy logs record inbound requests with the scanner user-agent strings in the Message or http_user_agent field.
- Test 2Sensitive Path Probing Simulation
Expected signal: WAF/reverse-proxy logs show requests to each sensitive path, mostly resulting in 404 responses.
- Test 3Behavioral URI Enumeration Simulation via ffuf-style Loop
Expected signal: WAF/reverse-proxy logs record 40 distinct URIs requested from the test source IP within a single 5-minute window, nearly all returning 404.
Response Playbook
Triage
- Identify the source IP(s) generating the scan traffic. Check AbuseIPDB, Shodan, and VirusTotal for reputation — scanning frequently originates from VPS hosts, Tor exit nodes, or known scanning-as-a-service infrastructure (Shodan, Censys, GreyNoise crawlers).
- Determine whether the source IP matches an authorised vulnerability management scanner (internal AppSec team, contracted pentest firm, or vendor scanning service) already on the allowlist. If so, close as expected activity and add to the exclusion list if missing.
- Review which URIs and paths were probed — sensitive-path hits (/.env, /.git/config, /.aws/credentials) indicate the scanner is specifically hunting for exposed secrets or source code, a higher-priority signal than generic crawling.
- Check whether any of the probed paths returned a 200 OK or otherwise non-404 response, which would indicate the scanner found a genuinely exposed misconfiguration or vulnerable endpoint rather than just probing blind.
- Correlate the scanning window against subsequent traffic from the same source IP or ASN over the following days — scanning is frequently the reconnaissance phase preceding an exploitation attempt days or weeks later.
Containment
- If the source IP is confirmed malicious and unauthorised, block it at the WAF/CDN edge and add to the perimeter firewall deny list.
- If a probed sensitive path (e.g. /.env, /.git/config) returned a non-404 response, treat this as a confirmed exposure: remediate the misconfiguration immediately (remove the exposed file, restrict access, rotate any credentials that may have been exposed) and escalate as a potential compromise, not just reconnaissance.
- Enable or tune WAF rate-limiting and bot-management rules to throttle high-request-volume sources before they can complete a full enumeration sweep.
- Consider geo-blocking or ASN-blocking known scanning infrastructure ranges if the organisation has no legitimate business need for traffic from those sources.
Evidence Collection
- WAF/reverse-proxy access logs for the source IP across the full scan window: full URI list, response codes, user-agent strings, and timestamps
- Any subsequent authentication or application-layer events from the same source IP or ASN in the days following the scan
- Threat intelligence lookups and passive DNS history for the source IP
- Configuration and exposure audit of any sensitive path that returned a non-404 response during the scan
Escalation Criteria
- !A probed sensitive path (e.g. /.env, /.git/config, /.aws/credentials, /phpmyadmin) returns a non-404/non-403 response — treat as a confirmed exposure requiring immediate remediation
- !The scanning source IP is later observed attempting authentication or exploitation against the same target
- !Scan volume or URI enumeration breadth is consistent with a known nation-state scanning campaign (e.g. mass internet-wide scanning for a newly disclosed CVE)
- !Multiple internet-facing assets across the organisation are scanned by the same source IP within a short window, indicating targeted rather than opportunistic reconnaissance
Investigation Guide
Related Techniques
Forensic Artifacts
- >
WAF/reverse-proxy access logs: source IP, requested URI, HTTP method, response code, user-agent, timestamps - >
CDN edge logs showing request geography and ASN for the scanning source - >
Application server logs corroborating whether any probed path was actually reachable behind the WAF - >
Threat intelligence enrichment records (AbuseIPDB, GreyNoise, Shodan) for the source IP at time of scan
Tuning Guidance
Thresholds should be tuned against your own baseline of legitimate scanning traffic — organisations that run frequent authorised vulnerability scans (weekly Nessus/Qualys runs, continuous DAST in CI/CD) should maintain a source-IP allowlist and exclude those ranges before enabling this rule broadly, otherwise the behavioral alert will fire constantly. The known-signature alert (Alert 1) is lower-noise and safe to run at high sensitivity since legitimate traffic rarely presents scanner user-agent strings. The behavioral alert (Alert 2) should have its distinct-URI and error-ratio thresholds raised for organisations with many single-page applications that legitimately generate high 404 rates from client-side routing, and lowered for small, stable web estates where any broad enumeration is anomalous.
Hunting Queries
Weekly hunt for any source IP that either enumerated 15+ distinct URIs against WAF-protected infrastructure in a single day or probed any known sensitive path — surfaces low-and-slow scanning that stays under the primary detection's 5-minute-window thresholds.
CommonSecurityLog
| where TimeGenerated > ago(7d)
| where DeviceVendor has_any ("F5", "Imperva", "Fortinet", "Akamai", "Cloudflare", "Citrix")
| summarize
DistinctURIs=dcount(RequestURL),
TotalRequests=count(),
SensitivePathHits=countif(RequestURL has_any ("/.env", "/.git/config", "/.aws/credentials", "/phpmyadmin"))
by SourceIP, bin(TimeGenerated, 1d)
| where DistinctURIs >= 15 or SensitivePathHits >= 1
| sort by SensitivePathHits desc, DistinctURIs desc index=network sourcetype IN ("f5:asm","imperva:waf","fortinet:fortiweb","cloudflare:waf")
| bin _time span=1d
| stats dc(uri_path) AS DistinctURIs, count AS TotalRequests,
count(eval(match(uri_path, "(?i)(\.env|\.git/config|\.aws/credentials|phpmyadmin)"))) AS SensitivePathHits
BY src_ip, _time
| where DistinctURIs >= 15 OR SensitivePathHits >= 1
| sort - SensitivePathHits, - DistinctURIs Atomic Red Team Tests
Simulates requests bearing known vulnerability scanner user-agent strings against a test web endpoint, to validate that Alert 1's signature matching fires correctly.
Command
for ua in "sqlmap/1.7.2#stable" "Mozilla/5.0 (Nikto/2.5.0)" "Nuclei - Open-source project (github.com/projectdiscovery/nuclei)"; do curl -s -A "$ua" -o /dev/null -w '%{http_code}\n' https://<TEST_TARGET>/; sleep 1; done Expected Telemetry
WAF/reverse-proxy logs record inbound requests with the scanner user-agent strings in the Message or http_user_agent field.
Expected Detection
Alert 1 fires on Message has_any match against known scanner tool signatures.
Simulates a scanner probing common sensitive/vulnerable paths against a test endpoint to validate signature-based path matching.
Command
for path in "/.env" "/.git/config" "/wp-login.php" "/actuator/env" "/phpmyadmin" "/.aws/credentials"; do curl -s -o /dev/null -w "%{http_code} $path\n" https://<TEST_TARGET>$path; sleep 1; done Expected Telemetry
WAF/reverse-proxy logs show requests to each sensitive path, mostly resulting in 404 responses.
Expected Detection
Alert 1 fires on RequestURL has_any match against the sensitive-path list.
Simulates a custom scanner without a recognisable user-agent rapidly enumerating many distinct URIs against a single target, to validate that Alert 2's behavioral detection fires when the signature-based alert would miss unsigned tooling.
Command
python3 -c "
import requests, time
paths = [f'/test-path-{i}' for i in range(40)]
for p in paths:
r = requests.get(f'https://<TEST_TARGET>{p}', verify=False)
print(p, r.status_code)
time.sleep(0.2)
" Expected Telemetry
WAF/reverse-proxy logs record 40 distinct URIs requested from the test source IP within a single 5-minute window, nearly all returning 404.
Expected Detection
Alert 2 fires when DistinctURIs >= 25, TotalRequests >= 30, and NotFoundRatio >= 0.5 within the 5-minute bin.
Related Detections
Tactic Hub
Detection Variants (2)
Different telemetry and tradecraft for the same technique — pick the one that matches the data you collect.
- THREAT-Recon-DistributedVulnScanBurstDistributed Vulnerability Scanning Burst Against Web Infrastructure
- THREAT-Recon-ExternalVulnScannerBurstDetectionExternal Vulnerability Scanner Burst/Sweep Against Internet-Facing AssetsBurst/sweep rate-and-breadth angle on external, internet-facing vulnerability scanning — distinct from the tool-signature and internal-scanner-execution branches already covered on the T1595.002 technique page; this detection fires purely on request volume/uniqueness from a single external source against WAF/firewall/proxy logs, without relying on scanner tool names or user-agent strings.