PermX is an easy-rated machine on Hack The Box, created by mtzsec. The machine begins with discovering a learning management system, identifying its version, and exploiting a CVE to gain the initial foothold. Through initial enumeration, we leveraged password reuse to escalate to a new user and then exploited a Bash script to escalate to root. Let's get right into this.
Enumeration
As always, I fired off an initial Nmap scan against all ports to understand what ports were open. Once the scan was completed, there are only two open: ports 22 and 80.
22 - SSH
I am going to skip enumerating SSH for now. There is not much we can do with it right now without some user credentials or SSH keys.
80 - HTTP
When navigating to http://10.10.11.23 initially, I found that it redirected to http://permx.htb. To access the site via the hostname, I had to add permx.htb to the hosts file.
Once added, the site could be accessed via the hostname after a refresh. After enumerating the webpage, nothing of interest was found. Either the links were not anchored anywhere, or they loaded another basic static HTML page.
As I had an initial apex domain which did not turn up much, I turned to virtual host discovery using ffuf, which revealed a new virtual host called lms. This new host was also added to the hosts file.
Poking Around Chamilo LMS
After adding lms.permx.htb to my hosts file, I accessed it and discovered a Chamilo learning management portal.
Trying basic username and password combinations did not work, and I could not get any SQL injection to work in an attempt to bypass the authentication.
With limited options around the login, I decided to perform directory enumeration using ffuf. Several items were discovered, but a few stood out:
web.config: Initially, this file seemed promising, but it ultimately did not contain anything useful at our current stage in the enumeration phase.
robots.txt: Always worth reviewing, this file revealed a directory that helped us identify the version of Chamilo in use on the application server.
The rest of the items required authentication to access, which is not helpful for us at this point.
I navigated to each of the directories listed in robots.txt and /documentation proved the most useful.
Now we know the version of Chamilo that is running is 1.11 - this is good to know.
Exploiting Chamilo LMS v1.11
The Chamilo LMS version on the host was vulnerable to CVE-2023-4220, a flaw allowing unauthorized file uploads and access at http://lms.permx.htb/main/inc/lib/javascript/bigupload/files/.
I cloned the exploit script from GitHub and copied the pentestmonkey PHP reverse shell to the same directory, renaming it to gray_shell.php. The file was modified to include my Kali IP and listening port.
/usr/share/webshells/php/php-reverse-shell.php
I started a netcat listener on port 9001 and ran the CVE-2023-4220 exploit against http://lms.permx.htb and got the initial foothold on the box.
Using the shell obtained through the exploit script, I began enumerating the box for anything useful. After some time, I discovered a configuration file containing database credentials—always a nice find.
These credentials did work with the local MariaDB database installation running on the box.
I extracted the password hashes for the admin and anon users but could not get these hashes to crack. That is okay as these were not needed to continue with the box. However, it is always a good habit to check things like this if you get the opportunity.
select id,username,password from user;
As I had a working password, I checked for password reuse—and indeed, it was a thing. A user named mtz was on the box, and the database password also worked for this user. Initially, I used su to switch to the mtz user but later leveraged SSH to get a more stable shell.
After switching to the mtz user, I restarted the enumeration phase. Remember, enumeration is a cyclical process that should be repeated after gaining a new user context.
The first step was to check if the mtz user had any sudo privileges, and sure enough, they did. The script /opt/acl.sh could be run with sudo privileges without requiring the user’s password.
Essentially, this script checks that the target specified is located within the mtz home directory and the path does not contain "..", which is an attempt to protect against directory traversal attacks. It also verifies that the target is a file, not a directory. If all these checks pass, the script uses the setfacl command with the positional variables provided during runtime.
Knowing we cannot attempt a directory traversal attack (so we can’t change the permissions on /etc/passwd for example), and we must stay within our home directory, we can instead use a symlink and then use it as the target for the acl.sh script.
I first created a new symlink for /etc/passwd
mtz@permx:~$ ln -s /etc/passwd /home/mtz/passwd
Then I used the acl.sh script with sudo privileges to grant the mtz user full permissions on the new symlink.
sudo /opt/acl.sh mtz rwx /home/mtz/passwd
In a real engagement and to be honest, even in a shared CTF environment, you do not want to go changing passwords for users or changing any of their permissions. Instead, I used a separate account and gave it root privileges. I first created a hash with a known password.
Next, I created a custom entry that would later append to /home/mtz/passwd. This entry would allow me to switch to the gray user using the password I set, granting root privileges. This approach helps preserve the CTF environment for others in the lab.
Below are all the steps for the privilege escalation in one fell swoop including getting a root shell and reading the root flag.
That brings us to the end of this walkthrough. This was a fun box to work though as I try to get back into CTFs and post fresh content to hopefully have the opportunity to share some knowledge and how I work through challenges.