Multiplayer pivoting solution
This thing is based on amazing work by nicocha30 on Ligolo-ng. I also borrowed quite a bit from Sliver codebase. Thanks, you people are amazing!
Ligolo-mp is a more specialized version of Ligolo-ng, with client-server architecture, enabling pentesters to play with multiple concurrent tunnels collaboratively. Also, with a sprinkle of less important bells and whistles.
Everything that you love about Ligolo-ng and:
On our local machine we use client to connect to a server, that's running on the attacking machine. Then we run an agent on the machine we want pivot through - a target machine. To actually start pivoting, we create a tun and use it to start a relay between server and agent. We can also start a listener to, for example, chain connections through agents in cases where target machine can't directly reach our server.
Here's a very professional visual:
Precompiled binaries (Windows/Linux/macOS) are available on the Release page.
Just refer to the makefile, but just for completeness sake:
# Build server
$ make assets server
# Build client
$ make client
# Build everything
$ make all
[Unit]
Description=Ligolo-mp
After=network.target
StartLimitIntervalSec=0
[Service]
Type=simple
Restart=on-failure
RestartSec=3
User=root
ExecStart=/usr/local/bin/ligolo-mp-server -daemon
[Install]
WantedBy=multi-user.target
$ ligolo-mp-server
...
ligolo-mp » operator new --name myoperator --server 127.0.0.1:58008 --path /home/kali/
Operator 'myoperator' added. Config is saved to '/home/kali/myoperator_127.0.0.1:58008_ligolo-mp.json'
$ ligolo-client -import /home/kali/myoperator_127.0.0.1:58008_ligolo-mp.json
Credentials successfully imported!
$ ligolo-client_linux
Use the arrow keys to navigate: ↓ ↑ → ←
Select credentials
operator
another_operator
-> myoperator
friendly_operator
--------- Agents ----------
Name: myoperator
Server: 127.0.0.1:58008
Use 'help' command, should be pretty self-explanatory
Create a TUN
ligolo-mp » tun new
[+] New TUN created: confident_euclid
ligolo-mp » tun route new 10.10.2.0/24 10.10.3.0/24 10.10.4.0/32
Selected: confident_euclid
[+] Route 10.10.2.0/24@confident_euclid created
[+] Route 10.10.3.0/24@confident_euclid created
[+] Route 10.10.4.0/32@confident_euclid created
-agentaddr
otherwise)$ agent generate --save /home/kali/agent --os linux --arch amd64 --server 127.0.0.1:11601 --obfuscate
[+] Agent binary saved to /home/kali/agent
# On target
$ ./agent
# On client
[+] Agent [email protected]/8,::1/128,192.168.2.53/24 joined
ligolo-mp »
ligolo-mp » relay start
Selected: bold_nash
Selected: confident_euclid
[+] Established a tunnel with agent [email protected]/8,::1/128,192.168.2.53/24
That's it, your pivot is ready to use. Using this flow you can maintain as many combinations of TUNs, routes and agents as you need.
Adding routes routine will check for overlaps in currently active TUNs and error out if that's the case. The only thing to keep in mind is that there's 1 to 1 mapping between agent and TUN, but I think there are enough railguards in place to prevent any undefined behavior.
If your agent dies, you can just restart in on the target machine and all the routes and the tunnel will be applied automatically. Also, if agent can't connect back to the server, it will retry indefinitely.
If you need to access the services running on the same machine that's running an agent, you can use --loopback
option for a TUN. Let me demonstrate:
Machine with agent bold_nash is running a service on 127.0.0.1:9999
Create a loopback TUN
$ ligolo-mp » tun new --loopback
[+] New TUN created: nervous_cori
$ ligolo-mp » tun route new 10.10.10.10/24
Selected: nervous_cori
[+] Route 10.10.10.10/24@nervous_cori created
$ ligolo-mp » relay start
Selected: bold_nash
Selected: nervous_cori
[+] Established a relay with agent [email protected]/8,::1/128,192.168.2.53/24
If your target machine (machine#1) can't reach the server directly, but can access a machine that's running another agent (machine#2), you can use listeners to proxy the traffic. So, to implement a chain machine#1<->machine#2<->server:
# 192.168.2.53 - bold_nash's address (you can also just use 0.0.0.0, if you want)
# 192.168.2.10 - server's address
ligolo-mp » listener new --from 192.168.2.53:1234 --to 192.168.2.10:11601
Selected: bold_nash
[+] Listener (bold_nash) from 192.168.2.53:1234 to 192.168.2.10:11601 started
# Notice the --server option, it's pointing to the listener
ligolo-mp » agent generate --save /home/kali/chained_agent --os linux --server 192.168.2.53:1234
[+] Agent binary saved to /home/kali/chained_agent
This listener is just a TCP redirector, so you can probably find more ways to use it.
If you just joined your friend's server, you probably need to see what's going on, you can do it with list
subcommand
$ ligolo-mp » tun list
┌───────────────────────────────────────────────┐
│ Active TUNs │
├────────────────┬────────────────┬─────────────┤
│ ALIAS │ ROUTES │ IS LOOPBACK │
├────────────────┼────────────────┼─────────────┤
│ gallant_kepler │ 11.11.11.0/24 │ false │
│ │ fe80::/64 │ │
│ nervous_cori │ fe80::/64 │ true │
│ │ 172.10.10.1/32 │ │
│ │ 10.11.0.0/16 │ │
│ │ 10.10.10.0/24 │ │
└────────────────┴────────────────┴─────────────┘
$ ligolo-mp » agent list
┌───────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Active agents │
├──────────────┬─────────────────────────────────────────┬───────────────┬────────────────┬─────────────┤
│ ALIAS │ AGENT INTERFACES │ CONNECTED TUN │ ROUTES │ IS LOOPBACK │
├──────────────┼─────────────────────────────────────────┼───────────────┼────────────────┼─────────────┤
│ elated_wiles │ 127.0.0.1/8 │ nervous_cori │ 10.10.10.0/24 │ true │
│ │ ::1/128 │ │ fe80::/64 │ │
│ │ 192.168.2.53/24 │ │ 172.10.10.1/32 │ │
│ │ │ │ 10.11.0.0/16 │ │
└──────────────┴─────────────────────────────────────────┴───────────────┴────────────────┴─────────────┘
$ ligolo-mp » listener list
┌─────────────────────────────────────────────────────────────────────────────────┐
│ Active listeners │
├────────────────────────┬──────────────┬────────────────────┬────────────────────┤
│ ALIAS │ AGENT │ FROM │ TO │
├────────────────────────┼──────────────┼────────────────────┼────────────────────┤
│ dazzling_chandrasekhar │ elated_wiles │ 192.168.2.53:31337 │ 192.168.2.10:31337 │
└────────────────────────┴──────────────┴────────────────────┴────────────────────┘
--obfuscate
. Not sure why you'd need that, since this whole thing is not stealthy at all, but I was borrowing code from Sliver and it was there toocertificate
. You can use it to refresh CA cert, for example.On the agent side, no! Everything can be performed without administrative access.
However, on your the server, you need to be able to create/modify tun interfaces.
Because the agent is running without privileges, it's not possible to forward raw packets. When you perform a NMAP SYN-SCAN, a TCP connect() is performed on the agent.
When using nmap, you should use --unprivileged
or -PE
to avoid false positives.