File Upload Checks
In the previous example of File Includes we saw how a user could upload an malicious file, and then use it to get code execution on the host.
This can occur, As the user has control over the file that is uploaded, and the developer has not implemented strong file type checking on the server.
In this article we are going to look at common methods for protecting file uploads, and ways that hackers can use to circumvent them.
Approaches for checking file type
So lets take a look at some common methods for checking that the file being uploaded is of the type we expect.
Checking the Extension
For simplest way to check the file type is to check the extension.
For example if we are expecting image files, we could reasonably expect the
uploads to have file extensions like .jpg .png .gif
etc.
However, this trivial type of error checking is not really reliable. Its easy to change the extension of a file (as we did in the RFI example previously)
Warning
An attacker can bypass this check easily. We can simply change the extension of our file, and
Another interesting variation on this issue can happen with some types of file
upload. (For example Apache server may have this as an issue).
If we create a doubled up file name for example evil.php.jpg
the server
may only check the final part of the file (the allowed .jpg
part of the
extension)
However, the save function will only count the first extension (the .php) part. Allowing us to save files in an executable format. This can make our lives much easier when trying to trigger an exploit as we can just navigate to the saved location rather than having to use an includes style vulnerblity to load the page.
Checking the Mime Type
Another common approach used to help filter out unwanted file types. Upon file upload the browser attempts to calculate the MIME-TYPE of the file. This is then passed across in the header to help the server deal with the upload.
For example, the browser may identify a file as text/javascript or image/jpeg and forwarded this information to the server.
Mime type filtering is commonly used in two ways.
-
On the Client (via JavaScript)
Here we block the upload functionality of the form using JS, depnding on the mime type that is detected. As with ANY client based filtering the user is in full controll of the browser, so this should not be relied on
-
On the Server
The server makes use of the reported mime type to filter input. Again, as the mime-type is generated on the client and forwarded. This should not be relied on for filtering.
Checking the file headers.
As well as extensions and mime types. Most types of file can be identified by the header. Each file will have a sequence of "Magic Bytes"1, that signify the file type.
For example:
- .bmp Images
0x42 0x4D
- .zip files
0x50 0x4B 0x03 0x04
We can then attempt to filter our uploads by checking the start of the file for this byte sequence, and filtering ones that don't match.
A common way to do this in PHP is to use the get_imagesize() function that will check the header and fail if the file type is not a recognised image.
Languages such as Node.js have their own implementations such as the file-type library.
While checking the file header is a reasonably secure way to prevent unwanted files being uploaded. Depending on the code that checks the magic bytes, it is still possible to circumvent. For example, we could prefix our file with the correct headers, then add the malicious code afterwards. This does however mean that the file will usually be processed by the web server as an Image (or whatever type of file we uploaded). And means we need to find some other way, usually a file includes style vulnerability, to execute it.
The Gif Trick:
Personally, I find this the easiest way. We could use Jpg but its more complex to modify the headers here.
The Signature for a .gif file is 0x47 0x49 0x46 0x38 0x39 0x61 (GIF89a)
If we create our malicious script to look something like this
```php
GIF89a
<?php
//Do Evil Stuff
?>
```
We can usually bypass filters.
Summary
Here we have looked at some of the common methods of bypassing file upload restrictions.
By allowing users to upload files, we provide an opening for malicious materials code to be placed on the servers we control. While we can put some filtering in place, a determined attacker may find ways to work around the checks.
Malicious file uploads can be especially dangerous when the attacker is then able to access the files later, for example through an Includes style vulnerblitliy.
!!! question "Polygot files polygot
Take a look at the following article on [Polygot Files](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)
What are your views on, these. What extra checks can we put in place to block them?
Further Reading
The approaches we can use to bypass upload restrictions depend heavily on the environment. Some useful guides on how attackers may bypass restrictions (and therefore strategies we need to implement to protect against them)