File uploads are ubiquitous throughout the world wide web, and also happen to be a prime target for attackers. If a hacker can upload a file that is then executed as code, they can achieve malicious access to your server. This type of attack can result in stolen customer information, complete defacement of your site, or even initial access to your enterprise network.
When attacking a file upload feature, we begin by uploading a file and watching how it is handled by the application. Some major questions we try to answer are:
What is returned from the server upon successful upload?
Are other editable fields sent along with the file contents?
What type(s) of files is the server expecting?
Where does the file upload to?
By answering these questions, we can better understand how the application is processing the file, and therefore how we can begin to attack it.
Many applications attempt to verify a file is non-malicious by checking some combination of the following:
- File extension
- Actual file contents
So as attackers, these are our three areas of focus.
We can attack file extension verification by determining if we can upload filetypes besides images (.php, .asp, .jsp).
We should then check:
- .php2 or .pHp
- .png.php or .jpg.asp
- .php%00 (Note that %00 is a null character)
It’s also essential to check if you can upload HTML or JS files.
Since this type of attack is focused on the front-end, many developers will not be as cautious in preventing it, since the impact appears less severe. However, you can launch a sophisticated phishing attack by creating a fake HTML login page on the target domain or use a malicious JS file as a source for Cross-Site Scripting.
In addition to file extension checks, it’s important to determine if the application is verifying the file based upon the specified content-type.
Some common content-types for a file upload feature that allows images are:
- Content-type: image/png
- Content-type: image/jpeg
To attack this, we should change the content-type to:
- Content-type: application/php
- Content-type: text/html
- Content-type: application/zip
Content-types should never be relied on for file verification, since they can easily be spoofed by a user.
Actual File Contents
The last way an application can verify a file is through the actual data being uploaded. This type of validation can be exploited if the application is only checking the first several bytes to determine the type of file.
We can use ‘Magic Bytes’ to trick the application into thinking the file is an image, when instead it is a server-side shell:
- PNG: \x89PNG\r\n\x1a\n\0\0\0\rIHDR\0\0\x03H\0\xs0\x03[
- JPG: \xff\xd8\xff
Placing this data at the top of the file contents can allow you to bypass file verification within a misconfigured application. The rest of the content should simply be whatever PHP/ASP/HTML file you’ve chosen to upload.
Additional Tips & Tricks
Other vulnerabilities that are worth assessing in file upload features:
- Path Traversal by setting filename to ../../../../../tmp/test.jpg
- SQL Injection by setting filename to
XSS by setting filename to <svg onload=alert(document.domain)>
The Bottom Line
File upload features are essential for modern-day applications but they can be complicated to secure. It is important to properly verify files before they’re uploaded, and thoroughly test code before it’s sent into production.