This is a write-up on the Curling machine access challenge from HTB. For more information on challenges like these, check out my post on penetration testing.  Special thanks to HTB user L4mpje for creating the challenge.

Start Hacking

Start with a simple nmap to discover a website and not much else.   There is a login form, but no common or default passwords will work. Note that one of the posts is signed by someone named Floris.

Look through the page source.  The site is running Joomla, an open-source content management system.  The Joomla administration page can be found in the usual location Down at the bottom of the code, there is a comment about a file called secrets.txt. Browse to and it will reveal the string Q3VybGluZzIwMTgh.

On the admin page, the string doesn't work as a password for username floris or any other common usernames.  We can test to see if the string is base64 encoded text and decode if necessary.  Use the command below on a bash shell with base64 installed, or just run the string through any base64 decoding tool and see if it produces anything meaningful.

    s="Q3VybGluZzIwMTgh" && [[ $s =~ ^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$ ]] && echo $s | base64 -d 

This decodes to Curling2018! which can be used in conjunction with the username floris to log into the admin page.

Getting a Reverse Shell

Joomla is written in PHP, so attempting to launch a PHP-based reverse shell makes sense.  A good one can be found here: Download it to your local computer and extract php-reverse-shell.php. Towards the top of the script, edit $ip so that it matches your own IP address.

To easily upload the file to the server, leverage one of the many available file-uploading Joomla extensions, such as the one found here:  Save the extension, in the form of a zip file, to your local computer.

In order to overcome security checks built into the extension, it is necessary to sightly modify the code.  Unzip the extension and open file ../Helper/EasyFileUploaderHelper.php. Find the function called checkFileSafety and add return true; to the first line of the function. This will circumvent all the safety checks.

Rezip the extension, careful to ensure that the original folder structure remains intact. From the Joomla admin page, navigate to Extensions/Manage and install the extension using the modified zip file. You can now launch the extension and upload the php reverse shell script.  The images directory has writable permissions and once uploaded, it is possible to launch the script by running nc -lnvp 1234 in your local terminal window and browsing to

NOTE: there are easier and quicker ways to launch a reverse shell on this machine.  I had the file uploader available and I thought it might come in handy if I needed to transfer multiple files later on.

Getting a Proper Shell

Running under the context of the webserver doesn't grant access to user.txt in /home/floris, but there is a world-readable backup file called password_backup which appears to be a hexdump.  Download the file to your local computer to analyze it (you can also run cat password_backup and copy/paste the output into a local file).  

It takes a little bit of analysis, but the file turns out to be a text file inside a tar file inside a gzipped bz2 archive inside a bz2 archive that is hexdumped.  To reverse this:

cat password_backup | xxd -r > password_backup.tar.bz2.gz.bz2
bzip2 -d password_backup.tar.bz2.gz.bz2
gunzip password_backup.tar.bz2.gz
bzip2 -d password_backup.tar.bz2
tar -xvpf password_backup.tar
cat password.txt

This should reveal the password for the floris account and you can SSH directly into the machine using those credentials. You now have the flag in user.txt!

Moving on Up

Under /home/floris there is a directory called admin-area with two files inside, input and report. The timestamp on report changes periodically and a quick glance at the file shows that it is just a copy of the website's front page.  There is one line in input which defines a URL of localhost. Based on the name of the challenge it is likely that the the curl command is being used to monitor the status of the website.  If the command is executed as root, it should be possible to modify the url in the input file to gain access to anything the system.

    url = "file:///root/root.txt

Wait for report to refresh and check the contents.  It should contain the flag in root.txt.

Really Owning the Box

Technically the challenge is over, but few real-life hackers would stop there. A few more steps are required to get access to a root shell.

Create a file called /tmp/sudoers with the following contents:

floris ALL=(root) NOPASSWD: /bin/su

Modify the input file so that is reads as follows:

url = "file:///tmp/sudoers" -o /etc/sudoers.d/os
output = "/etc/sudoers.d/os"

This will cause the curl script to copy the contents of /tmp/sudoers into /etc/sudoers.d/os, at which point you should be able to run sudo su as the floris user and obtain a root shell without a password.  

NOTE: figuring this out was a bit of a guess. I knew that url is one of the parameters that gets passed to curl, and I wanted to trick curl into dropping the output where I wanted it.  Without access to the job/script that was executing curl, I didn't know how the input file was being parsed, so I used tried two different methods (one on the same line, one on a separate line).  This worked and I never actually bothered to check which was correct.