Securing File Uploads
Tags: webdev, security, guide
Published: 2024-06-06 11:06:14

File uploads are a common feature in web and mobile applications, but they can pose significant security risks if not handled properly. To ensure your apps remains secure, it's crucial to implement robust validation and security measures. This guide will help you to effectively secure file uploads, protecting your systems and end users from malicious intent and malware.

File uploads present several security risks that could compromise both your apps and users. The main risks include:

  - **Malicious Files**: Uploaded files can contain viruses, malware, or executable code designed to exploit vulnerabilities.
  
  - **Cross-Site Scripting (XSS)**: Inadequately validated files can contain scripts that execute in the context of the user's browser.
  
  - **Denial-of-Service (DoS) Attacks**: Malicious users upload large files, or numerous smaller files, to exhaust server storage and processing capacities.
  
  - **SQL Injection**: If uploaded file metadata (e.g. filename) are not meticulously sanitised, they can serve as vectors for SQL injection attacks, potentially compromising the database.

Due to the diverse range of risks, relying on a single method is not sufficient - a multi-layered approach is required, combining validation checks, metadata sanitisation, secure configuration and malware scanning.

## Validate the File Extension
File extensions help in identifying the type of file and determining whether it should be accepted. However, just like the `Content-Type` header, file extensions can be manipulated. Despite this, enforcing a whitelist of allowed file extensions can act as a preliminary filter to block obviously dangerous file types. Ensure that only extensions pertinent to your application's needs are accepted.

Checking the file extension is another basic step in securing file uploads. However, like other HTTP headers, file names and extensions can easily be spoofed. Use an allowlist approach, permitting only the specific extensions that your application requires (e.g., `.jpg`, `.png`, `.pdf`). This is a simple validation, and can act as a preliminary filter to block obviously dangerous/incorrect file types.

## Validate the File Size
Limiting the file size is crucial to prevent denial-of-service (DoS) attacks where an attacker attempts to upload extremely large files to exhaust server resources. Set a maximum file size limit according to your application's requirements and enforce this limit server-side to ensure that oversized files are rejected immediately.

## Validate the `Content-Type` Header
Depending on your application's requirements, you will want to accept only particular types of file; for example, for a profile picture you would only want to accept image files.

The `Content-Type` header, sent by the client, indicates the [MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types) of the file being uploaded. While it's useful to validate as a quick and easy check, it should never be fully trusted - malicious users can easily spoof this header. Therefore, treat the `Content-Type` header as just one of several checks.

How to *definitively* determine the file type is covered in the next section.

## Validate the File Type Based on Signature
As neither the file extension or `Content-Type` header can be trusted, the most effective and reliable way to verify a file's content/media type is by checking its file signature, or "magic number". These are unique [sequences of bytes](https://www.garykessler.net/library/file_sigs.html), usually at the beginning of a file, that indicate its true format. Validation can be performed by reading the first few bytes of the file and matching them against known signatures for allowed file types. For example, a PNG file typically starts with `89 50 4E 47`, and a JPEG file starts with `FF D8 FF`.

This method ensures that the file content matches its purported type, providing a robust defence against file type spoofing. Libraries and tools are available in various programming languages to facilitate this check, or alternatively [Verisys Antivirus API](https://www.ionxsolutions.com/products/antivirus-api?utm_source=devto) can identify [50+ different file formats](https://docs.av.ionxsolutions.com/?utm_source=devto#content-type-detection) for you, while also scanning files for malware.

## Scan for Malware
Incorporating malware scanning into your file upload process is a critical step to ensure the security of both your application and your end users. Malware can be hidden in seemingly harmless files, posing significant risks once they are uploaded and processed.

While there are several malware scanning tools available, not all are equally effective. For instance, [ClamAV](https://www.clamav.net) is a popular open-source antivirus engine, but has notable drawbacks such as poor detection rates, high resource usage, and slow scan times. These limitations can compromise your application's performance and security.

Consider using a more robust and efficient solution like [Verisys Antivirus API](https://www.ionxsolutions.com/products/antivirus-api?utm_source=devto). Verisys Antivirus API offers vastly superior detection capabilities, faster scan times, and a ready-to-use [antivirus API](https://www.ionxsolutions.com/products/antivirus-api?utm_source=devto), making it a reliable choice for integrating malware scanning into your applications.

![JSON response from Verisys Antivirus API](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wvsq7e79j04hn1qu046e.png)

> _Boost your app security with [Verisys Antivirus API](https://www.ionxsolutions.com/products/antivirus-api?utm_source=devto): our language-agnostic API seamlessly integrates malware scanning into your mobile apps, web apps, and backend systems._
> 
> _By scanning user-generated content and file uploads, Verisys Antivirus API can stop dangerous malware at the edge, before it reaches your servers, applications - or end users._

## Storing Files
Steps required to secure files at rest will depend on the location of stored files - for example, they could be uploaded to object storage such as S3, or they could be stored on disk.

  - **Sanitise File Names**: file names can contain malicious characters that your application may be unable to process correctly. Always sanitise file names by removing or replacing special characters, spaces, and potentially executable scripts. Consider renaming files upon upload to a standardised naming convention to prevent any harmful effects.

  - **Secure Storage Location**: if storing files on disk (rather than, for example, object storage), uploaded files should be stored in a directory that is not directly accessible via the web. This prevents direct execution or access to the files from a URL.

  - **Set Appropriate Permissions**: ensure that uploaded files have the minimum necessary permissions. For instance, files should not be executable if they don't need to be.

## Closing Thoughts
By combining these strategies, developers can significantly enhance the security of file uploads in their applications. A layered approach, which includes malware scanning, provides comprehensive protection against a variety of attack vectors, ensuring that file uploads remain a safe and useful feature.

For a comprehensive guide on securing file uploads and other web application security best practices, refer to [OWASP](https://owasp.org) (Open Worldwide Application Security Project). OWASP provides a wealth of resources, including the [OWASP Top Ten](https://owasp.org/www-project-top-ten/), which highlights the most critical security risks to web applications. In particular, see [Unrestricted File Upload](https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload).

Learn more about [Verisys Antivirus API](https://www.ionxsolutions.com/products/antivirus-api?utm_source=devto), our language-agnostic API that seamlessly integrates antivirus scanning into your mobile apps, web apps, and backend systems: [https://www.ionxsolutions.com/products/antivirus-api](https://www.ionxsolutions.com/products/antivirus-api?utm_source=devto)