Detection rules › Splunk

Internal Port Scan - Critical Ports (Windows Event Log)

Group by
_time, host, src_ip
Source
github.com/anvilogic-forge/armory

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

TacticTechniques
Discovery

References

Telemetry coverage

Rule body

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

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process_pathregex_match"(?i)\x5csplunkuniversalforwarder\x5cbin\x5csplunkd.exe"excludes:process_path

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
EventCodeeq
  • 5152
  • 5156 corpus 15 (splunk 13, kusto 2)
field:"EventID" kind:eq
dc_dest_portgt
  • 5
field:"dc_dest_port" kind:gt value:"5"
dest_portregex_match
  • "^(21|22|23|25|80|8080|139|389|443|8443|445|3306|3389)$"
field:"DestinationPort" kind:regex_match
src_ipregex_match
  • "(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})"
field:"src_ip" kind:regex_match

Search terms

These SPL tokens match against raw event text.

StageTerm
1"<EventID>5152<"
1"<EventID>5156<"