Voyage
Chain multiple vulnerabilities to gain control of a system. - by 1337rce
The following post by 0xb0b is licensed under CC BY 4.0
Recon
We start with a rustscan and continue with an nmap default script and service scan, finding three open ports. Ports 22 and 2222, both running SSH.

On port 80, we have a web server running the Joomla CMS.

We can't find anything manually or using directory scan. So we'll continue by taking a closer look at Joomla.

We use Joomscan for this purpose. Joomscan is an open source vulnerability scanner:
We run joomscan but do not find any vulnerabilities. But the version running: Joomla 4.2.7

After some research, we also found a vulnerability related to this: CVE-2023-23752
CVE-2023-23752
This allowed an improper access check which allows an unauthorized access to webservice endpoints exposing sensitive information:
An issue was discovered in Joomla! 4.0.0 through 4.2.7. An improper access check allows unauthorized access to webservice endpoints.
PoCs are also available for this purpose, which access the following endpoints. We could also try it manually.
We run the PoC...

... and are able to retrieve some credentials.

Shell as root on f5eb774507f2
They are not valid for the login on the web page.

Next, we try those on port 22 and 2222 and are successful on 2222. We are able to log in as root. We seem to be in a docker container. No flags yet, and a docker escape seems not to be applicable.

Shell as root on d221f7bc7bf8
Since we are inside a container, it’s reasonable to assume that other containers or internal services may be accessible. By checking the /etc/hosts file, we identify the container’s internal IP address. From this, we can derive the subnet 192.186.100.0/24 and proceed to scan the internal network.

Internal Service Enumeration
Fortunately, Nmap is available on the machine, which is not usually the case. If nmap were not available, we could try put statically compiled version on the machine or use ligolo-ng. A setup for ligolo-ng is described as a bonus below, but it is not mandatory.
We scan the network 192.168.100.0/24 and find the host 192.168.100.12

Unfortunatly, the service and script scan seems to fail on the victim machine.
We create an SSH tunnel with port forwarding using, which maps the remote service on 192.168.100.12:5000 to our local port 5000.

We redo the the service and script scan and see a python webserver running on port 5000.

The index page reveals a login page.

Bonus Ligolo-ng Setup
For the subsequent phases, we can use ligolo to relay traffic between the docker container and our attacker machine to make the internal and external services of the docker container accessible from the container to our attacker machine.
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).
First, we set up a TUN (network tunnel) interface called ligolo on our attacker machine and configuring routes to forward traffic for specific IP ranges (240.0.0.1, 192.168.100/24) through the tunnel.

On our attack machine, we start the proxy server.
Next, we get the agent on the docker container and connect to our proxy.
We get a message on our ligolo-ng proxy that an agent has joined. We use session to select the session and then start it.
We are now able to reach the machines on networks 192.168.100.0/24 and the machines services itself.
Access to Finance Panel
We reuse the credentials found through CVE-2023-23752, and are able to login.

There we see just an table of investments.

RCE via Insecure Deserialization
We inspect the cookies and find the session_data cookie which looks like serialized data.

Since it is a python web server - recalling the results from our Nmap scan on 127.0.0.1:5000, it could be serialized pickle data. To confirm we write a small script to deserialize the data.
We run the script and provide the cookie data and see it gets properly deserialized.

Since we know, the data is serialized by pickle we can try to craft a malicious payload, that eventually gets deserizalized and exectued by the app.
Next, we creat a malicious Python pickle payload that, when deserialized, spawns a reverse shell to our IP 10.14.90.235 on port 4445. The __reduce__ method in our Exploit class ensures that unpickling executes subprocess.Popen with the reverse shell command.
We run the script and receive the serialized data for the reverse shell. Next, we set up a listener on our desired port 4445. Then we request the page using cURL providing the malicious session_data.

The data gets deserialized and evaluated. We receive a connection back to our listener and are root on d221f7bc7bf8.

Next, we upgrade our shell.

At /root/user.txt we find the first flag

Shell as root on tryhackme-2404
On d221f7bcf7bf8 we are still in a docker container, our voyage continues. Linpeas does only spot that /proc is mounted for a possible container escape.

We continue with deepce, a slightly older script. But still reliable. This reveals the set capabilities.

One of these is cap_sys_module. If this is set, it allows a docker escape as described several times in the following sources.

In short: Because the CAP_SYS_MODULE Linux capability allows a process (even inside a Docker container) to load or unload kernel modules, an attacker with container-level execution can insert a malicious module that executes code or launches a reverse shell on the host, effectively breaking out of the container’s isolation.
We adapt the script with our IP and port for a reverse shell and provide the script and Makefile from the sources using a Python web server and transfer them to the machine.
We adjust the Makefile because our test always used the incorrect version 6.8.0-1031-aws, which was not installed. We simply hardcode this.
We transfer the files.
Then we compile the exploit.
Next, we trigger the exploit with the following:

We receive a connection back and are root on d221f7bcf7bf8 and find the final flag at /root/root.txt.

Last updated
Was this helpful?