5. Upload Vulnerabilities
Fifth section in the Complete Beginner learning path.
Introduction
Uploading files to a server has become integral to modern interaction with web applications. Social media profile pictures, cloud storage services or even GitHub are examples of web apps that make extensive use of file uploads. When handled badly, file uploads can lead to a wide range of issues from minor problems all the way to Remote Code Execution (RCE). Attacks with unlimited upload access can deface existing content or use servers to host illegal content. This exercise explores:
Overwriting files on a server
Uploading and executing shells on a server
Bypassing Client-Side filtering
Bypassing various kinds of Server-Side filtering
Fooling content type validation checks
Overwriting Existing Files
Files being uploaded to a server should undergo extensive checks to ensure that nothing on the server will be overwritten, common practice is to rename the file with a new random name or with a date and time stamp appended. Alternatively, checks can be made to see if the filename already exists on the server and change it if it does.
File permissions are also relevant here, for example, web pages should not be writeable to the web user, which prevents them from being overwritten. Without these precautions, a site can be left vulnerable to overwriting. In most realistic scenarios, basic permissions on the server prevent this happening.
RCE (Remote Code Execution)
RCE allows the arbitrary execution of code on the web server. Even on low-privilege accounts this can be a serious vulnerability. RCE via upload is typically done by uploading a program written in the same language as the back-end of the website (or at least one the server will understand and execute). Traditionally, this is PHP but more modern technologies take advantage of Python, JavaScript in the form of Node.js or Django. In routed applications (app where routes are defined programmatically rather than mapped to the file-system) this becomes more complicated to achieve.
There are two basic methods to achieve RCE on a web server: web shells and reverse/bind shells. A full reverse shell is the ideal goal, however, a web shell may be an available option. These can be uploaded and accessed through either direct navigation to the upload location or by forcing the web app to run the script.
Filtering
A client-side script (in the context of web apps) means it is running in the users browser rather than on the web server. JavaScript is the most used client-side scripting language, although there are alternatives. A client-side script will run in your web browser, meaning filtering occurs before the file is uploaded. In theory this is good, in practice it is very easy to bypass. Client-side filtering alone is highly insecure and not a good way to verify an uploaded file is not malicious.
A server-side script will run on the server. PHP was the traditionally predominant server side language, many more like Python, Node.js, Ruby on Rails and C# are becoming more widely used. Server-side filtering is much harder to bypass, often a payload will need to be formed which will conform to filters but still allow code execution.
Some different types of filtering are:
Extension Validation: file extensions are used (in theory) to identify the contents of a file. Practically, they are easily changed so they don't mean much. However, Windows still uses them to identify file types, Unix based systems rely on other methods. Filters for extensions either blacklist set extensions or whitelist set extensions.
File Type Filtering: file type filtering is a more intense version of extension validation. There are two types of file type filtering:
MIME (Multi-purpose Internet Mail Extension) validation checks the MIME type of a file, the MIME type is used to identify a file when transferred over HTTP(S) or email. The mime type of a file upload is attacked in the header of a request and looks like "image/jpeg". MIME is easy to bypass as it is based on the extension of a file.
Magic Number validation is an accurate way to determine file type, however, it is still bypassable. The magic number of a file is a string of bytes at the beginning that identifies it, for example, a PNG has the magic number: 89 50 4E 47 0D 0A 1A 0A.
File Length Filtering: file length filters prevent massive files from being uploaded to the file. This won't cause issues uploading shells, however, a filter may be in place if an upload server only expects a very short file name. For example, a web server may expect a max of 2Kb being uploaded and block anything larger.
File Name Filtering: checks that files names or unique or checks if a file already exists. Also, should sanitise file names and remove any "bad characters" which can cause problems, for example, remove null bytes or forward slashes, or control characters like ";".
File Content Filtering: complex filter systems will scan file contents to check it is not spoofing its extension, MIME type or Magic Number.
Bypassing Client-Side Filtering
There are four easy ways to bypass an average client-side filter:
Turn Off JavaScript in Browser : this works if the site does not require JavaScript to function, otherwise, it will completely bypass a client-side filter.
Intercept and Modify Incoming Page : using Burp, the incoming page can be stripped of JavaScript before it can run.
Intercept and Modify the File Upload : intercept the file upload after it is passed and accepted by the filter by changing the MIME type to an accepted one e.g. change image/jpeg to text/x-php and the file extension from .jpg to .php.
Send the File Directly to Upload : tool like curl can be used to pass the data directly to the webpage and bypass the client-side filter. The syntax for this would look like:
Last updated