Skip to main content

Insecure file upload

Need

Secure file upload and validation process

Context

  • Usage of C# 7.1 for developing applications with advanced language features and improvements
  • Usage of Microsoft.AspNetCore.Mvc for building web applications with ASP.NET Core
  • Usage of Microsoft.AspNetCore.Http for handling HTTP requests and responses in ASP.NET Core applications

Description

Non compliant code

public async Task<IActionResult> UploadFile(IFormFile file)
{
var filePath = Path.GetTempFileName();

using (var stream = System.IO.File.Create(filePath))
{
await file.CopyToAsync(stream);
}

return Ok(new { filePath });
}

The above code is an ASP.NET Core action method that accepts a file from a form submission and saves it to a temporary location on the server. The vulnerability lies in the fact that there are no checks to validate the type or content of the file being uploaded.

This means that a user can upload a file with any extension, including potentially harmful ones like .html, .php or .exe which can contain malicious code. In addition, there are no checks for double extensions, which is a common trick used by attackers to bypass weak extension checks (for example, a file named image.jpg.php).

Furthermore, the system does not validate whether or not the file is free from malicious code. This means that if a user uploads a file containing malicious code, the system will save it and potentially execute it, depending on the server's configuration and the file's extension.

This insecure file upload vulnerability can lead to various attacks such as code execution, system takeover, or data leakage.

Steps

  • Implement file extension validation to only allow specific file types to be uploaded.
  • Use a secure file storage location instead of the temporary file location.
  • Implement file content validation to check for malicious code or executable files.
  • Set appropriate file permissions to restrict access to uploaded files.
  • Implement file size restrictions to prevent large files from being uploaded.
  • Implement secure file naming conventions to prevent directory traversal attacks.
  • Implement logging and monitoring to detect any suspicious file uploads or activities.

Compliant code

public async Task<IActionResult> UploadFile(IFormFile file)
{
// 1. Validate file extension
var allowedExtensions = new[] { ".jpg", ".png", ".gif", ".bmp" }; // Add more safe extensions as needed
var extension = Path.GetExtension(file.FileName).ToLowerInvariant();

if (string.IsNullOrEmpty(extension) || !allowedExtensions.Contains(extension))
{
return BadRequest(new { message = "Invalid file extension" });
}

// 5. Implement file size restrictions
if (file.Length > 2097152) // 2MB
{
return BadRequest(new { message = "File size exceeds limit" });
}

// 6. Secure file naming
var fileName = Guid.NewGuid().ToString() + extension;

// 2. Secure file storage location
var filePath = Path.Combine("SecureFileStorage", fileName);

// 4. Set appropriate file permissions
// This is usually done at the OS level or during deployment, not in the code

using (var stream = System.IO.File.Create(filePath))
{
await file.CopyToAsync(stream);
}

// 3. File content validation
// This is highly dependent on the file type and the kind of threats you expect.
// For example, for images, you might re-encode the image using a trusted library.

// 7. Logging
// Log the file upload event here

return Ok(new { filePath });
}

The updated code includes several security measures to mitigate the risk of insecure file uploads:

  1. File Extension Validation: The code checks the file extension against a list of allowed extensions. This prevents the upload of potentially dangerous file types like .html, .php, or .exe.

  2. Secure File Storage Location: Files are stored in a secure location ("SecureFileStorage") instead of the temporary file location.

  3. File Content Validation: This step is highly dependent on the file type and the kind of threats you expect. For example, for images, you might re-encode the image using a trusted library. This step is not included in the code as it requires a specific implementation based on your needs.

  4. File Permissions: Setting appropriate file permissions is crucial to restrict access to uploaded files. This is usually done at the OS level or during deployment, not in the code.

  5. File Size Restrictions: The code checks the size of the file and rejects the upload if the file size exceeds a certain limit (2MB in this case).

  6. Secure File Naming: The code generates a new, random file name for each uploaded file. This prevents directory traversal attacks that could exploit predictable file names.

  7. Logging: Implementing logging and monitoring can help detect any suspicious file uploads or activities. This step is not included in the code as it requires a specific implementation based on your logging infrastructure.

References