Networking
How to best communicate between you and everything on your target
Last updated
How to best communicate between you and everything on your target
Last updated
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:
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.
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 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:
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:
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 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:
With this set, you can now simply prepend proxychains
to the command, and your localhost becomes the target localhost!
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
).
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:
You should instantly receive a "Agent joined" message in your server, choose it using session
:
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):
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.
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:
Now, you should be able to reach into this internal network through the tunnel using tools like nmap
:
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:
Now a deeper client can connect to the compromised agent, as it should be reachable:
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:
Finally, you can add the routes of this new client to your interface:
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: