Writeup: HackTheBox File Upload – Skills Assessment

As part of my university work, I am working through courses on HackTheBox. This is so I can add these courses and the skill assessments to my portfolio. In this brief writeup I will show how I went about performing the skills assessment for the file upload attack course.

Exploring

We are presented with the following page upon accessing the webpage hosted by the target machine. We can see various categories, all of which do nothing when clicked on. We have a features page, this can also not be accessed. We do, however, have a contact page.

the frontpage of the website is shown, with an image and mostly nonfunctional buttons

When accessing this contact page, we are met with the following screen. We see a form where we can input a name, email and message, as well as upload an image. While the form itself is of interest, we can see that the file upload is what we came here for.

The contact us page is shown, with a name, email and message, as well as screenshot upload box

If we send in a sample .jpg image of a cat, we can see that the request data is the following:

the request and response when uploading a photo is shown for reference of data being sent

A POST request is made where the image is uploaded, while the form data is uploaded separately by a GET request. The uploaded image is also returned as base64 encoded data. This means we cannot see where the image is hosted on the webserver.

Let’s start by fuzzing the data with several PHP file extensions and see if anything gets through. We will swap the data of the image with an XXE exploit and add some magic bytes to the front to have it recognized as an image file. This way, we can try and get access to the upload.php file and see what checks are being performed. This way, we can perfectly bypass the checks.

The exploit is being ran and base64 encrypted data is returned
The payload fuzzing list is shown with various php extensions
The exploit is shown

We can see that the data returned is still encoded as base64. This is not very handy for us, because we cannot use it at this point. Oddly enough, removing the magic bytes actually returns the data of upload.php as base64 encoded data.

The exploit is shown
The output is shown to be the full code of upload.php in base64

If we decrypt this base64 code, we can see the full code of upload.php!

<?php
require_once('./common-functions.php');

// uploaded files directory
$target_dir = "./user_feedback_submissions/";

// rename before storing
$fileName = date('ymd') . '_' . basename($_FILES["uploadFile"]["name"]);
$target_file = $target_dir . $fileName;

// get content headers
$contentType = $_FILES['uploadFile']['type'];
$MIMEtype = mime_content_type($_FILES['uploadFile']['tmp_name']);

// blacklist test
if (preg_match('/.+\.ph(p|ps|tml)/', $fileName)) {
    echo "Extension not allowed";
    die();
}

// whitelist test
if (!preg_match('/^.+\.[a-z]{2,3}g$/', $fileName)) {
    echo "Only images are allowed";
    die();
}

// type test
foreach (array($contentType, $MIMEtype) as $type) {
    if (!preg_match('/image\/[a-z]{2,3}g/', $type)) {
        echo "Only images are allowed";
        die();
    }
}

// size test
if ($_FILES["uploadFile"]["size"] > 500000) {
    echo "File too large";
    die();
}

if (move_uploaded_file($_FILES["uploadFile"]["tmp_name"], $target_file)) {
    displayHTMLImage($target_file);
} else {
    echo "File failed to upload";
}

At this point, we can use this knowledge to perfectly bypass any checks performed on the inputted data. As we can see below, the contents of /etc/passwd are returned in plaintext:

a shellcode is uploaded and the output is shown. The output is the output of /etc/passwd/

Now, if we attempt to enter our shellcode, we can upload it. Since we know where it is being uploaded, we can also access it as we normally would.

a shellcode is uploaded and the output is shown. The output is a base64 decrypted URL

When we access it, we can see that the magic bytes fail to display, but are added to the output. Just the same, our command is also outputted.

a screenshot of an endpoint being accessed to run the ls command

We can see that the flag is in the root directory, too. When we cat the info out of it, we get the flag.

a screenshot of an endpoint being accessed to read the flag

And when we input the flag into HTB as our answer, we can see it is correct and finish the exercise.

The root flag found is verified to be correct

More writeups?

If you enjoyed this writeup or have questions, please leave a comment!

Want to read more (HackTheBox) writeups? Check them right here!

Leave a Reply

Your email address will not be published. Required fields are marked *