Detection rules › Splunk
Internal Port Scan - Critical Ports (Windows Event Log)
After gaining an initial foothold, threat actors may attempt to identify services operating on hosts within the network, often using legitimate port scanning software. This use case detects when more than 5 of the following ports have been scanned from a single internal source IP within one minute: 21 (FTP), 22 (SSH), 23 (Telnet), 25 (SMTP), 80 (HTTP), 8080 (Alternative HTTP), 139 (NetBIOS/SMB), 389 (LDAP), 443 (HTTPS), 8443 (Alternative HTTPS), 445 (Microsoft-DS/SMB), 3306 (MySQL), 3389 (RDP).
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Discovery | T1046 Network Service Discovery |
References
Event coverage
| Provider | Event | Title |
|---|---|---|
| Security-Auditing | Event ID 5152 | The Windows Filtering Platform blocked a packet. |
| Security-Auditing | Event ID 5156 | The Windows Filtering Platform has permitted a connection. |
Rule body yaml
id: '26208.48343'
title: Internal Port Scan - Critical Ports
description: 'After gaining an initial foothold, threat actors may attempt to identify
services operating on hosts within the network, often using legitimate port scanning
software. This use case detects when more than 5 of the following ports have been
scanned from a single internal source IP within one minute: 21 (FTP), 22 (SSH),
23 (Telnet), 25 (SMTP), 80 (HTTP), 8080 (Alternative HTTP), 139 (NetBIOS/SMB), 389
(LDAP), 443 (HTTPS), 8443 (Alternative HTTPS), 445 (Microsoft-DS/SMB), 3306 (MySQL),
3389 (RDP). '
logic_format: Splunk
logic: '`get_endpoint_data` `get_endpoint_data_winevent` (TERM(EventCode=5152) OR
"<EventID>5152<" OR TERM(EventCode=5156) OR "<EventID>5156<") | where match(src_ip,
"(10\.\d{1,3}\.\d{1,3}\.\d{1,3}|172\.(1[6-9]|2[0-9]|3[0-1])\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3})")
and match(dest_port, "^(21|22|23|25|80|8080|139|389|443|8443|445|3306|3389)$") and
not match(process_path, "(?i)\x5csplunkuniversalforwarder\x5cbin\x5csplunkd\.exe")
| table _time, host, user, signature_id, process, process_*, dest_port, dest_ip,
src_ip | bin span=60s | stats values(*) as * by _time, host | streamstats dc(dest_port)
as dc_dest_port by _time, src_ip| where dc_dest_port>5 '
techniques:
- discovery:network service discovery
technique_id:
- T1046
data_category:
- Windows event logs
references:
- https://www.fortinet.com/content/dam/fortinet/assets/threat-reports/rhysida-ransomware-intrusion.pdf?utm_source=blog&utm_medium=blog&utm_campaign=rhysida-ransomware
- https://www.advanced-port-scanner.com/
Stages and Predicates
Stage 1: search
`get_endpoint_data` `get_endpoint_data_winevent` (TERM(EventCode=5152) OR "<EventID>5152<" OR TERM(EventCode=5156) OR "<EventID>5156<")
Stage 2: where
| where match(src_ip, "(10\.\d{1,3}\.\d{1,3}\.\d{1,3}|172\.(1[6-9]|2[0-9]|3[0-1])\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3})") and match(dest_port, "^(21|22|23|25|80|8080|139|389|443|8443|445|3306|3389)$") and not match(process_path, "(?i)\x5csplunkuniversalforwarder\x5cbin\x5csplunkd\.exe")
Stage 3: table
| table _time, host, user, signature_id, process, process_*, dest_port, dest_ip, src_ip
Stage 4: bucket
| bin span=60s
Stage 5: stats
| stats values(*) as * by _time, host
Stage 6: streamstats
| streamstats dc(dest_port) as dc_dest_port by _time, src_ip
Stage 7: where
| where dc_dest_port>5
Exclusions
Top-level NOT(...) conjuncts: predicates this rule actively suppresses.
| Field | Kind | Excluded values |
|---|---|---|
process_path | match | "(?i)\x5csplunkuniversalforwarder\x5cbin\x5csplunkd\.exe" |
Indicators
Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.
| Field | Kind | Values |
|---|---|---|
EventCode | eq |
|
dc_dest_port | gt |
|
dest_port | match |
|
src_ip | match |
|
Search terms
Bare-string tokens in the SPL search body. Splunk matches each token against _raw (the untyped raw event text) anywhere it appears, not against a specific field. These don't surface in the Indicators table because they aren't predicates on a known field.
| Stage | Term |
|---|---|
| 1 | TERM |
| 1 | "<EventID>5152<" |
| 1 | TERM |
| 1 | "<EventID>5156<" |