Skip to main content

Pivoting with Ligolo-ng

Project GitHub

https://github.com/nicocha30/ligolo-ng

Download Binaries

https://github.com/nicocha30/ligolo-ng/releases

  • Proxy
    • Requires user to create a tun interface
    • Traffic flows through tun interface, like a VPN
    • ⚠️Requires root access on the host, in order to create the tun interface⚠️
  • Agent
    • Connects to the proxy and effectively establishes a VPN tunnel with the server
    • Does not require administrative privileges

Function to Auto-Download the Latest Stable Release

You can add this to your .zshrc or other .rc file to have this function available at login

Click to show code
function download_ligolo() {

    # Use the "latest" slug to always grab the newest stable release
    latest_release_url='https://github.com/nicocha30/ligolo-ng/releases/latest'
    # Get the base URL of the latest stable tagged version
    # Remove any trailing spaces
    latest_stable_url=$(curl -sI "$latest_release_url" | grep location | awk -v FS=' ' '{print $2}' | sed -E 's/\s{1,}$//g')

    # Use the tagged release URL and swap out `tag` for `download` in the URL
    download_base_url=$(echo -n "$latest_stable_url" | sed 's/tag/download/g')    
    binary_version=$(echo "$latest_stable_url" | rev | cut -d '/' -f 1 | rev | tr -d 'v')
    
    linux_proxy_binary_name="ligolo-ng_proxy_${binary_version}_linux_amd64.tar.gz"
    linux_agent_binary_name="ligolo-ng_agent_${binary_version}_linux_amd64.tar.gz"
    linux_proxy_download_url="${download_base_url}/${linux_proxy_binary_name}"
    linux_agent_download_url="${download_base_url}/${linux_agent_binary_name}"
    linux_proxy_output_name='ligolo-proxy.tar.gz'
    linux_agent_output_name='ligolo-agent.tar.gz'
    
    windows_proxy_binary_name="ligolo-ng_proxy_${binary_version}_windows_amd64.zip"
    windows_agent_binary_name="ligolo-ng_agent_${binary_version}_windows_amd64.zip"    
    windows_proxy_download_url="${download_base_url}/${windows_proxy_binary_name}"
    windows_agent_download_url="${download_base_url}/${windows_agent_binary_name}"
    windows_proxy_output_name='ligolo-proxy.exe.zip'
    windows_agent_output_name='ligolo-agent.exe.zip'

    # Download, extract, set mode
    curl -sL $linux_proxy_download_url -o "$PWD/${linux_proxy_output_name}"
    curl -sL $linux_agent_download_url -o "$PWD/${linux_agent_output_name}"
    
    curl -sL $windows_proxy_download_url -o "$PWD/${windows_proxy_output_name}"
    curl -sL $windows_agent_download_url -o "$PWD/${windows_agent_output_name}"
    
    tar -xzf $linux_proxy_output_name proxy > /dev/null
    tar -xzf $linux_agent_output_name agent > /dev/null

    unzip $windows_proxy_output_name -x README.md LICENSE > /dev/null
    unzip $windows_agent_output_name -x README.md LICENSE > /dev/null
    
    chmod u+x ./proxy ./agent > /dev/null
    
    echo "Linux and Windows Ligolo-ng binaries downloaded and unarchived in $PWD"

}

Example Data Flow

Ligolo-ng is not port forwarding in the way you might be familiar with it using tools like ssh or chisel.

Ligolo-ng operates at layer 3 and up of the OSI model, focusing on IP routing. SSH and Chisel operate at layer 4 and up of the OSI model, focusing on TCP/UDP transport and SOCKS.

Ligolo-ng can be thought of more like a VPN server. There's a server component, the proxy, and a client component, the agent. However, the roles are slightly reversed here, where the routes are published on the proxy side and exit out the agent side.

When you enter a destination IP address and port, if the route exists, it goes through the target interface, through the tunnel, and exits out the agent side to its destination.

Reaching Ports on Loopback

