T1595

Active Scanning

Reconnaissance Last updated:

This detection identifies inbound active reconnaissance scanning against your infrastructure by monitoring network perimeter logs for systematic port scanning, IP block sweeping, and vulnerability probing patterns originating from external sources. Because T1595 occurs pre-compromise and is directed at victim infrastructure from the outside, detection relies on perimeter telemetry such as firewall deny/drop logs, IDS/IPS alerts, and web server access logs rather than endpoint events. The detection correlates high-frequency blocked connection attempts from single source IPs across multiple destination ports or multiple destination hosts within short time windows, which is characteristic of automated scanning tools such as nmap, masscan, Shodan crawlers, and vulnerability scanners like Nessus or Qualys. Early identification of active scanning enables defenders to preemptively block attacker infrastructure before exploitation attempts begin.

What is T1595 Active Scanning?

Active Scanning (T1595) 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 Active Scanning, covering the data sources and telemetry it touches: Firewall, IDS/IPS, Network Security Appliances. The queries below are rated medium severity at medium confidence, and ship for 7 SIEM platforms — KQL, SPL, Elastic, QRadar, Sumo, YARA-L, LogScale.

MITRE ATT&CK

Tactic
Reconnaissance
Technique
T1595 Active Scanning
Canonical reference
https://attack.mitre.org/techniques/T1595/
Microsoft Sentinel / Defender
kusto
CommonSecurityLog
| where TimeGenerated > ago(1h)
| where DeviceAction in~ ("Deny", "Drop", "Block", "Reject", "deny", "drop", "block", "reject")
| where isnotempty(SourceIP) and SourceIP !startswith "10." and SourceIP !startswith "192.168." and SourceIP !startswith "172."
| where DestinationPort > 0
| summarize
    UniqueDestPorts = dcount(DestinationPort),
    UniqueDestIPs = dcount(DestinationIP),
    TotalAttempts = count(),
    PortsTargeted = make_set(DestinationPort, 50),
    FirstSeen = min(TimeGenerated),
    LastSeen = max(TimeGenerated),
    DeviceVendor = any(DeviceVendor),
    DeviceProduct = any(DeviceProduct)
    by SourceIP, bin(TimeGenerated, 5m)
| where UniqueDestPorts >= 10 or (UniqueDestIPs >= 5 and TotalAttempts >= 30)
| extend
    ScanType = case(
        UniqueDestPorts >= 20, "Aggressive Port Scan",
        UniqueDestPorts >= 10, "Port Scan",
        UniqueDestIPs >= 10, "IP Block Sweep",
        UniqueDestIPs >= 5, "Limited IP Sweep",
        "Suspicious Probe"
    ),
    ScanDurationSeconds = datetime_diff('second', LastSeen, FirstSeen),
    AttemptsPerMinute = TotalAttempts / max_of(datetime_diff('minute', LastSeen, FirstSeen), 1)
| project
    TimeGenerated,
    SourceIP,
    ScanType,
    UniqueDestPorts,
    UniqueDestIPs,
    TotalAttempts,
    AttemptsPerMinute,
    PortsTargeted,
    ScanDurationSeconds,
    FirstSeen,
    LastSeen,
    DeviceVendor,
    DeviceProduct
| order by TotalAttempts desc

Detects inbound active scanning against perimeter infrastructure by aggregating firewall deny/drop/block events from CommonSecurityLog over 5-minute windows. Flags external source IPs that probe 10 or more distinct destination ports (port scan) or reach 5 or more distinct destination IPs with 30 or more blocked attempts (IP block sweep). Excludes RFC1918 private address space to focus on external threats. Enriches each alert with scan type classification, attempts per minute rate, and list of targeted ports.

medium severity medium confidence

Data Sources

Firewall IDS/IPS Network Security Appliances

Required Tables

CommonSecurityLog

