In a reverse SSH tunnel the compromised host initiates an outbound connection to an operator-controlled server and requests a remote forward with -R. The operator then connects to a loopback port on their own server and reaches the victim’s SSH, RDP or shell. autossh and a service wrapper keep the tunnel alive across drops and reboots, which gives defenders both process and persistence artifacts to find.
Signals at a Glance
| Signal | Where | ATT&CK |
|---|---|---|
| ssh -R or autossh with -R and -N from a server or workstation | auditd, Sysmon for Linux, EDR | T1572 |
| autossh or ssh invoked from cron, systemd or rc scripts | auditd, journald, file events | T1543.002 |
| Crontab @reboot or systemd unit whose ExecStart is an ssh tunnel | File integrity monitoring | T1053.003 |
| Hours-long outbound SSH to an external VPS or residential address | Firewall, Zeek conn.log | T1090 |
| Private key created and used without interactive logon | File events, auth logs | T1021.004 |
Process and Persistence Patterns
The reverse direction is defined by the -R flag, and persistence wrappers add -M 0, -o ServerAliveInterval, -N and -f. The combination of remote forwarding, no remote command and keepalive options is characteristic. A Sigma rule for Linux:
title: Reverse SSH Tunnel or autossh Remote Forward
logsource:
category: process_creation
product: linux
detection:
selection_autossh:
Image|endswith: '/autossh'
selection_ssh:
Image|endswith: '/ssh'
CommandLine|contains: ' -R '
selection_opts:
CommandLine|contains:
- ' -N'
- 'ServerAliveInterval'
- 'ExitOnForwardFailure'
condition: selection_autossh or (selection_ssh and selection_opts)
level: high
# tune/validate: expect bastion and support-tooling matches; scope by host
# role and the destination address, not the flags alone.
For persistence, review the units and cron entries that start the wrapper. A user-level systemd service or an @reboot crontab line that calls autossh or ssh -R on a server is rarely benign:
// Microsoft Defender XDR (KQL) - autossh / ssh -R on Linux endpoints
DeviceProcessEvents
| where Timestamp > ago(14d)
| where (FileName =~ "autossh")
or (FileName =~ "ssh" and ProcessCommandLine has " -R ")
| where ProcessCommandLine has_any (" -N", "ServerAliveInterval", "ExitOnForwardFailure")
| project Timestamp, DeviceName, AccountName, ProcessCommandLine,
InitiatingProcessFileName, InitiatingProcessCommandLine
// tune/validate: join to DeviceNetworkEvents on the process id to see the
// external destination and the session lifetime.
Network and Host Context
- Alert on any server that begins long-lived outbound SSH to an address outside your approved list; servers rarely initiate SSH to the Internet.
- Look for key material written by a non-interactive process (for example under
/tmpor a service account home) shortly before the tunnel starts. - Review
authorized_keyschanges and new keypairs in the same time window. - Egress-filter SSH to a managed allow-list; deny by default and log.
Use SigmaHQ Linux process-creation rules for SSH tunneling, Elastic detection rules for SSH and autossh persistence, Splunk ESCU analytic stories for Linux persistence, MITRE CAR and your auditd baseline. Always baseline your own environment — support and monitoring tools sometimes use reverse tunnels on purpose and must be documented.
Build Detections That Fire
Mjolnir Security helps blue teams turn threat intelligence into high-fidelity detections across endpoint, network, identity and cloud telemetry.
- Detection Engineering We build and tune detections mapped to ATT&CK from your own telemetry.
- Threat Hunting as a Service Hypothesis-driven hunts for the behaviours on this page.
- 24/7 Incident Response Containment when a detection fires. Call +1 833 403 5875.
Stay ahead of emerging threats. Get notified when we publish new intelligence reports and advisories.
Subscribe to Alerts