Show / Hide Diagram
                                                                               Post-compromise
                                                                               identify target route(s)
                                                                               to which TARGET has access
                                                                               
                                                                                * 127.0.0.1 (localhost) 
                                                                                  aliased to 240.0.0.1

                                 AGENT INITIALIZES TLS HANDSHAKE        
 ______________                                                                  ______________
|              |            << ==========[ TLS ENCRYPTION ]========== [+]       |              |
|  ATTACK BOX  |      __________________________________________________________|    TARGET    |____
|    proxy     |     |                                                          |     agent    |    |
|              |     |      [+] =========[ TLS ENCRYPTION ]========== >>        |              |    |
'______________'     |                                                          '______________'    |
                     |           CRYPTOGRAPHIC TUNNEL ESTABLISHED                                   |
 240.0.0.1:3306 [+]--'                                                          127.0.0.1:3306  <<--'
 
 
Add routes to target network(s):                                          Traffic exits out agent
                                                                          If route exists in agent routing table,
interface_add_route --name INTERFACE --route 240.0.0.1/32                 or default gateway

                                                                           * Firewalls may block traffic

Pivoting to Local Area Network

Show / Hide Diagram

                                AGENT INITIALIZES TLS HANDSHAKE        
 ______________                                                                   ______________                            ______________
|              |             << ========[ TLS ENCRYPTION ]======== [+]           |              |                          |              |
|  ATTACK BOX  |       ____________________________________________________      |    TARGET    |                          |              |
|    proxy     |      |                                                    |     |     agent    |    ,---[ packets ]--- >> | 192.168.10.3 |
|              |      |      [+] =======[ TLS ENCRYPTION ]======== >>      |     |              |    |                     |              |
'______________'      |                                                    |     '______________'    |                     '______________'
    Port Scan         |         CRYPTOGRAPHIC TUNNEL ESTABLISHED           |                         |
 192.168.10.3/24 [+]--'                                                    '--------- [eth0] --------'
                                                                               192.168.10.10/24
Add routes to target network(s):

interface_add_route --name INTERFACE --route 192.168.10.0/24

Pivoting to Other Networks

Show / Hide Diagram (Dual-Homed Host)

                               AGENT INITIALIZES TLS HANDSHAKE        
 ______________                                                                  ______________                            _____________
|              |            << ========[ TLS ENCRYPTION ]======== [+]           |              |                          |             |
|  ATTACK BOX  |      ____________________________________________________      |    TARGET    |                          |             |
|    proxy     |     |                                                    |     |     agent    |    ,---[ packets ]--- >> | 172.16.1.44 |
|              |     |      [+] =======[ TLS ENCRYPTION ]======== >>      |     |              |    |                     |             |
'______________'     |                                                    |     '______________'    |                     '_____________'
   Port Scan         |         CRYPTOGRAPHIC TUNNEL ESTABLISHED           |                         |
 172.16.1.44/24 [+]--'                                                    '----- [eth0]   [eth1] ---'
                                                                       192.168.10.10/24   172.16.1.22/24
Add routes to target network(s):                                                    '-------'

interface_add_route --name INTERFACE --route 172.16.1.0/24

Dual-Homed Host

Show / Hide Diagram (Packets to Firewall)

                               AGENT INITIALIZES TLS HANDSHAKE                                                                  ,. . . . ,
 ______________                                                                  ______________                               :     ^      :
|              |            << ========[ TLS ENCRYPTION ]======== [+]           |              |                           ::       |       ::
|  ATTACK BOX  |      ____________________________________________________      |    TARGET    |                          ::        |        ::
|    proxy     |     |                                                    |     |     agent    |    ,---[ packets ]--- >> :: <------|------> ::
|              |     |      [+] =======[ TLS ENCRYPTION ]======== >>      |     |              |    |                     ::        |        ::
'______________'     |                                                    |     '______________'    |                      ::       |       ::
   Port Scan         |         CRYPTOGRAPHIC TUNNEL ESTABLISHED           |                         |                        :      v      :
 172.16.1.44/24 [+]--'                                                    '--------- [eth0]---------'                          " . . . . "
                                                                                 192.168.10.10/24                               [firewall]
