Sitemap
DFIRinthehole

DFIRinthehole

File Uploads Skills Assessment (HTB)

3 min readOct 9, 2026

--

Overview

This assessment is part of the penetration testing path, specifically the file uploads module; it touches on basic exploitation, bypassing various filters, and briefly on how can file uploads be leveraged to exploit XXE and XSS.

Enumeration

Upon viewing the source of “http://ip/contact/” we find an interesting link, which is /contact/upload.php, we can also notice the client side checks implemented:

Press enter or click to view image in full size

Exploitation

We can read /upload.php through and XXE vulnerability by uploading and SVG file with embedded XML (encoded in base64), using burp to bypass client side verifications.

Press enter or click to view image in full size
  • Upon decoding the base64 encode upload.php, the upload directory is revealed “/user_feedback_submissions/” and how the uploaded files are named, i.e.., “date(‘ymd’) . ‘_’ . basename($_FILES[“uploadFile”][“name”]);” and the various server side checks implemented such as blacklisting and whitelisting, checking content type and MIME types.

Get DFIRinthehole’s stories in your inbox

Join Medium for free to get updates from this writer.

<?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";
}
  • We can notice that an extension such as “phar” is not included in the blacklist so let’s try to exploit that using double extensions!!
Extension Verification Bypass
  • So i uploaded an image with an Embedded PHP system webshell as seen below, and it successfully uploaded bypassing all checks, as MIME and content types matches the server side checks.
Embedded PHP System Webshell
  • Now let’s try to execute the webshell using this naming scheme “date(‘ymd’) . ‘_’ . basename($_FILES[“uploadFile”][“name”]);” the below request results in a 404 not found error.
GET /contact/user_feedback_submissions/20261009_shell.phar.jpg?cmd=id
  • So let’s try using the shortened year format and indeed we get a response
GET /contact/user_feedback_submissions/261009_shell.phar.jpg?cmd=cat+/xxxxflag.txt

Thank you!!

--

--