Detection rules › Splunk
Scheduled Task with Potential SSH Tunnel - Windows (Windows Event Log)
Threat actors have been observed using scheduled tasks to create reverse SSH tunnels to facilitate persistence on a compromised machine as reported by DFIR. This use case detects scheduled tasks created with commands indicating potential SSH tunnels. The regex filtering matches on the patterns 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 Bare-string tokens in the SPL MITRE ATT&CK coverage
Tactic Techniques Execution T1053 Scheduled Task/JobPersistence T1053 Scheduled Task/JobPrivilege Escalation T1053 Scheduled Task/JobCommand & Control T1572 Protocol TunnelingReferences
Event coverage
Provider Event Title Security-Auditing Event ID 4688 A new process has been created. Security-Auditing Event ID 4698 A scheduled task was created. Rule body yaml
id: '25326.46988'
title: Scheduled Task with Potential SSH Tunnel - Windows
description: Threat actors have been observed using scheduled tasks to create reverse
SSH tunnels to facilitate persistence on a compromised machine as reported by DFIR.
This use case detects scheduled tasks created with commands indicating potential
SSH tunnels. The regex filtering matches on the patterns <user>@<IP address> and
<port number>:<IP Address> :<port number>. Living Off the Land Binary and Scripts
(LOLBAS) (LOLBIN)
logic_format: Splunk
logic: '`get_endpoint_data` `get_endpoint_data_winevent` (TERM(EventCode=4698) OR
"<EventID>4698<") OR (TERM(EventCode=4688) OR "<EventID>4688<" OR Type=Process)
"@" "/create" ("-L" OR "-R" OR "-N" OR "-D" OR "-C" OR "IdentitiesOnly=yes" OR "StrictHostKeyChecking=no"
OR "ssh") | where ((match(TaskContent, "\w+@\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}")
and match(TaskContent, "\d{1,5}:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{1,5}") and
match(TaskContent, "-L|-R|-N|-D|-C|IdentitiesOnly=yes|StrictHostKeyChecking=no|ssh"))
OR (match(process, "\w+@\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}") and match(process,
"\d{1,5}:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{1,5}") and match(process, "(?i)\-(L|R|N|D|C)|IdentitiesOnly=yes|StrictHostKeyChecking=no|ssh")))
| table _time, host, user, process, process_*, parent_process_name, parent_process_*,
signature_id | bin span=1s | stats values(*) as * by _time, host '
techniques:
- execution:scheduled task/job
- command-and-control:protocol tunneling
technique_id:
- T1053
- T1572
data_category:
- Process command-line parameters
- Windows event logs
references:
- https://thedfirreport.com/2023/10/30/netsupport-intrusion-results-in-domain-compromise/
Stages and Predicates
Stage 1:
search`get_endpoint_data` `get_endpoint_data_winevent` (TERM(EventCode=4698) OR "<EventID>4698<") OR (TERM(EventCode=4688) OR "<EventID>4688<" OR Type=Process) "@" "/create" ("-L" OR "-R" OR "-N" OR "-D" OR "-C" OR "IdentitiesOnly=yes" OR "StrictHostKeyChecking=no" OR "ssh")
Stage 2:
where| where ((match(TaskContent, "\w+@\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}") and match(TaskContent, "\d{1,5}:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{1,5}") and match(TaskContent, "-L|-R|-N|-D|-C|IdentitiesOnly=yes|StrictHostKeyChecking=no|ssh")) OR (match(process, "\w+@\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}") and match(process, "\d{1,5}:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{1,5}") and match(process, "(?i)\-(L|R|N|D|C)|IdentitiesOnly=yes|StrictHostKeyChecking=no|ssh")))
Stage 3:
table| table _time, host, user, process, process_*, parent_process_name, parent_process_*, signature_id
Stage 4:
bucket time_window=1s| bin span=1s
Stage 5:
stats| stats values(*) as * by _time, host
Indicators
1 shows that the indicator is specific to this rule.Field Kind Values EventCodeeq 4688 4698 TaskContentmatch "-L|-R|-N|-D|-C|IdentitiesOnly=yes|StrictHostKeyChecking=no|ssh""\d{1,5}:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{1,5}""\w+@\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"processmatch "(?i)\-(L|R|N|D|C)|IdentitiesOnly=yes|StrictHostKeyChecking=no|ssh" "\d{1,5}:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{1,5}" "\w+@\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" Search terms
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 TERM1 "<EventID>4698<"1 TERM1 "<EventID>4688<"1 "@"1 "/create"1 "-L"1 "-R"1 "-N"1 "-D"1 "-C"1 "IdentitiesOnly=yes"1 "StrictHostKeyChecking=no"1 "ssh"