False Positives

  • Legitimate external vulnerability scanners operated by authorized third-party security vendors (e.g., Qualys, Tenable, Rapid7) running scheduled assessments — coordinate with security team to whitelist known scanner IPs
  • Cloud provider health checks, CDN edge probes, and load balancer connectivity tests from cloud service IP ranges (AWS, Azure, Cloudflare) that generate denied traffic to closed ports
  • Internet background radiation and automated internet-wide scanners from academic research institutions such as Shodan, Censys, and university security research groups hitting exposed public IPs

Sigma rule & cross-platform mapping

The detection logic for Active Scanning (T1595) 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 1nmap TCP SYN Port Scan Against Test Target

    Expected signal: Firewall deny/drop log entries for TCP SYN packets from the scanning host IP to TARGET_IP across ports 1-1024, visible in CommonSecurityLog (KQL) or cisco:asa/pan:traffic sourcetypes (SPL). IDS/IPS may generate nmap OS fingerprint detection signatures.

  2. Test 2masscan High-Rate IP Block Sweep

    Expected signal: High-rate firewall deny/drop events across multiple destination IPs within the target CIDR. NetFlow records will show SYN-only TCP sessions with no SYN-ACK responses to closed ports. Masscan generates distinctive TCP options patterns detectable by IDS/IPS signature engines.

  3. Test 3Web Application Vulnerability Scan with Nikto

    Expected signal: Web server access logs (IIS W3CIISLog, Apache access_combined) show hundreds of HTTP GET/HEAD requests to paths such as /.env, /.git/config, /admin, /wp-admin, /phpmyadmin, /manager/html with predominantly 404 (Not Found) and 403 (Forbidden) response codes. Nikto User-Agent string 'Mozilla/5.00 (Nikto/2' visible in csUserAgent field.


Response Playbook

Triage

  1. Step 1: Identify the source IP and perform reverse DNS lookup and ASN/ISP lookup using tools such as whois, ipinfo.io, or Shodan. Determine if the IP belongs to a known scanner (Shodan, Censys, academic research), cloud provider, CDN, or residential/VPS hosting that could indicate an adversary-controlled system.
  2. Step 2: Cross-reference the source IP against threat intelligence feeds (Microsoft Threat Intelligence, VirusTotal, AbuseIPDB, AlienVault OTX). Check if the IP has prior scanning or malicious activity history. Note IOC confidence scores and associated threat actor groups.
  3. Step 3: Review the specific ports and services targeted. High-value port combinations (22, 3389, 445, 1433, 3306, 8080, 8443) suggest targeted reconnaissance of common remote access and database services. Sequential port scanning (1-65535) indicates automated scanning tools. Known exploit ports (CVE-specific ports) indicate vulnerability scanning.
  4. Step 4: Determine if any of the scanned ports are actually open and reachable. Check firewall allow rules for the destination IPs. If the scanner received a successful response (SYN-ACK) on any port, escalate immediately — the adversary has confirmed accessible services.
  5. Step 5: Review whether the scanning IP has appeared in other log sources (web server access logs, authentication logs, email headers). Prior contact suggests a more targeted attack where scanning is part of a broader kill chain against your specific organization.
  6. Step 6: Calculate scan velocity and duration. Scans exceeding 1000 attempts per minute are typically automated tool-generated (nmap -T5, masscan) and indicate systematic rather than opportunistic reconnaissance. Document peak rate, total duration, and total unique ports/IPs targeted.
  7. Step 7: Check for correlated events in authentication logs (SecurityEvent 4625, Syslog auth failures, AADSignInLogs) during or shortly after the scan window. Adversaries often attempt exploitation immediately after identifying open services.

Containment

  1. If the source IP is confirmed malicious via threat intelligence and the scan targeted specific services, implement an emergency block at the perimeter firewall for the source IP and its associated CIDR block, coordinating with the network team using your standard change process.
  2. If any scanned ports received successful responses (services are accessible), immediately review those specific services for attempted exploitation or authentication attempts from the same source IP in application-level logs.
  3. Submit the scanning IP to your upstream ISP or cloud provider abuse team if the IP appears to be a compromised or rented host, as takedown requests can neutralize the scanning infrastructure.
  4. Update WAF rules and IDS/IPS signatures to block the source IP and rate-limit future scanning attempts from the same ASN if the ASN shows a pattern of malicious infrastructure.

