mezcal

###By b13ss3d###

There's also a video version, if you want to check it out: mezcal

Port Scanning

To start our exploration, we performed a port scan using Nmap. We used Nmap with the options -n, -Pn, and triple -v to not wait for DNS resolution, prevent host discovery checks (though irrelevant if we know it's up), and increase verbosity.

The scan revealed that ports 22 (SSH) and 80 (HTTP) are open. When port 80 is open, it's very likely that there is a web page on the machine, as this port is assigned by default to the HTTP protocol.

Gaining Initial Access

Upon accessing the web server on port 80, we found that it was running Cacti, specifically version 1.3.0. When identifying the version of software in a CTF, the first thing to do is search for exploits for that specific version. We searched for "Cacty 1.3.0 exploit" and found results, including some on GitHub which often contain Proof of Concepts (PoC). PoCs are code created by others to exploit vulnerabilities.

We downloaded an exploit from GitHub using wget.

$ wget https://raw.githubusercontent.com/Rubioo02/CVE-2024-29895/refs/heads/main/poc.py

Before using it, it is highly recommended to review the code, at least superficially, to ensure it is not malicious. It's also important to understand why it works or doesn't work.

Upon executing the script for the first time, testing with a command like whoami, we received an error stating "not cacti instance found".

Reviewing the exploit's source code, we found that the checkurl function made a GET request to a URL that concatenated a specific endpoint (/cacti/cmd_realtime.php).

But this resulted in a 404 error on the target server. By modifying the path to the correct one (/cmd_realtime.php), we received a different response, indicating that the correct path for exploitation did not include the /cacti/ directory.

Although we modified the URL, when sending commands like whoami, the server didn't respond with anything visible, not even in the source code. This doesn't mean the command isn't executing, just that we don't see the output. To verify execution, we set up a basic HTTP server on our machine using Python (python3 -m http.server 80) and then tried to make a curl request from the target machine to our IP. Initially, the command curl <our_ip> did not work due to the use of spaces. The solution was to replace the spaces with the International Field Separator (${IFS}). By sending the request curl${IFS}<our_ip> using the International Field Separator, we received the request on our HTTP server!. This confirmed that we could execute commands on the target machine.

The next step was to obtain a reverse shell to execute commands more comfortably. We configured a netcat listener on our machine on port 443 (nc -nlvp 443). Then, we sent a reverse shell payload using the command injection previously discovered and maintaining the use of ${IFS} instead of spaces. We received the connection. We verified with the id command and confirmed that we were the www-data user.

To improve terminal convenience, which initially was not fully interactive (e.g., CTRL+C terminated the connection), we converted it to an interactive terminal. This was achieved by following a series of steps: execute script /dev/null -qc bash, press CTRL+Z, execute stty raw -echo;fg, execute reset xterm (and press Enter even if you don't see what you're typing), and finally execute export TERM=xterm.

Privilege Escalation

Once inside as www-data, we listed the processes that were running. We noticed that some commands were being executed periodically by the root user. This suggested the existence of a scheduled task or cron job.

We looked in the cron jobs directory (/etc/cron.d/) and found a file named cacti. Upon reading this file, we saw a syntax that indicated the root user executed a specific command every minute. We could use crontab.guru to understand the cron job syntax.

We checked the permissions of the /etc/cron.d/cacti file and discovered that it was writable by our user (www-data). This allowed us to modify its content to execute our own code as root.

We used vi to edit the file. To facilitate editing, we adjusted the terminal size using stty size to get dimensions and then stty rows and stty cols to apply them. Inside the cacti file, we added a line of PHP code (system("chmod +s /bin/bash");) within the appropriate tags to assign the SUID permission (+s) to the /bin/bash binary. This, when executed by root every minute, would make bash executable with root privileges.

We saved the changes in vim (using escape, :x or :wq). To verify that the SUID permission was applied, we used watch -n10 ls -l /bin/bash. We waited until the 'x' in the owner permissions of bash changed to an 's', which confirmed that the SUID permission had been set correctly.

Finally, to obtain the root shell, we simply executed the bash binary with the -p flag (bash -p), which activates privileged mode. We were root!.

Flag Locations

The flags for this machine are located in the following places:

  • The root flag is in the /root directory.

  • The environment flag is in /proc/1/environ.

  • The two system flags are in /etc/passwd and /etc/shadow.

Last updated