Add routes to target network(s):                                                                                             192.168.10.1/24
                                                                                                                                    |
interface_add_route --name INTERFACE --route 172.16.1.0/24                                                                          |
                                                                                                                                    |
                                                                                                                                    |
                                                                                                                                    |
                                                                                                                                    V
                                                                                                                           [Target Network(s)]
                                                                                                                              172.16.1.0/24
                                                                                                                        .------.          .------.
                                                                                                                        |      |          |      |
                                                                                                                        |      | .------. |      |
                                                                                                                        '------' |      | '------'
                                                                                                                        .------. |      | .------.
                                                                                                                        |      | '------' |      |
                                                                                                                        |      |          |      |
                                                                                                                        '------'          '------'

Packets Moved by Firewall

Routing to Target Network(s)

1. Identify Network(s) on Target

Once a reverse shell has been established on the target, run some commands to establish any IP configurations or routes available on the target host.

Linux

# Show routes on the target
ip route show
# Show any IP configurations on the target
ip addr show
# Show any IP addresses cached in the ARP table
ip neighbor

If certain binaries are not installed on the box and are preventing you from enumerating IP configurations, routes, and / or hostnames, try some of these tricks here

Windows

# Show routes on the target
Get-NetRoute
# Show any IP configurations on the target
Get-NetIPConfiguration
# Show any IP addresses cached in the ARP table
Get-NetNeighbor

PowerShell

# Show routes on the target
route print
# Show any IP configurations on the target
ipconfig
# Show any IP addresses cached in the ARP table
arp -a

cmd.exe

2. Listener on Attack Box

2.a — Start the Ligolo Proxy on Attack Box

sudo ./proxy -selfcert --selfcert-domain pwnz -laddr 10.10.10.9:443

Start the proxy on tcp/443 on 10.10.10.9

ligolo-ng » certificate_fingerprint

Show the self-signed certificate fingerprint

2.b — Connect Agent to the Proxy

Linux
/tmp/agent -accept-fingerprint SHA_256_SELF_SIGNED_FINGERPRINT -connect 10.10.10.9:443 &

Use the fingerprint of the self-signed certificate from above and run in the background

Windows
Start-Job -ScriptBlock { C:\Path\To\agent.exe -accept-fingerprint SHA_256_SELF_SIGNED_FINGERPRINT -connect 10.10.10.9:443 }

Use the fingerprint of the self-signed certificate from above and run in the background

2.c — Create and Start the Tunnel

In most cases where specifying --name or --tun, I am using the target hostname or challenge name as the identifier. This helps when you're managing multiple sessions.

ligolo-ng » session

Choose the session number for your target agent

[Agent : user@target_hostname] » interface_create --name target_hostname

Create an interface for this session, you could use the target hostname, for example

[Agent : user@target_hostname] » interface_add_route --name target_hostname --route 172.32.1.0/24

Add any routes to target network(s), issue the command as many times as needed

[Agent : user@target_hostname] » tunnel_start --tun target_hostname

Start the tunnel and move traffic to target route(s)

Tips and Tricks

Accessing Agent Ports

In this example, the host that is running the agent process has some internal port bindings on 127.0.0.1. Ligolo-ng uses 240.0.0.1/32 to route traffic to loopback address on the agent side of the tunnel.

Ligolo Command

[Agent : user@target_hostname] » interface_add_route --name target_hostname --route 240.0.0.1/32

Scan Agent Ports

sudo nmap -Pn -sT -p3000 240.0.0.1

Scan tcp/3000 on 127.0.0.1 on the agent side of the tunnel

Tunneling to a Single Host

Use a /32 network mask to tunnel to a single host

[Agent : user@target_hostname] » interface_add_route --name target_hostname --route 172.32.1.228/32