Evidence Collection

  1. Export all firewall logs for the scanning IP across the full detection window, including any allowed traffic not captured by the deny/drop filter, to establish complete attack timeline.
  2. Capture full NetFlow/IPFIX records for the source IP if available from your network infrastructure — these provide packet counts, byte counts, and flag analysis that confirm scanner tool behavior.
  3. Preserve web server access logs (IIS W3CIISLog, Apache/Nginx syslog) for the same time window to identify if HTTP/HTTPS-based vulnerability scanning or directory enumeration coincided with the network-level scan.
  4. Document the specific ports targeted and compare against publicly known vulnerability disclosures (NVD, vendor advisories) that match those ports/services to assess what vulnerabilities the adversary may have been probing for.
  5. Capture WHOIS, ASN registration, and BGP routing data for the source IP to support threat intelligence enrichment and potential law enforcement referral.

Escalation Criteria

  • ! Escalate immediately if any scanned port received a successful TCP handshake response — this confirms the adversary has identified accessible services and exploitation attempts may follow within minutes to hours.
  • ! Escalate if the scanning IP subsequently appears in authentication failure logs, web application firewall alerts, or exploit attempt signatures — indicating active exploitation following reconnaissance.
  • ! Escalate if scan targets include SCADA/ICS/OT systems, healthcare systems, or other critical infrastructure that would indicate a targeted nation-state or critical infrastructure threat actor.
  • ! Escalate if multiple distinct external IPs scan the same internal services within a short time window, as this may indicate distributed scanning using a botnet or multiple VPS nodes to evade single-IP rate limiting.
  • ! Escalate if threat intelligence confirms the scanning IP is associated with a known advanced persistent threat (APT) group or active ransomware campaign targeting your industry vertical.

Investigation Guide

Forensic Artifacts

  • > Firewall deny/drop logs containing source IP, destination IP, destination port, protocol, timestamp, and action fields
  • > NetFlow/IPFIX records showing traffic volume, packet counts, TCP flag distributions (SYN-only floods indicate scanners), and session duration
  • > IDS/IPS alert logs with signature names identifying specific scanning tool signatures (nmap OS fingerprint probes, Masscan banners, Nessus plugin traffic patterns)
  • > Web server access logs showing systematic HTTP requests with scanner User-Agent strings (Nmap Scripting Engine, Nikto, Nuclei, sqlmap) or sequential URL enumeration patterns
  • > BGP routing table snapshots and WHOIS records for the source IP's ASN to identify hosting provider, registration country, and network block ownership

Tuning Guidance

Start by building an allowlist of known authorized scanner IPs: approved penetration testing vendors, your organization's own vulnerability management platform (Qualys, Tenable, Rapid7), and cloud provider health check CIDRs (reference vendor-published IP range lists). Add these as exclusion filters before deploying to production. Tune the port scan threshold (default 10 unique ports) based on your firewall log volume — high-traffic environments may need to raise this to 20-30 ports to reduce noise from background internet scanning. The IP sweep threshold (5 unique IPs, 30 attempts) should be adjusted based on your network size — larger /16 or /8 address spaces will see more legitimate multi-destination traffic from CDNs and cloud services. Consider creating separate rules with higher severity for specific high-value port combinations (22+3389+445) versus general port scanning, since targeted multi-service scanning is a stronger indicator of adversary activity than random internet background radiation.


Hunting Queries

Hunts for ICMP-based ping sweep reconnaissance using Syslog data from Linux hosts and network devices. ICMP sweeps are distinct from TCP/UDP port scans and are a common precursor to identifying live hosts before targeted port scanning begins. Detects sources sending 20+ ICMP echo requests or reaching 5+ distinct destinations within 10-minute windows.

