Potential SSH Reverse Port Forwarding

Identifies the use of Windows OpenSSH or Plink to create a reverse SSH port forward or reverse dynamic SOCKS proxy. Adversaries may abuse reverse forwarding to expose an internal service or proxy listener through an external SSH server, establishing an outbound tunnel that bypasses direct inbound connectivity controls.

Elastic rule (View on GitHub)

  1[metadata]
  2creation_date = "2026/06/24"
  3integration = ["endpoint", "windows", "sentinel_one_cloud_funnel", "m365_defender", "system", "crowdstrike"]
  4maturity = "production"
  5updated_date = "2026/06/24"
  6
  7[rule]
  8author = ["Elastic"]
  9description = """
 10Identifies the use of Windows OpenSSH or Plink to create a reverse SSH port forward or reverse dynamic SOCKS proxy.
 11Adversaries may abuse reverse forwarding to expose an internal service or proxy listener through an external SSH server,
 12establishing an outbound tunnel that bypasses direct inbound connectivity controls.
 13"""
 14from = "now-9m"
 15index = [
 16  "endgame-*",
 17  "logs-crowdstrike.fdr*",
 18  "logs-endpoint.events.process-*",
 19  "logs-m365_defender.event-*",
 20  "logs-sentinel_one_cloud_funnel.*",
 21  "logs-system.security*",
 22  "logs-windows.forwarded*",
 23  "logs-windows.sysmon_operational-*",
 24  "winlogbeat-*",
 25]
 26language = "eql"
 27license = "Elastic License v2"
 28name = "Potential SSH Reverse Port Forwarding"
 29references = [
 30  "https://thedfirreport.com/2025/11/04/from-bing-search-to-ransomware-bumblebee-and-adaptixc2-deliver-akira-2/",
 31  "https://thedfirreport.com/2023/10/30/netsupport-intrusion-results-in-domain-compromise/",
 32  "https://x.com/Securityinbits/status/2067602540209021196",
 33]
 34risk_score = 21
 35rule_id = "86817045-ea22-4038-9959-c3437bc4c064"
 36severity = "low"
 37tags = [
 38  "Domain: Endpoint",
 39  "OS: Windows",
 40  "Use Case: Threat Detection",
 41  "Tactic: Command and Control",
 42  "Tactic: Lateral Movement",
 43  "Data Source: Elastic Defend",
 44  "Data Source: SentinelOne",
 45  "Data Source: Microsoft Defender XDR",
 46  "Data Source: Windows Security Event Logs",
 47  "Data Source: Crowdstrike",
 48  "Data Source: Sysmon",
 49  "Data Source: Elastic Endgame",
 50  "Resources: Investigation Guide",
 51]
 52timestamp_override = "event.ingested"
 53type = "eql"
 54
 55query = '''
 56process where host.os.type == "windows" and event.type == "start" and
 57  (
 58    process.name : ("ssh.exe", "plink.exe") or
 59    ?process.pe.original_file_name : ("Plink", "plink.exe")
 60  ) and
 61  (
 62    process.args : "-R*" or
 63    process.args : "-oRemoteForward*" or
 64    (process.args : "-o" and process.args : "*RemoteForward*") or
 65
 66    /* -R can be combined with ~20 no-arg SSH flags (e.g. -NR, -fNR) */
 67    process.command_line regex """.*\s-[A-Za-z]*R[^A-Za-z].*"""
 68  )
 69'''
 70
 71note = """## Triage and analysis
 72
 73### Investigating Potential SSH Reverse Port Forwarding Detected
 74
 75#### Possible investigation steps
 76
 77- What reverse-forward command triggered the alert?
 78  - Focus: `@timestamp`, `host.id`, `user.name`, `process.name`, `process.command_line`
 79  - Implication: Confirm via $investigate_0 a process start for `ssh.exe` or `plink.exe`/Plink with the matched `-R` or `RemoteForward` artifact. Suspicious when the command exposes an internal service or SOCKS listener without host/account owner confirmation; close only when command, host, account, parent, and remote-forward values match a recognized recurring tunnel workflow for this account.
 80- Is the process lineage and executable consistent with the expected workflow?
 81  - Focus: `process.parent.command_line`, `process.executable`, `process.hash.sha256`, `process.working_directory`, `process.Ext.relative_file_creation_time`
 82  - Implication: Via $investigate_0, compare parent, path, hash, and file age. Escalate when shells, script interpreters, unusual parents, recently created binaries, or a Plink original name under another process name appear; benign requires the same artifact and parent tied to the verified host/account reverse-forward workflow.
 83- Is the tunnel active or recurring on this host?
 84  - Focus: `host.id`, `process.entity_id`, `process.pid`, `process.uptime`, `process.exit_code`
 85  - Implication: Use $investigate_1 to check whether the SSH/Plink process remained running, exited, or relaunched with reverse-forward arguments. Recurring or long-lived commands outside a confirmed window are suspicious; a single exited process supports closure only with owner confirmation and no unresolved process or network evidence.
 86- What remote SSH server and exposed service are implied?
 87  - Focus: `process.args`, `process.command_line`, `destination.ip`, `destination.port`, `network.direction`
 88  - Implication: Parse `-R`/`RemoteForward` syntax, then recover same-process connection events if network telemetry exists; `destination.*` and `network.*` are connection-event fields not present on the process alert. Missing network telemetry is unresolved, not benign. Escalate when the remote host, port, or exposed service does not match the confirmed workflow.
 89- Where else does the same binary or reverse-forward pattern appear?
 90  - Focus: `process.hash.sha256`, `process.name`, `host.name`, `user.name`, `process.command_line`
 91  - Implication: Use $investigate_2 to scope the same hash, comparing command lines for `-R`/`RemoteForward` on other hosts/accounts. Absence of matches is not benign; broaden containment when the artifact appears beyond the source host/account. Close recurrence only when each match ties to the same confirmed workflow.
 92
 93Disposition: Escalate suspicious or unresolved commands; close only when alert-local and recovered evidence confirm the exact host/account/process/remote-forward scope; preserve and escalate mixed cases.
 94
 95### False positive analysis
 96
 97- Benign activity is limited to a confirmed reverse SSH forwarding workflow where `process.command_line`, `host.id`, `user.name`, parent process, executable, remote server, and forward port are verified.
 98- Do not close because the binary is named `ssh.exe`/`plink.exe`, has a familiar path, or a trusted signature — the matched command and owner workflow must explain the `-R`/`RemoteForward` artifact.
 99- Scope exceptions to `host.id`, `user.name`, `process.executable` or `process.hash.sha256`, `process.parent.executable` or `process.parent.command_line`, and the exact reverse-forward args. Do not suppress all reverse forwarding across hosts or accounts.
100
101### Response and remediation
102
103- Scope first by reviewing the exact command, same-process network evidence, same executable hash, same user/host activity, and related alerts for the same remote SSH server or port before cleanup.
104- Preserve or export case evidence plus volatile process, memory, executable, and file-system artifacts before isolation, process termination, or other disruptive action.
105- After evidence capture, use reversible containment such as isolating the affected host or blocking egress to the confirmed SSH server/port while credential and session review proceeds.
106- For confirmed malicious tunneling, terminate the SSH/Plink process, remove persistence or scripts that launched it, rotate exposed credentials, and clean staged binaries only after scoping.
107- Record confirmed indicators and logging or detection gaps for the responsible detection or logging owners after containment.
108"""
109setup = """## Setup
110
111This rule is designed for data generated by [Elastic Defend](https://www.elastic.co/security/endpoint-security), which provides native endpoint detection and response, along with event enrichments designed to work with our detection rules.
112
113Setup instructions: https://ela.st/install-elastic-defend
114
115### Additional data sources
116
117This rule also supports the following third-party data sources. For setup instructions, refer to the links below:
118
119- [CrowdStrike](https://ela.st/crowdstrike-integration)
120- [Microsoft Defender XDR](https://ela.st/m365-defender)
121- [SentinelOne Cloud Funnel](https://ela.st/sentinel-one-cloud-funnel)
122- [Sysmon Event ID 1 - Process Creation](https://ela.st/sysmon-event-1-setup)
123- [Windows Process Creation Logs](https://ela.st/audit-process-creation)
124"""
125
126[rule.investigation_fields]
127field_names = [
128  "@timestamp",
129  "host.name",
130  "user.name",
131  "user.id",
132  "user.domain",
133  "process.entity_id",
134  "process.name",
135  "process.executable",
136  "process.command_line",
137  "process.parent.executable",
138  "process.parent.command_line",
139]
140
141[[transform.investigate]]
142label = "Matched process context"
143description = "Recover the process start event and immediate process context for the alerted OpenSSH or Plink reverse-forward command."
144providers = [
145  [
146    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
147    { excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" },
148  ],
149]
150relativeFrom = "now-1h"
151relativeTo = "now"
152
153[[transform.investigate]]
154label = "Same host process launches"
155description = "Find other process events with the same alerted process name on the same host for local recurrence and parent/account comparison."
156providers = [
157  [
158    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
159    { excluded = false, field = "process.name", queryType = "phrase", value = "{{process.name}}", valueType = "string" },
160  ],
161]
162relativeFrom = "now-24h"
163relativeTo = "now"
164
165[[transform.investigate]]
166label = "Executable hash scope"
167description = "Find other events for the same executable hash to scope repeated use of the matched OpenSSH or Plink binary after local validation."
168providers = [
169  [
170    { excluded = false, field = "process.hash.sha256", queryType = "phrase", value = "{{process.hash.sha256}}", valueType = "string" },
171  ],
172]
173relativeFrom = "now-7d"
174relativeTo = "now"
175
176[[rule.threat]]
177framework = "MITRE ATT&CK"
178
179[[rule.threat.technique]]
180id = "T1090"
181name = "Proxy"
182reference = "https://attack.mitre.org/techniques/T1090/"
183
184[[rule.threat.technique.subtechnique]]
185id = "T1090.002"
186name = "External Proxy"
187reference = "https://attack.mitre.org/techniques/T1090/002/"
188
189[[rule.threat.technique]]
190id = "T1572"
191name = "Protocol Tunneling"
192reference = "https://attack.mitre.org/techniques/T1572/"
193
194[rule.threat.tactic]
195id = "TA0011"
196name = "Command and Control"
197reference = "https://attack.mitre.org/tactics/TA0011/"
198
199[[rule.threat]]
200framework = "MITRE ATT&CK"
201
202[[rule.threat.technique]]
203id = "T1021"
204name = "Remote Services"
205reference = "https://attack.mitre.org/techniques/T1021/"
206
207[[rule.threat.technique.subtechnique]]
208id = "T1021.004"
209name = "SSH"
210reference = "https://attack.mitre.org/techniques/T1021/004/"
211
212[rule.threat.tactic]
213id = "TA0008"
214name = "Lateral Movement"
215reference = "https://attack.mitre.org/tactics/TA0008/"

Triage and analysis

Investigating Potential SSH Reverse Port Forwarding Detected

Possible investigation steps

  • What reverse-forward command triggered the alert?
    • Focus: @timestamp, host.id, user.name, process.name, process.command_line
    • Implication: Confirm via $investigate_0 a process start for ssh.exe or plink.exe/Plink with the matched -R or RemoteForward artifact. Suspicious when the command exposes an internal service or SOCKS listener without host/account owner confirmation; close only when command, host, account, parent, and remote-forward values match a recognized recurring tunnel workflow for this account.
  • Is the process lineage and executable consistent with the expected workflow?
    • Focus: process.parent.command_line, process.executable, process.hash.sha256, process.working_directory, process.Ext.relative_file_creation_time
    • Implication: Via $investigate_0, compare parent, path, hash, and file age. Escalate when shells, script interpreters, unusual parents, recently created binaries, or a Plink original name under another process name appear; benign requires the same artifact and parent tied to the verified host/account reverse-forward workflow.
  • Is the tunnel active or recurring on this host?
    • Focus: host.id, process.entity_id, process.pid, process.uptime, process.exit_code
    • Implication: Use $investigate_1 to check whether the SSH/Plink process remained running, exited, or relaunched with reverse-forward arguments. Recurring or long-lived commands outside a confirmed window are suspicious; a single exited process supports closure only with owner confirmation and no unresolved process or network evidence.
  • What remote SSH server and exposed service are implied?
    • Focus: process.args, process.command_line, destination.ip, destination.port, network.direction
    • Implication: Parse -R/RemoteForward syntax, then recover same-process connection events if network telemetry exists; destination.* and network.* are connection-event fields not present on the process alert. Missing network telemetry is unresolved, not benign. Escalate when the remote host, port, or exposed service does not match the confirmed workflow.
  • Where else does the same binary or reverse-forward pattern appear?
    • Focus: process.hash.sha256, process.name, host.name, user.name, process.command_line
    • Implication: Use $investigate_2 to scope the same hash, comparing command lines for -R/RemoteForward on other hosts/accounts. Absence of matches is not benign; broaden containment when the artifact appears beyond the source host/account. Close recurrence only when each match ties to the same confirmed workflow.

Disposition: Escalate suspicious or unresolved commands; close only when alert-local and recovered evidence confirm the exact host/account/process/remote-forward scope; preserve and escalate mixed cases.

False positive analysis

  • Benign activity is limited to a confirmed reverse SSH forwarding workflow where process.command_line, host.id, user.name, parent process, executable, remote server, and forward port are verified.
  • Do not close because the binary is named ssh.exe/plink.exe, has a familiar path, or a trusted signature — the matched command and owner workflow must explain the -R/RemoteForward artifact.
  • Scope exceptions to host.id, user.name, process.executable or process.hash.sha256, process.parent.executable or process.parent.command_line, and the exact reverse-forward args. Do not suppress all reverse forwarding across hosts or accounts.

Response and remediation

  • Scope first by reviewing the exact command, same-process network evidence, same executable hash, same user/host activity, and related alerts for the same remote SSH server or port before cleanup.
  • Preserve or export case evidence plus volatile process, memory, executable, and file-system artifacts before isolation, process termination, or other disruptive action.
  • After evidence capture, use reversible containment such as isolating the affected host or blocking egress to the confirmed SSH server/port while credential and session review proceeds.
  • For confirmed malicious tunneling, terminate the SSH/Plink process, remove persistence or scripts that launched it, rotate exposed credentials, and clean staged binaries only after scoping.
  • Record confirmed indicators and logging or detection gaps for the responsible detection or logging owners after containment.

References

Related rules

to-top