Detection rules › Splunk

Scheduled Task with Potential SSH Tunnel - Windows (Sysmon)

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

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>

MITRE ATT&CK coverage

TacticTechniques
ExecutionT1053 Scheduled Task/Job
PersistenceT1053 Scheduled Task/Job
Privilege EscalationT1053 Scheduled Task/Job
Command & ControlT1572 Protocol Tunneling

References

Event coverage

ProviderEventTitle
SysmonEvent ID 1Process creation

Rule body yaml

id: '25326.47104'
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_sysmon` (TERM(EventCode=1) OR "<EventID>1<")
  "@" "/create" ("-L" OR "-R" OR "-N" OR "-D" OR "-C" OR "IdentitiesOnly=yes" OR "StrictHostKeyChecking=no"
  OR "ssh") | where 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:
- Windows Sysmon
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_sysmon` (TERM(EventCode=1) OR "<EventID>1<") "@" "/create" ("-L" OR "-R" OR "-N" OR "-D" OR "-C" OR "IdentitiesOnly=yes" OR "StrictHostKeyChecking=no" OR "ssh")

Stage 2: where

| where 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

| bin span=1s

Stage 5: stats

| stats values(*) as * by _time, host

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.

FieldKindValues
EventCodeeq
  • 1 corpus 237 (splunk 224, kusto 13)
processmatch
  • "(?i)\-(L|R|N|D|C)|IdentitiesOnly=yes|StrictHostKeyChecking=no|ssh" corpus 3 (splunk 3)
  • "\d{1,5}:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{1,5}" corpus 3 (splunk 3)
  • "\w+@\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" corpus 3 (splunk 3)

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.

StageTerm
1TERM
1"<EventID>1<"
1"@"
1"/create"
1"-L"
1"-R"
1"-N"
1"-D"
1"-C"
1"IdentitiesOnly=yes"
1"StrictHostKeyChecking=no"
1"ssh"