File Upload Vulnerability
Overview
Most major websites offer file upload functionality, allowing users to upload various types of files to the server. These files can range from images in formats like .jpeg
, .png
, and .gif
, to document files such as .pdf
, .doc
, and .xls
. Additionally, there are server-related functionalities where users can upload files with extensions like .php
, .aspx
, or .jsp
. While these functionalities are common, they can pose security issues if the server does not properly validate and restrict file uploads.
If the server fails to implement proper validation, it becomes vulnerable. Attackers can take advantage of this vulnerability by uploading arbitrary and potentially dangerous files instead of the intended images or other allowed file types. In some cases, if the uploaded files contain server-side scripts, the attacker can execute those scripts on the server, resulting in Remote Code Execution and granting the attacker direct control over the server.
By seeing all that let's take a proper definition of file upload vulnerability
File Upload Vulnerability
File upload vulnerabilities refer to security weaknesses in web applications that allow attackers to exploit the file upload functionality. These vulnerabilities arise when the application does not properly validate or restrict the uploaded files, potentially leading to unauthorized access, remote code execution, or other malicious activities.
File Upload Vulnerability occurs in various ways but the following are some common misconfigurations that can lead to file upload vulnerabilities.
Insufficient file type validation: The application may not adequately verify the file type or extension, allowing attackers to upload malicious files with executable code or disguised as benign files.
Lack of file size limitations: Without imposing size restrictions, attackers can upload large files, consuming server resources or causing denial-of-service issues.
Inadequate file sanitization: Insufficient
sanitization
or filtering of user-supplied file names or metadata can enable attackers to manipulate file names or inject malicious content.Failure to enforce secure file storage: If the uploaded files are stored in an insecure location or with weak access controls, attackers may be able to directly access or execute the uploaded files.
Malicious file content: Attackers can exploit vulnerabilities in the file parser or processing logic to execute arbitrary code or perform other malicious actions.
File upload vulnerabilities pose significant threats to applications, although it is becoming increasingly rare to find websites that completely lack any form of file upload restrictions. Developers typically implement certain measures to mitigate these vulnerabilities, such as restricting specific file extensions, imposing size limitations, or sanitizing user-supplied names. The thing is Developers implement what they believe is the best fix and a robust validation for the issue and maybe they are correct however, the effectiveness of these measures depends on the developers' understanding and adherence to best practices and industry standards.
While developers may genuinely believe that their chosen approach provides a robust fix and adequate validation for the issue, there are cases where their implementation may be flawed or easily bypassed. This can occur if the developers overlook certain security standards or fail to account for all potential attack vectors.
Consider a scenario where a developer tries to mitigate file upload vulnerabilities by implementing a blacklist approach. However, they overlook the possibility of parsing discrepancies that can occur when checking the file extension. In the process, they may inadvertently omit certain less common file types that could still pose a threat to the application's security.
In some cases, a website may attempt to determine the file type by checking certain properties or characteristics of the uploaded file. However, these properties can be easily manipulated by an attacker using tools such as Burp Proxy or Repeater. By modifying the file's properties or crafting a malicious file that appears to meet the expected criteria, an attacker can bypass the file type check and upload potentially harmful files to the server.
Ultimately, we see even robust validation measures may be applied inconsistently across the network of hosts and directories that form the website, resulting in discrepancies that can be exploited.
Now that we understand these vulnerabilities exist in the wild, let's explore how to detect and exploit them. By bypassing these flawed defenses, we can successfully upload web shells to the server, enabling us to achieve remote code execution.
Web Server File Handling
Understanding of Web server file handling is essential to fully understanding file upload vulnerabilities so let's first learn about it. In the past, websites primarily comprised static files that were directly served to users upon request. This meant that the path of each request corresponded directly to the structure of directories and files on the server's filesystem. However, with the evolution of websites, they have become more dynamic, and the path of a request no longer necessarily reflects the filesystem structure. Despite this shift, web servers still handle requests for certain static files, such as stylesheets and images. While the relationship between the request path and the filesystem is no longer direct, web servers continue to manage these static file requests.
The handling of static files follows a similar process. When a request for a static file is received, the server examines the file extension by looking at the path of the request. It determines the file's type by comparing the extension to a predefined list of mappings between extensions and MIME types. The subsequent actions taken by the server depend on the file type and the server's configuration.
For dynamic websites, the process is different. The server's response is determined by the backend logic, and the file does not need to be located in the same directory structure as the request. The back-end logic retrieves the file from another location on the network or server and includes it in the user's response.
On the user's side, the following scenarios can occur:
If the file type is non-executable, such as an image or a static HTML page, the server simply sends the file's contents to the client in an HTTP response.
If the file type is executable, like a PHP file, and the server is configured to execute files of this type, it assigns variables based on the headers and parameters in the HTTP request. The script is then run, and the resulting output is sent to the client in an HTTP response.
If the file type is executable, but the server is not configured to execute files of this type, it typically responds with an error. However, in some cases, the contents of the file may still be served to the client as plain text. Such misconfigurations can occasionally be exploited to reveal source code and other sensitive information.
In HTTP headers we see a Content-Type
header that tell our browser what type of file is served and based on that our browser either displayed it or downloads it on the client system. This header gives us clues to what the server thinks about these files and if this header has not been explicitly set by the application code, it typically reflects the result of the file extension and MIME type mapping.
Having gained an understanding of these fundamental concepts, we can now delve into exploring the vulnerabilities associated with them. To enhance our practical comprehension, we will engage in hands-on exercises and lab scenarios, allowing us to apply and reinforce our knowledge of these vulnerabilities in a more concrete and immersive manner.
1. Unrestricted File Upload
Unrestricted File Upload refers to a security vulnerability where an application allows users to upload files without proper validation or restrictions. This means that users can upload any type of file, including potentially malicious files, to the application's server. In terms of security, this is the most concerning situation for a website that lets an attacker upload scripts that can be executed on the server, like PHP, Java, or Python files. This means they can easily create a web shell, giving you control over the server and potentially causing harm.
Web Shell A web shell is a malicious script that enables an attacker to execute arbitrary shell commands on a remote web server simply by sending HTTP requests to that script.
To be able to execute shell commands on the server is the dream of an attacker. This means they can read and write arbitrary files, exfiltrate sensitive data, and even use the server to pivot attacks against both internal infrastructure and other servers outside the network.
The simple PHP web shell looks like this.
Once uploaded, sending a request for this malicious file with the right parameter will execute the shell command on the server and see its output in the response. The example request and response will look like the following.
In the above scenario, the attacker first makes a file on his local system that contains the above web-shell code and saves it with the shell.php
name. After that, they upload the file onto the server using vulnerable upload functionality. When successfully uploaded they send the GET request to that file to execute system commands.
LAB #1: Remote Code Execution via web shell upload
Lab URL: https://portswigger.net/web-security/file-upload/lab-file-upload-remote-code-execution-via-web-shell-upload
Objective Upload the web shell on the server and read the content of /home/carlos/secret
file.
Credentials
Solution
2. Flawed Validation of file uploads
Now that we have practiced the basic file upload vulnerability in the previous lab, it's important to note that real-life scenarios are usually more complex. Unlike the lab, where no validation was enforced to prevent us from uploading a web shell, in reality, we encounter additional defenses. Web Application Firewalls (WAFs) play a significant role by inspecting input and uploaded files for malicious content, and blocking requests that violate the rules. Furthermore, applications often implement their own validations to protect servers from these vulnerabilities.
In this section, we will explore common validation techniques implemented by websites. We will also examine flawed validations that can be completely bypassed, allowing the upload of malicious files onto the server.
Flawed file type validation
We commonly upload various types of files to servers, including images, documents, text files, and zip files. These are typical file types that are frequently uploaded. However, there are also other types of files that we upload for specific purposes. For example, code files, configuration files, and database files are often uploaded to servers, but they are typically associated with Git repositories or Software as a Service (SaaS) platforms.
These files are uploaded using HTTP Post
method, the HTML forms send the request in the background with a specific Content-Type Header. The Content-Type header informs the server about the type of data being sent, and the server processes it accordingly. There are two commonly used Content-Type headers for uploading files:
The Content-Type header application/x-www-form-urlencoded
is suitable for sending simple text data, like names and addresses, as it encodes the data in a key-value format. However, it is not suitable for sending large binary data such as images or PDF documents. For such cases, the preferred approach is to use the multipart/form-data
content type header.
It's worth mentioning that there are other content type headers available as well, such as application/json
and text/xml
, which are used for sending data in JSON
or XML
format, respectively. However, the multipart/form-data
header is more commonly seen when it comes to binary file uploads.
Using the appropriate content type header ensures that the server correctly interprets the data being sent and processes it accordingly.
Imagine a form where you can upload an image, add a description, and enter your username. When you submit this form, it generates a request that consists of multiple parts. Here's an example of how the request might look:
In this example, the request body is divided into separate parts, each representing a specific input field from the form. Each part has a Content-Disposition
header that provides basic information about the corresponding input field. Additionally, some parts may have their own Content-Type
header, which indicates the MIME type of the data submitted through that input field.
Server configurations often include validation of file types by examining the Content-Type
header and comparing its MIME type to the expected MIME type. For instance, if the server is expect image files, it might only permit types such as image/jpeg
and image/png
. However, issues can arise when the server blindly trusts the value of this header without conducting additional validation to ensure that the file's contents genuinely match the indicated MIME type. This defense mechanism can be easily bypassed using tools like Burp Repeater.
Attackers can exploit vulnerabilities by manipulating the Content-Type
header and uploading malicious code onto the server. If the server solely relies on the provided header value without further verification, it may accept the uploaded content as legitimate. This can enable attackers to execute arbitrary code on the server and potentially gain unauthorized access or control.
LAB #2: Web Shell Upload via Content-Type restriction bypass
Lab URL: https://portswigger.net/web-security/file-upload/lab-file-upload-web-shell-upload-via-content-type-restriction-bypass
Objective
Upload a basic PHP web shell and use it to exfiltrate the content of the file /home/carlos/secret
.
Credentials
Solution
Restrict File Execution
To enhance security, it is crucial to prevent the upload of harmful file types. However, as an additional measure, it is essential to block the execution of any scripts that manage to bypass the initial security measures.
As a safeguard, servers typically execute scripts only if their MIME type has been explicitly configured for execution. Otherwise, the server may respond with an error message or, in certain situations, serve the file's contents as plain text.
This behavior can be intriguing since it could allow for source code leakage, but it effectively prevents the creation of a web shell.
Such configurations often vary between directories. The directory where user-uploaded files are stored is likely to have stricter controls compared to other areas of the file system that are assumed to be inaccessible to end users. However, if you manage to upload a script to a different directory that is not intended for user-supplied files, the server might still execute your script.
In the multipart/form-data
content type of HTTP, there is a parameter called filename
that not only provides the application with the file name but also specifies the location where it should be saved. By adding a directory traversal sequence i.e. ../
to the filename, we can upload the file to a different location where it can be executed.
The thing that should be noted and may create some problems is that when we send requests to a domain name, it typically refers to a reverse proxy server or a load balancer. These servers act as intermediaries and our requests are further processed by additional servers in the background. These backend servers may have different configurations and settings compared to the front-facing servers.
LAB #3: Web Shell Upload via Path Traversal
Lab URL: https://portswigger.net/web-security/file-upload/lab-file-upload-web-shell-upload-via-path-traversal
Objective
Upload a PHP web shell and use it to exfiltrate the contents of the /home/carlos/secret
file.
Credentials
3. Insufficient blacklisting
A common approach to prevent the upload of malicious scripts is to create a blacklist of file extensions, such as .php
, that are considered dangerous. However, this method has limitations because it is impractical to block every potential file extension that can execute code. Attackers can easily bypass these blacklists by using lesser-known file extensions like .php5
or .shtml
, which can still be executable.
Overriding the server configuration
As mentioned earlier, servers usually require specific configurations to execute files. For instance, to enable the execution of PHP files on an Apache server, developers need to include certain directives in their /etc/apache2/apache2.conf
file:
In addition, developers can create specific configuration files within directories to modify or supplement global settings on many servers. For instance, Apache servers can load a directory-specific configuration from a file named .htaccess
if it exists.
Similarly, IIS servers support directory-specific configuration through a web.config
file. This allows developers to include directives like the following, which permits serving JSON
files to users:
Web servers utilize these types of configuration files internally, and they are not typically accessible via regular HTTP requests. However, there are instances where servers fail to prevent the upload of malicious configuration files. In such cases, even if the desired file extension is blacklisted, it may be possible to deceive the server into associating a custom file extension with an executable MIME type. This can open up opportunities to execute arbitrary code on the server, bypassing the restrictions imposed by the blacklist.
LAB #4: Web shell upload via extension blacklist bypass
Lab URL: https://portswigger.net/web-security/file-upload/lab-file-upload-web-shell-upload-via-extension-blacklist-bypass
Objective
Bypass the file extension restriction to upload a PHP web shell, and use it to exfiltrate the content of the /home/carlos/secret
file.
Credentials
Obfuscating file extension
Even the most comprehensive blacklists can be circumvented using common obfuscation techniques. Let's consider a scenario where the validation code is case-sensitive and fails to recognize that exploit.pHp
is actually a .php
file. If the code responsible for mapping file extensions to MIME types is not case-sensitive, this inconsistency allows malicious PHP files to pass validation and potentially be executed by the server.
Similar results can be achieved through the following methods:
Providing multiple extensions: By using a filename like
exploit.php.jpg
, the file may be interpreted as both a PHP file and aJPG
image, depending on the filename parsing algorithm.Adding trailing characters: Certain components may ignore or strip trailing
whitespaces
or dots, allowing filenames likeexploit.php.
to bypass validation.Using URL encoding: Dots, forward slashes, and backward slashes can be URL-encoded (or double URL-encoded) to deceive validation mechanisms that don't decode the value. For example,
exploit%2Ephp
may pass as a valid filename but represent a malicious file.Adding semicolons or URL-encoded null byte characters: Appending semicolons or URL-encoded null byte characters before the file extension, such as
exploit.asp;.jpg
orexploit.asp%00.jpg
, can exploit discrepancies between high-level language validation and lower-level file processing.Employing multibyte Unicode characters: Certain
Unicode
sequences may be converted to null bytes or dots after conversion or normalization, such asxC0
x2E
orxC4
xAE
, potentially bypassing filename validation.
Additional defenses involve stripping or replacing dangerous extensions to prevent file execution. However, if this transformation is not applied recursively, it is possible to position the prohibited string in a way that removing it still leaves a valid file extension. For example, consider the filename exploit.p.phphp
, where stripping .php
results in a valid file extension.
These are just a few examples of the various methods for obfuscating file extensions.
LAB #5: Web Shell upload via obfuscated file extension
Lab URL: https://portswigger.net/web-security/file-upload/lab-file-upload-web-shell-upload-via-obfuscated-file-extension
Objective
Bypass the file extension blacklist to upload a PHP webshell, and use the to exfiltrate the content of the /home/carlos/secret
file.
Credentials
4. File Content Validation
Instead of blindly trusting the Content-Type
header provided in a request, secure servers employ a cautious approach by verifying the actual content of uploaded files to ensure they match the expected file type.
When dealing with image uploads, servers can perform additional checks on intrinsic file properties, such as its dimensions. By examining these properties, the server can detect inconsistencies. For example, if a file claimed to be an image lacks any dimensions, it is clear that it cannot be a valid image, leading to the rejection of the upload.
Moreover, certain file types have distinct patterns in their header or footer, which serve as unique fingerprints or signatures. These specific byte sequences, often referred to as Magic Bytes or signature characters, allow servers to determine if the file content corresponds to the expected file type. For instance, JPEG files always start with the bytes FF D8 FF
. Each file type has its own set of magic bytes, and you can learn more about them in the Wikipedia Magic Bytes reference.
While this approach greatly improves file type validation, it is not completely immune to exploitation. Advanced tools like ExifTool
can be used to create polyglot (a type of file that is valid and interpretable by multiple file formats or programming languages) JPEG files that contain malicious code within their metadata, evading detection by leveraging the intricacies of file format specifications.
Attackers employ these techniques to bypass security measures and execute PHP web shell code. One approach involves adding image magic bytes at the beginning of a PHP web shell file, disguising it as an image file. Another method involves utilizing tools like ExifTool
to embed PHP web shell code within the metadata of an image file. This allows the attacker to upload the file with a PHP file extension while still executing the malicious code. These tactics enable attackers to evade detection and exploit vulnerabilities in web applications.
LAB #6: Remote Code Execution via polyglot web shell upload
Lab URL: https://portswigger.net/web-security/file-upload/lab-file-upload-remote-code-execution-via-polyglot-web-shell-upload
Objective
Upload a polyglot image file that contains the PHP web shell to get RCE, and use that to exfiltrate the content of the /home/carlos/secret
file.
Credentials
File Upload with Race Conditions
Modern frameworks have implemented strong measures to prevent such attacks. Instead of directly uploading files to their final destination on the filesystem, they take precautions. They upload the files to a temporary and isolated directory with a randomized name to avoid overwriting existing files. In this temporary location, the uploaded files undergo rigorous validation. Only when they are considered safe, and are transferred to their intended destination.
However, there are cases where developers opt to handle file uploads on their own, disregarding the framework's provided mechanisms. This approach is not only challenging to implement correctly but also introduces the possibility of race conditions that can compromise the effectiveness of validation measures, even those that are considered robust.
What is a Race Condition? A race condition happens when multiple processes or threads access shared resources at the same time, resulting in unpredictable outcomes due to timing differences. This can lead to bugs, security vulnerabilities, and data inconsistencies.
Certain websites implement a practice where files are uploaded directly to the primary filesystem and subsequently deleted if they do not pass validation. This behavior is commonly observed in websites that employ anti-virus software as a means to detect and mitigate malware. Despite the efforts of attackers to obfuscate the malicious content and evade signature-based detection, it is assumed that the anti-virus software accurately identifies and removes the compromised files. However, even in this scenario, a fleeting time window of mere milliseconds emerges during which the file remains on the server, exposing the possibility of its execution.
These vulnerabilities are typically subtle, making them challenging to identify through black box
testing unless the relevant source code can be exposed.
Race conditions can also arise in functions that involve file uploading via a URL. In this scenario, the server needs to fetch the file from the internet and create a local copy before performing any validation.
Since the file is loaded using HTTP, developers cannot rely on the built-in security mechanisms of their framework for file validation. Instead, they may resort to manually creating their own processes to temporarily store and validate the file, which may not be as secure as we discussed above.
For example, developers may use a temporary directory with a randomized name to load the file, assuming that it prevents attackers from exploiting race conditions. By not knowing the directory name, attackers would be unable to request the file and trigger its execution. However, if the randomized directory name is generated using pseudo-random functions like PHP's uniqid()
, it could potentially be guessed through brute force.
To facilitate such attacks, one can attempt to prolong the processing time of the file, thereby increasing the window for brute-forcing the directory name. One approach is to upload a larger file. If the file is processed in chunks, it may be possible to create a malicious file that begins with the payload and is followed by a substantial amount of arbitrary padding bytes.
These attackers exist in the real world and they are indeed very hard to find and exploit but if they were found and exploited there severity is critical.
LAB #7: Web Shell Upload via Race Condition
Lab URL: https://portswigger.net/web-security/file-upload/lab-file-upload-web-shell-upload-via-race-condition
Objective
Upload the PHP web shell and execute it using the race condition to exfiltrate the content of the /home/carlos/secret
file.
Source Code
Credentials
5. File Uploads without RCE
We talk about scenarios in which we bypass different defensive mechanisms to upload server-side scripts to get remote code execution. Other than this these vulnerabilities also be exploited in other ways.
Uploading Malicious client-side scripts
While you may not have the ability to execute server-side scripts, there is still a possibility of uploading scripts for client-side attacks. For instance, if you can upload HTML files or SVG
images, you can leverage <script>
tags to craft stored XSS payloads.
When the uploaded file is displayed on a page visited by other users, their web browsers will execute the embedded script during the rendering process. It's important to note that such attacks will only be successful if the uploaded file is served from the same origin to which it was uploaded, as it is governed by the same-origin policy restrictions.
Vulnerabilities in Parsing Process
If the uploaded file appears to be securely stored and served, and all other options have been exhausted, a final approach is to explore vulnerabilities specific to the parsing or processing of various file formats. For instance, if you are aware that the server parses XML-based files like Microsoft Office .doc
or .xls
files, there might be an opportunity to launch XXE
injection attacks through this vector.
Uploading files using the PUT method
The PUT method is an HTTP request method that is used to upload or replace a resource on a server. It allows clients to send data to the server to update or create a resource at a specific URL.
It is important to mention that certain web servers can be configured to allow PUT requests. In the absence of proper defenses, this can serve as an alternative method for uploading malicious files, even when a specific upload function is not available through the web interface.
We can try sending OPTIONS
requests to different endpoints to test for any that advertise support for the PUT
method.
6. Prevention
Allowing users to upload files is commonplace and doesn't have to be dangerous as long as you take the right precautions. In general, the most effective way to protect your own websites from these vulnerabilities is to implement all of the following practices:
Validate file metadata: Verify the file type, size, and other metadata provided by the user. Use server-side validation to ensure that only allowed file types are accepted.
Restrict file uploads: Implement restrictions on the maximum file size and limit the allowed file extensions. Consider using a whitelist approach instead of blacklisting specific extensions.
Use secure file storage: Store uploaded files outside the web root directory to prevent direct access and execution. Maintain strict file permissions to limit unauthorized access.
Perform server-side validation: Validate the contents and structure of uploaded files on the server. Use file parsing libraries or built-in functions to check for anomalies or malicious code.
Scan for malware: Employ anti-malware tools or virus scanners to scan uploaded files for potential threats. This helps detect and prevent the upload of malicious files.
Use secure coding practices: Follow secure coding guidelines and best practices to ensure robust input validation and prevent common vulnerabilities like path traversal or remote code execution.
Implement secure file naming: Generate unique and unpredictable filenames for uploaded files to prevent overwriting or direct access to sensitive files.
Implement rate limiting and session management: Enforce rate limits on file uploads to prevent abuse and protect against denial-of-service attacks. Manage user sessions and implement proper authentication and authorization controls.
Educate users: Provide guidance and educate users about safe file upload practices. Encourage them to avoid uploading files of unknown or suspicious origin.
Keep software up to date: Regularly update web server software, frameworks, and libraries to leverage security patches and bug fixes.
By implementing these preventive measures, you can significantly reduce the risk of file upload vulnerabilities and enhance the security of your application.
Last updated