Hunting — KQL
kql
// Hunt for ICMP-based ping sweep reconnaissance (Syslog from Linux hosts or network devices)
Syslog
| where TimeGenerated > ago(24h)
| where SyslogMessage contains "ICMP" and (SyslogMessage contains "echo request" or SyslogMessage contains "type 8")
| extend SourceIP = extract(@"from\s+([\d\.]+)", 1, SyslogMessage)
| where isnotempty(SourceIP)
| where SourceIP !startswith "10." and SourceIP !startswith "192.168."
| summarize
    PingCount = count(),
    UniqueDestinations = dcount(HostName),
    FirstSeen = min(TimeGenerated),
    LastSeen = max(TimeGenerated)
    by SourceIP, bin(TimeGenerated, 10m)
| where PingCount >= 20 or UniqueDestinations >= 5
| extend SweepRate = PingCount / max_of(datetime_diff('minute', LastSeen, FirstSeen), 1)
| project TimeGenerated, SourceIP, PingCount, UniqueDestinations, SweepRate, FirstSeen, LastSeen
| order by PingCount desc
Hunting — SPL
spl
index=* (sourcetype=syslog OR sourcetype="linux_secure" OR sourcetype="cisco:ios" OR sourcetype="juniper:junos:syslog")
"ICMP" ("echo request" OR "type 8" OR "ping")
| rex field=_raw "from\s+(?P<src_ip>[\d\.]+)"
| search NOT (src_ip="10.*" OR src_ip="192.168.*" OR src_ip="172.1[6-9].*" OR src_ip="172.2[0-9].*" OR src_ip="172.3[0-1].*")
| bin _time span=10m
| stats count as ping_count, dc(host) as unique_destinations, min(_time) as first_seen, max(_time) as last_seen by src_ip _time
| where ping_count >= 20 OR unique_destinations >= 5
| eval sweep_rate = round(ping_count / max((last_seen - first_seen) / 60, 1), 2)
| sort - ping_count
| table _time, src_ip, ping_count, unique_destinations, sweep_rate

Hunts for web-layer vulnerability scanning by detecting systematic probing of common sensitive paths and injection patterns in IIS/Apache/Nginx access logs. Scanners like Nikto, Nuclei, and Burp Scanner generate high unique URI counts with predominantly 4xx error responses as they enumerate non-existent paths. This complements the firewall-layer detection by catching scanning that reaches the application tier.

Hunting — KQL
kql
// Hunt for systematic vulnerability scanning via web application logs showing automated probe patterns
W3CIISLog
| where TimeGenerated > ago(24h)
| where csUriStem matches regex @"/(\.env|\.git|admin|wp-admin|phpmyadmin|manager|actuator|api/v\d|swagger|config|backup|\.well-known)" or csUriQuery contains "'" or csUriQuery contains "<script" or csUriQuery contains "../"
| extend ClientIPClean = tostring(split(cIP, ":" )[0])
| where ClientIPClean !startswith "10." and ClientIPClean !startswith "192.168."
| summarize
    UniqueUris = dcount(csUriStem),
    TotalRequests = count(),
    Http4xxCount = countif(scStatus between (400 .. 499)),
    Http5xxCount = countif(scStatus between (500 .. 599)),
    UserAgents = make_set(csUserAgent, 10),
    SampleUris = make_set(csUriStem, 20)
    by ClientIPClean, bin(TimeGenerated, 10m)
