Jollyfrogs' pedantic guide to pivoting - part 1: SSH local port forwarding

 

"Pivoting is the act of tunneling traffic between two networks, through a computer under our control"

In part one of the SSH pivoting guide, I'll provide a detailed (pedantic) guide of the easiest form of pivoting which is depicted by the green arrow in the diagram above. If you would like to reproduce this pivoting guide in your local lab, click on the following links for installation guides:
Installing kali

Installing pivot-host-1

Installing target-1

Preparation tasks

All commands are run from the attacker machine "kali" unless explicitly stated

Pivoting is the act of tunneling traffic between two networks, through a computer under our control. Generally, pivoting is used to bypass a lack of routing between the networks, or to bypass a firewall which prevents routing between the two networks. There are various tools that can be used to pivot, including ssh client, sshuttle, meterpreter, iptables, python, a custom tool etc.

Due to the proliferation of secure shell (SSH) it makes sense to first detail how ssh can be used to pivot.
The two commands to pivot through 10.123.1.210 to 10.2.1.22:2222 using SSH local port forwarding are:

We will go into detail of what exactly happens 'under the hood' when we enter those two commands.

The best place to learn about the SSH protocol is the RFC document that describes it. There are a few RFCs that make up the description of the complete SSH protocol and the RFC that describes the SSH connection protocol is available at https://www.ietf.org/rfc/rfc4254.txt

Section "7. TCP/IP Port Forwarding" describes the component we will use to pivot, specifically:

We can demonstrate with an example how SSH local port forwarding works.

The following command creates a locally forwarded TCP/IP port on "kali" with some useful options.

The command above can be broken down as follows:

When we enter the command above, the following happens:

  • the ssh client starts up and sends itself to the background
  • the ssh client on "kali" connects to "pivot-host-1" via a new session we'll refer to as process-1
  • the ssh server on "pivot-host-1" accepts connection from "kali"
  • the ssh client on "kali" logs in with user "frog" and matching private key "id_rsa"
  • the ssh server on "pivot-host-1" logs in user based on match with a key in authorized_keys
  • the ssh client on "kali" creates a listener on port 9922 and waits for new connections

This is the relevant netstat output on "kali" after connecting:

And this is the relevant netstat output on "pivot-host-1" after connecting:

process-1 can be visually represented as follows:

Now that we have created a local ssh port-forwarding session on "kali", we can connect to the listening port 9922 to see what happens. The following command connects to local port 9922 on "kali" which was configured as an ssh local port-forward:

When we enter the command above, the following happens:

  • the ssh client on "kali" connects to its own port tcp/9922 as new process we'll refer to as process-2
  • backgrounded port-forward process process-1 accepts the connection
  • process-1 sends a "direct-tcpip" request to remote ssh server "pivot-host-1" with following contents
    • ssh request: "direct-tcpip"
    • host to connect: 10.2.1.22
    • port to connect: 2222
    • originator IP address: 127.0.0.1 (process-2 connection source IP)
    • originator port: 51210 (process-2 connection source port)
  • ssh server on "pivot-host-1" reads the "direct-tcpip" request
  • "pivot-host-1" looks up the routing table for destination IP 10.2.1.22 and confirms source interface 10.2.1.1
  • ssh server on "pivot-host-1" creates a new connection to 10.2.1.22:2222 from interface 10.2.1.1 port 33000
  • ssh server on "pivot-host-1" maps ssh connection from process-2 to the new connection to 10.2.1.22:2222
  • 10.2.1.22 port 2222 runs an SSH server, so we will be asked to login to the ssh server on "target-1"

This is the relevant netstat on "kali" after connecting to port 9922 on "kali":

And this is the relevant netstat on "pivot-host-1" after connecting to port 9922 on "kali":

process-2 can be visually represented as follows:

When process-2 connects to port 9922 on "kali", process-1 on "kali" tunnels the request via its existing ssh (port-forward) connection with "pivot-host-1". Host "pivot-host-1" connects the new connection to 10.2.1.22:2222 via its interface "10.2.1.1".

Pivoting into an unreachable network via SSH local port-forwarding can be useful when there are known ports on known hosts in the remote network. When hosts are not known, or ports are not known, setting up a large number of single port forwards is not practical. This is where ProxyChains takes over, and it will be covered in Part 2 of the detailed guide to pivoting.

 

 

 

Filed under: Jollyfrogs' pedantic guides Pivoting