File Upload

1. Introduction:

File upload is becoming a more and more essential part of any web application. Imagine an application that is usable and does not have some kind of uploading... you can count them on the fingers of one hand. Every developer should be able to defend against bugs and malicious files in a way to keep the application and the users safe.

In short, following these policies should suffice against any known attacks that could be done through file uploading:

2. Mitigation and defensive techniques:

2.1. Using a Secure Storing System:

The zombie that's not in your house can't hurt you!

Jokes aside, one of the most important approaches to a secure file uploading functionality is ensuring that your web server treats the uploaded files as inert rather than executable objects. In this sense, you may opt for the alternative of storing the uploaded files into a CDN(Content Delivery Network) such as Cloudflare; you have maybe guessed from my zombie quote that by doing this a developer basically unloads the security burden to the third party that they are working with, such that the files are always stored securely in this manner.

Of course, using a CDN may not be your best pick, and thus you may opt for one of the other alternatives, such as cloud-based storage(Amazon S3, Google Storage Bucket, etc), or even dedicated CMS(although this comes with the extra configuration and attention headache).

2.2. Various defensive techniques and alternatives:

You may not opt for CDNs or any of the alternatives listed above. Should that be the case, and you really have to upload files to your "local" disk, here's what you have to do:

  • Renaming the files as you upload them: creating a custom or using a default hashing function for the filenames is a good principle so that it is harder to guess where exactly the files have been saved.

  • Write to disk without executable permissions: this is a necessary step towards securing your uploading process. There are countless scripts or executable files that an attacker may leverage, and thus you simply have to remove this kind of permissions from the files that get uploaded.

import os

file_f = os.open("/path/to/your/file", os.O_WRONLY | os.O_CREAT, 0o600)

with os.fdopen(open(file_f, "wb")) as file_handling:
    file_handling.write(...)
  • Validate the file extensions: ensure that the validation occurs after decoding the file name, and that a proper filter is set in place in order to avoid certain known bypasses, such as the following:

    • Double extensions, e.g. .jpg.php, where it circumvents easily the regex \.jpg.

    • Null bytes, e.g. .php%00.jpg, where .jpg gets truncated and .php becomes the new extension.

    • Generic bad regex that isn't properly tested and reviewed. Refrain from building your own logic unless you have enough knowledge on this topic.

  • File content verification: As a file's content may contain malicious or inappropriate data, a developer can always extra-validate it, based on the expected file type:

3. Takeaways:

While the fundamental aspects of file uploading remain the same, developers have for good reason started looking towards ways of "incorporating" file storage systems, that are easy, secure and overall convenient to use.

Last updated