| where UniqueUris >= 15 or TotalRequests >= 50
| extend ErrorRate = round(toreal(Http4xxCount) / TotalRequests * 100, 1)
| project TimeGenerated, ClientIPClean, UniqueUris, TotalRequests, ErrorRate, Http4xxCount, Http5xxCount, UserAgents, SampleUris
| order by UniqueUris desc
Hunting — SPL
spl
index=* (sourcetype="access_combined" OR sourcetype="ms:iis:auto" OR sourcetype="apache:access" OR sourcetype="nginx:access")
| search NOT (src_ip="10.*" OR src_ip="192.168.*")
| eval is_probe=if(match(uri_path, "/(\.\.env|\.git|admin|wp-admin|phpmyadmin|manager|actuator|swagger|config|backup)") OR match(uri_query, "('|<script|\.\./)"), 1, 0)
| search is_probe=1
| bin _time span=10m
| stats dc(uri_path) as unique_uris, count as total_requests, sum(eval(if(status>=400 AND status<500, 1, 0))) as http_4xx, values(http_user_agent) as user_agents, values(uri_path) as sampled_uris by src_ip _time
| where unique_uris >= 15 OR total_requests >= 50
| eval error_rate = round(http_4xx / total_requests * 100, 2)
| sort - unique_uris
| table _time, src_ip, unique_uris, total_requests, error_rate, http_4xx, user_agents, sampled_uris

Hunts for coordinated distributed scanning campaigns where multiple attacker-controlled IPs systematically probe the same destination ports, evading single-IP detection thresholds. This pattern is characteristic of botnet-driven scanning, shared scanning infrastructure, or adversaries using cloud VPS nodes in rotation. Focuses on high-value ports (SSH, RDP, SMB, databases) that are common initial access targets.

Hunting — KQL
kql
// Hunt for low-and-slow distributed scanning that evades single-IP thresholds
CommonSecurityLog
| where TimeGenerated > ago(6h)
| where DeviceAction in~ ("Deny", "Drop", "Block", "Reject")
| where isnotempty(SourceIP) and SourceIP !startswith "10." and SourceIP !startswith "192.168."
// Find port 22, 3389, 445, 1433, 3306 — high-value initial access targets
| where DestinationPort in (22, 23, 25, 80, 443, 445, 1433, 3306, 3389, 5900, 8080, 8443, 9200)
| summarize
    AttemptsPerPort = count(),
    UniqueSourceIPs = dcount(SourceIP),
    SourceIPs = make_set(SourceIP, 30),
    FirstSeen = min(TimeGenerated),
    LastSeen = max(TimeGenerated)
    by DestinationIP, DestinationPort
| where UniqueSourceIPs >= 10 and AttemptsPerPort >= 50
| extend PortName = case(
    DestinationPort == 22, "SSH",
    DestinationPort == 23, "Telnet",
    DestinationPort == 25, "SMTP",
    DestinationPort == 445, "SMB",
    DestinationPort == 1433, "MSSQL",
    DestinationPort == 3306, "MySQL",
    DestinationPort == 3389, "RDP",
    DestinationPort == 5900, "VNC",
    DestinationPort == 9200, "Elasticsearch",
    tostring(DestinationPort)
)
| project FirstSeen, LastSeen, DestinationIP, DestinationPort, PortName, UniqueSourceIPs, AttemptsPerPort, SourceIPs
| order by UniqueSourceIPs desc
Hunting — SPL
spl
index=* (sourcetype="cisco:asa" OR sourcetype="pan:traffic" OR sourcetype="fortinet:fortigate:traffic")
(action=denied OR action=dropped OR action=blocked)
dest_port IN (22, 23, 25, 80, 443, 445, 1433, 3306, 3389, 5900, 8080, 8443, 9200)
| search NOT (src_ip="10.*" OR src_ip="192.168.*")
| stats dc(src_ip) as unique_src_ips, count as total_attempts, values(src_ip) as source_ips by dest_ip dest_port
| where unique_src_ips >= 10 AND total_attempts >= 50
| eval port_name = case(dest_port=22, "SSH", dest_port=445, "SMB", dest_port=1433, "MSSQL", dest_port=3306, "MySQL", dest_port=3389, "RDP", dest_port=5900, "VNC", dest_port=9200, "Elasticsearch", true(), tostring(dest_port))
| sort - unique_src_ips
| table dest_ip, dest_port, port_name, unique_src_ips, total_attempts, source_ips

Atomic Red Team Tests

Test 1 nmap TCP SYN Port Scan Against Test Target
linux

