Pivoting through SSH is one of the most convenient methods. If you have the opportunity to perform port forwarding with this protocol, it’s one of the best options.

Table of Contents:

Introduction

SSH allows us 3 modes of port forwarding:

  • Local Port Forwarding
  • Remote Port Forwarding
  • Dynamic Port Forwarding

The “lab” for this post is as follows:

  • 3 Machines:
    • Kali: My attacker machine
      • IP: 192.168.10.10
    • Debian: SSH service enabled
      • IP: 192.168.10.20 and 192.168.20.10 (2 Network Interfaces)
    • Debian: Apache2 server enabled
      • IP: 192.168.20.20 and 192.168.30.10 (2 Network Interfaces, although the second one is irrelevant for this post)

Lab diagram with three machines for SSH pivoting

Lab

The goal is to reach the Debian that has the web server from Kali. Based on how the networks are distributed above, we can quickly realize that there is no direct connection between one machine and another. However, we’re going to take advantage of the Debian that acts as an SSH server and also has a connection to both networks to be able to reach the web server from Kali.

Local Port Forwarding

In this case, we take advantage of the SSH session to open a port on our Kali that will redirect to the selected machine and ports, using the server we connect to via SSH as pivoting.

The syntax and idea is as follows:

Local Port Forwarding syntax with SSH

Syntax

With this in mind, we proceed:

SSH command with Local Port Forwarding from Kali

Kali - SSH Server Connection

As we can see, the syntax used is:

ssh -L 80:192.168.20.20:80 sikumy@192.168.10.20

Explained in words, it’s as follows:

With the -L parameter, we indicate that we want to do Local Port Forwarding. The first port we specify is the port we open locally that will tunnel to the service. Subsequently, the specified IP and port is what we want to access and reach from our local port. All of this through the machine on which we start an SSH session.

So at this point, if we go to the browser while keeping the SSH session open and go to the address: http://localhost/, we’ll see the web server:

Web server accessible from localhost through SSH tunnel

Web Server tunneled to localhost

This way, we can access all ports of all IPs that the SSH server has access to.

When we close the connection we will also lose the port forwarding:

SSH session closed with exit

End of SSH Connection

Connection error when closing SSH tunnel

End of Web Server Connection

Remote Port Forwarding

Remote Port Forwarding is a bit different from Local Port Forwarding. It doesn’t change much at the syntax level but it does at the conceptual level.

The syntax in this case is as follows:

ssh -R <port to open on the machine you connect to>:<address to point to>:<port to point to on the address> <user>@<kali address>

The peculiarity of Remote Port Forwarding is that we don’t start a session on the SSH server we have defined in the lab. Instead, in this case, it’s the reverse, from the SSH server we have, we start a session on our Kali machine (we would need to enable the SSH service).

Looking at it from the attacker and victim point of view, if we treat Kali as the attacker and Debian (SSH server) as the victim, we can realize that on the victim machine, we would be entering credentials from our machine. From a security standpoint, this is not optimal, which is why Local Port Forwarding is always used, as it doesn’t have this danger.

So, returning to practice, we would execute the following on Debian (SSH server):

SSH command with Remote Port Forwarding from Debian to Kali

Login Session on Kali

As we can see, the command for Remote Port Forwarding is:

ssh -R 80:192.168.20.20:80 user@192.168.10.10

This way, since we’re starting a session on Kali, we’re telling it to open port 80 and point to the Debian that acts as a web server. We can do this because the Debian from which we connect has access to both networks, therefore it’s possible to connect them.

With this done, if we go to localhost from Kali:

Web server accessible from Kali through Remote Port Forwarding

Localhost

We can see that we can perfectly access the web server.

And just like in Local Port Forwarding, the moment we close the SSH session, we lose the connection:

SSH session closed with exit in Remote Port Forwarding

exit

Connection error when closing Remote Port Forwarding tunnel

Connection lost

Dynamic Port Forwarding

This can be the most peculiar type of Port Forwarding but very useful in certain situations. Dynamic Port Forwarding, in a summarized and loosely speaking way, allows us to tunnel all ports of the entire network that the SSH server has access to. This happens because with this mode, we can make SSH act as a SOCKS proxy:

SOCKS proxy definition

SOCKS Proxy Definition

The syntax to achieve this is the simplest of all:

ssh -D <local port that will act as proxy> <user>@<IP>

Therefore:

SSH command with Dynamic Port Forwarding creating SOCKS proxy

SSH Connection with Dynamic Port Forwarding

This way, we now have a SOCKS proxy on our local port 8080.

If, for example, from Firefox, we go to “Settings > Network Settings”, we can tell it to use this port as a SOCKS proxy:

SOCKS proxy configuration in Firefox

Proxy Configuration in Firefox

Now, we no longer need to access localhost as we did in Local or Remote Port Forwarding. This way, we can go directly:

Direct access to web server using SOCKS proxy

Web Server through SOCKS Proxy

As we can see, it appears as if we were on the same network as the web server. The question at this point is:

  • Can we use this with other tools, for example, nmap?

Well, we can indeed use nmap as well as other utilities. It’s true that there are certain limitations, but we can, and sometimes it’s very useful. To do this we’ll use Proxychains.

Conclusion + Important Info

Something I haven’t mentioned until now is that in any of the 3 modes, you can use as many arguments as you want, meaning you can put multiple -L to create multiple Local Port Forwarding in the same session. This also applies to Remote and Dynamic Port Forwarding.

Example with Dynamic:

Creating two simultaneous SOCKS proxies with SSH

2 SOCKS Proxies

This way, we can tunnel as many ports as we want (if we’re talking about local and remote).

And these are the three main ways to do pivoting with SSH. Additionally, as an extra fact, all connections work on top of the security layer provided by this protocol, so all connections will be encrypted.