-
Notifications
You must be signed in to change notification settings - Fork 425
Description
Is your feature request related to a problem? Please describe.
The current Internal Horizontal Port Scan NMAP Top 20 detection rule in the Splunk ESCU content package may generate false positives in environments where legitimate internal services (e.g., load balancers, backup systems, patch management tools) connect to multiple internal hosts using a small set of common ports (e.g., HTTP, SMB, RDP). The rule triggers when a host connects to ≥250 distinct destination IPs on any of the top 20 NMAP ports in a 1-hour time window, which fails to account for the fact that legitimate services may generate high volumes of traffic across many IPs but only hit a few specific ports.
Describe the solution you'd like
I propose adding an additional condition to the rule that checks for the distinct number of destination ports. Specifically, the rule should only trigger if a host connects to at least 5 distinct destination ports within the NMAP top 20 port list, in addition to the existing condition of connecting to ≥250 distinct destination IPs. This would improve detection accuracy by distinguishing between malicious scanning activity and legitimate high-volume internal services that may hit many hosts but only target a few ports.
Describe alternatives you've considered
An alternative could be to add a whitelist or exception list for known legitimate services (e.g., backup systems, monitoring systems), but this may require ongoing maintenance and tuning to keep up with changing environments.
Another alternative could be to adjust the threshold for the number of distinct destination IPs, but this may still allow legitimate high-volume services to trigger false positives if they use a small number of ports.
Additional context
The current rule does not differentiate between:
Malicious horizontal scanning, where attackers probe many hosts across multiple ports,
Legitimate activities, where internal services like backup tools, patch management systems, and monitoring tools may generate high traffic volumes on a few ports but hit many hosts.
This enhancement would help reduce unnecessary alerts and improve SOC efficiency by focusing on true scanning activities.
The updated SPL query with the added port count condition would look as follows:
| tstats security_content_summariesonly
values(All_Traffic.action) as action values(All_Traffic.src_category) as src_category values(All_Traffic.dest_zone) as dest_zone values(All_Traffic.src_zone) as src_zone count from datamodel=Network_Traffic where index=fortigate AND All_Traffic.action="allowed" All_Traffic.src_ip IN ("10.0.0.0/8","172.16.0.0/12","192.168.0.0/16") AND All_Traffic.dest_port IN (21, 22, 23, 25, 53, 80, 110, 111, 135, 139, 143, 443, 445, 993, 995, 1723, 3306, 3389, 5900, 8080) by All_Traffic.src_ip All_Traffic.dest_port All_Traffic.dest_ip span=1s _time All_Traffic.transport
| drop_dm_object_name("All_Traffic")
| eval gtime=_time
| bin span=1h gtime
| stats min(_time) as firsttime max(_time) as lasttime values(action) as action dc(dest_ip) as totalDestIPCount dc(dest_port) as TotalDestPortCount values(src_category) as src_category values(dest_zone) as dest_zone values(src_zone) as src_zone by src_ip dest_port gtime transport
| security_content_ctime(firsttime)
| security_content_ctime(lasttime)
| where totalDestIPCount>=250
| eval dest_port=transport + "/" + dest_port
| where TotalDestPortCount>=5
| stats values(action) as action sum(totalDestIPCount) as totalDestIPCount sum(TotalDestPortCount) as TotalDestPortCount values(src_category) as src_category values(dest_port) as dest_ports values(dest_zone) as dest_zone values(src_zone) as src_zone by firsttime lasttime src_ip gtime
| fields - gtime
| internal_horizontal_port_scan_nmap_top_20_filter
This approach minimizes false positives by accounting for port diversity while maintaining detection accuracy for true port scanning behaviors.