Simulates an adversary performing a TCP SYN port scan using nmap against a designated test IP or hostname. Generates the characteristic denied/blocked connection pattern in firewall logs that the detection queries identify. Run this against an internal test system or a designated scanning target, never against production systems or external IPs without written authorization.

Command

bash
# Requires nmap installed: sudo apt-get install nmap
# Replace TARGET_IP with an authorized test system IP
TARGET_IP="192.168.100.10"
nmap -sS -T4 -p 1-1024 --reason $TARGET_IP -oN /tmp/nmap_scan_$(date +%Y%m%d_%H%M%S).txt
cat /tmp/nmap_scan_*.txt

Cleanup

bash
rm -f /tmp/nmap_scan_*.txt

Expected Telemetry

Firewall deny/drop log entries for TCP SYN packets from the scanning host IP to TARGET_IP across ports 1-1024, visible in CommonSecurityLog (KQL) or cisco:asa/pan:traffic sourcetypes (SPL). IDS/IPS may generate nmap OS fingerprint detection signatures.

Expected Detection

Alert fires within the 5-minute aggregation window when UniqueDestPorts >= 10 threshold is reached. ScanType classification should be 'Aggressive Port Scan' once 20+ ports are reached.

Test 2 masscan High-Rate IP Block Sweep
linux

Simulates a high-velocity IP block sweep using masscan, which is faster than nmap and commonly used by adversaries to rapidly enumerate live hosts across CIDR blocks. Generates high-volume blocked connection events characteristic of professional scanning operations. Requires masscan installation and must be run against authorized test CIDR ranges only.

Command

bash
# Requires masscan: sudo apt-get install masscan
# TARGET_RANGE must be an authorized test network CIDR
TARGET_RANGE="192.168.100.0/28"
masscan $TARGET_RANGE -p 80,443,22,3389,445 --rate=100 --wait 5 -oL /tmp/masscan_results_$(date +%Y%m%d_%H%M%S).txt
cat /tmp/masscan_results_*.txt

Cleanup

bash
rm -f /tmp/masscan_results_*.txt

Expected Telemetry

High-rate firewall deny/drop events across multiple destination IPs within the target CIDR. NetFlow records will show SYN-only TCP sessions with no SYN-ACK responses to closed ports. Masscan generates distinctive TCP options patterns detectable by IDS/IPS signature engines.

Expected Detection

Alert triggers when UniqueDestIPs >= 5 and TotalAttempts >= 30 within a 5-minute window. ScanType should be classified as 'IP Block Sweep' or 'Limited IP Sweep' depending on CIDR size.

Test 3 Web Application Vulnerability Scan with Nikto
linux

Simulates a web application vulnerability scan using Nikto, which performs systematic HTTP probes against common vulnerable paths, outdated software signatures, and server misconfigurations. Generates the web-layer scanning pattern detected by the W3CIISLog hunting query. Must be run against an authorized web application test target only.

Command

bash
# Requires nikto: sudo apt-get install nikto
# TARGET_URL must be an authorized test web application
TARGET_URL="http://192.168.100.10"
nikto -h $TARGET_URL -o /tmp/nikto_scan_$(date +%Y%m%d_%H%M%S).txt -Format txt -Tuning 1234567 2>&1 | tee /tmp/nikto_output.txt
echo "Scan complete. Results:"
cat /tmp/nikto_scan_*.txt | head -50

Cleanup

bash
rm -f /tmp/nikto_scan_*.txt /tmp/nikto_output.txt

Expected Telemetry

Web server access logs (IIS W3CIISLog, Apache access_combined) show hundreds of HTTP GET/HEAD requests to paths such as /.env, /.git/config, /admin, /wp-admin, /phpmyadmin, /manager/html with predominantly 404 (Not Found) and 403 (Forbidden) response codes. Nikto User-Agent string 'Mozilla/5.00 (Nikto/2' visible in csUserAgent field.

Expected Detection

Hunting query fires when UniqueUris >= 15 within 10-minute window with high 4xx error rate. Nikto scans typically generate 300-1000+ unique URI probes, well exceeding the 15-URI threshold.

Related Detections