FILE UPLOAD ATTACKS

Table of contents:
Absent validation (most basic, without any defense)
Bypassing Client-Side validation
Bypassing Server-Side validation
Preventing File Upload Vulnerability
ABSENT VALIDATION
The most basic type of file upload vulnerability occurs when the web application does not have any form of validation filters on the uploaded files, allowing the upload of any file type by default.
IDENTIFYING WEB FRAMEWORK
A Web Shell provides us with an easy method to interact with the back-end server by accepting shell commands and printing their output back to us within the web browser. A web shell has to be written in the same programming language that runs the web server, as it runs platform-specific functions and commands to execute system commands on the back-end server, making web shells non-cross-platform scripts. So, the first step would be to identify what language runs the web application.
We can do this using a few techniques-
visit the
/index.extpage, where we would swap outextwith various common web extensions, likephp,asp,aspx, among others, to see whether any of them exist.Use extensions like Wappalyzer
VULNERABILITY IDENTIFICATION
When selecting a file, it shows "all files" and does not limit to the type of files we can upload.
doesn't have any client-side protection, i.e let's any type of file be uploaded, and the rejection comes from the server (if it does).
Has only client-side protection, i.e if we bypass client-side protection, the server let's the the file be uploaded without verification
EXPLOITING BASIC FILE UPLOAD VULNERABILITY
If we do come across a file upload vulnerability, to exploit it, we can upload a malicious script in the same language as the web application, like a web shell or a reverse shell script.
WEB SHELLS
We can find many excellent web shells online that provide useful features, like directory traversal or file transfer. One good option for PHP this is phpbash. while using phpbash looks something like this

WRITING CUSTOM WEB SHELL
Using a web shell from an online resource can be very easy and fast, but we should know how we can write a simple or advanced web shell.
with
PHPweb applications, we can use thesystem()A function that executes system commands and prints their output, and passes it to thecmdparameter with$_REQUEST['cmd']
like this
Or we can make a bit advanced web shell with better functionality
REVERSE SHELL
One reliable reverse shell for PHP It is the pentestmonkey PHP reverse shell. As usual, we'll have to start a listener on our machine and visit the file we have uploaded
. We can also generate a custom php reverse shell using msfvenom. Note that this is highly flagged by Defender or any AV.
BYPASSING CLIENT-SIDE VALIDATION
We can know that a web app has client-side validation if it rejects our uploaded file without sending it to the server.
So, what we can do to bypass it is:
Modify the upload request to the back-end server
manipulate the front-end code to disable these type validations.
BACK-END REQUEST MODIFICATION
First, we'll see back-end request modification. So, this is what a normal request looks like after it has passed the client-side validation and is sent to the server.r

So what we're gonna do is once the request has passed the client-side validation (which was the only security in this case), we're gonna intercept it and edit the file type and file content. To make it look like this (i.e., change the PNG image file type and content to a PHP webshell)

DISABLING FRONT-END VALIDATION
Another method to bypass client-side validations is through manipulating the front-end code. These functions are being completely processed within our web browser.
This is what a normal code validating the file type on the client side looks like:

Here we can see that the code below is checking for the file extensions
And even more interesting part is onchange="checkFile(this)", which appears to run a JavaScript code whenever we select a file, which appears to be doing the file type validation. When we go in details we see
The key thing we take from this function is where it checks whether the file extension is an image, and if it is not, it prints the error message we saw earlier (Only images are allowed!) and disables the Upload button. We can add PHP as one of the allowed extensions or modify the function to remove the extension check entirely.
Luckily here removing this entire validation wouldn't break anything so we'll do that, and the resultant client-side code will be this

BYPASSING SERVER-SIDE VALIDATION
BLACKLIST FILTERS
Blacklist filters simply means that the server checks the uploaded file against a set of specific extensions to see if the file's extension has been blacklisted, the code on server-side might look something like this-
The code is taking the file extension ($extension) from the uploaded file name ($fileName) and then comparing it against a list of blacklisted extensions ($blacklist). However, this validation method has a major flaw. Except that it is not comprehensive.
FUZZING EXTENSIONS
To identify which extensions are blacklisted we'll fuzz using either burpsuite or we can create a custom python script
we can set the our target web page in the intruder like this

There are many lists of extensions we can utilize in our fuzzing scan. PayloadsAllTheThings provides lists of extensions for PHP and .NET web applications. We may also use SecLists list of common Web Extensions.
We can filter the extensions which are blacklisted or allowed by the lenghts in the fuzzing result.
WHITELIST FILTERS
A whitelist is generally more secure than a blacklist. The web server would only allow the specified extensions, and the list would not need to be comprehensive in covering uncommon extensions.
the code on the server-side for whitelist validation ight look something like this
We see that the script uses a Regular Expression (regex) to test whether the filename contains any whitelisted image extensions. The issue here lies within the regex, as it only checks whether the file name contains the extension and not if it actually ends with it. Many developers make such mistakes due to a weak understanding of regex patterns.
DOUBLE EXTENSIONS
The code only tests whether the file name contains an image extension; a straightforward method of passing the regex test is through Double Extensions. For example, if the .jpg extension was allowed, we can add it in our uploaded file name and still end our filename with .php (e.g. shell.jpg.php), in which case we should be able to pass the whitelist test, while still uploading a PHP script that can execute PHP code.
We will fuzz the extension similarly but instead of simple extensions we can use Wordlist.
CHARACTER INJECTION
Another method of bypassing a whitelist validation test is through Character Injection. We can inject several characters before or after the final extension to cause the web application to misinterpret the filename and execute the uploaded file as a PHP script.
like:
%20%0a%00%0d0a/.\.…:
For example, (shell.php%00.jpg) works with PHP servers with version 5.X or earlier, as it causes the PHP web server to end the file name after the (%00), and store it as (shell.php), while still passing the whitelist.
TYPE FILTERS
Type filters are used to validate the file content instead of the file name itself.
There are two common methods for validating the file content: Content-Type Header or File Content. Let's see how we can identify each filter and how to bypass both of them.
CONTENT-TYPE
There might be a content-type filter in the server-side like this
The code sets the ($type) variable from the uploaded file's Content-Type header. Our browsers automatically set the Content-Type header when selecting a file through the file selector dialog, usually derived from the file extension. However, since our browsers set this, this operation is a client-side operation, and we can manipulate it to change the perceived file type and potentially bypass the type filter.
We may start by fuzzing the Content-Type header with SecLists' Content-Type Wordlist through Burp Intruder
MIME-TYPE
The second and more common type of file content validation is testing the uploaded file's MIME-Type. Multipurpose Internet Mail Extensions (MIME) is an internet standard that determines the type of a file through its general format and bytes structure.
This is done by inspecting the first few bytes of the file's content, which contain the File Signature or Magic Bytes. For eg- a file starting with GIF87a or GIF89a indicates that the file is a GIF image, even if the file has .txt extension it would still be treated as GIF.
while a file starting with plaintext will be treated as a txt file even if it's extension is .jpg, like below
Web servers can also utilize this standard to determine file types, which is usually more accurate than testing the file extension. Web servers can use code like this to check for MIME type of an uploaded file
so to this we have to first fuzz the file to verify allowed files, then we will put the MIME of that signature file (extension would still be of php), and after the first few bytes we will put in our web shell, like this

PREVENTING FILE UPLOAD VULNERABILITIES
EXTENSION VALIDATION
While whitelisting extensions is always more secure, as we have seen previously, it is recommended to use both by whitelisting the allowed extensions and blacklisting dangerous extensions. This way, the blacklist list will prevent uploading malicious scripts if the whitelist is ever bypassed (e.g. shell.php.jpg).
The following example shows how this can be done with a PHP web application, but the same concept can be applied to other frameworks:
CONTENT VALIDATION
We can use framework like below to validate the file extension through whitelisting, and validate both the File Signature and the HTTP Content-Type header, while ensuring both of them match our expected file type:
UPLOAD DISCLOSURE
Another thing we should avoid doing is disclosing the uploads directory or providing direct access to the uploaded file.
users should not have direct access to the uploads directory. Any direct requests to this directory should return a 403 Forbidden response. Instead, files should be served through the controlled script using security-focused HTTP headers such as:
Content-Disposition: Used to specify how the content should be displayed in the browser. Setting it toattachmentinstructs the browser to download the file rather than render it inline.Content-Type: Specifies the MIME type of the file, ensuring that the browser knows how to handle the file content appropriately.X-Content-Type-Options: nosniff: Prevents the browser from MIME-type sniffing, which helps mitigate security risks by ensuring that the browser adheres strictly to the specifiedContent-Type.
Last updated