logo

Database

Insecure file upload - Files Limit

Need

Enforce file upload limits and implement proper file management

Context

• Usage of Ruby for developing web applications and scripting

• Usage of Ruby on Rails for building web applications

Description

1. Non compliant code

class UploadsController < ApplicationController
  def create
    params[:files].each do |file|
      UploadedFile.create(file: file)
    end
    redirect_to uploads_path
  end
end

This code represents a file upload feature in a Ruby on Rails application. The `create` action in the `UploadsController` is responsible for handling file uploads. Here's how it works: - It accepts a collection of files as a parameter (`params[:files]`). - For each file in the collection, it creates a new instance of the `UploadedFile` model, storing the file. - After all files have been uploaded, it redirects the user to the uploads page. The vulnerability lies in the fact that there is no limit to the number of files a user can upload. This means that a malicious user could potentially upload a large number of files, filling up the server's storage and potentially causing a Denial of Service (DoS) attack. Additionally, the system does not delete any previously uploaded files when a new one is uploaded. This means that over time, old and potentially unneeded files could accumulate on the server, further exacerbating the potential for storage issues.

2. Steps

• Implement a limit on the number of files that can be uploaded per unit of time.

• Consider implementing a file retention policy to delete old files from the server.

• Validate the uploaded files to ensure they are of the expected file types and do not contain any malicious content.

• Implement proper error handling and user feedback for failed file uploads.

• Consider implementing file size restrictions to prevent excessively large files from being uploaded.

3. Secure code example

class UploadsController < ApplicationController
  MAX_FILES = 10 # Maximum number of files that can be uploaded per unit of time
  MAX_FILE_SIZE = 5.megabytes # Maximum size of each file

  def create
    if params[:files].size > MAX_FILES
      flash[:error] = "You can only upload a maximum of #{MAX_FILES} files at a time."
      return...

The updated code now includes a limit on the number of files that can be uploaded at a time, as well as a maximum file size for each file. The `MAX_FILES` constant is set to 10, meaning that users can only upload up to 10 files at a time. If a user tries to upload more than this, they will be redirected back to the uploads page with an error message. The `MAX_FILE_SIZE` constant is set to 5 megabytes. If a user tries to upload a file that is larger than this, they will be redirected back to the uploads page with an error message. When a file is uploaded, the `create` method is called on the `UploadedFile` model. If there are any errors with this (for example, if the file is of an invalid type), these errors are added to the `flash[:error]` hash and the user is redirected back to the uploads page. If all files are uploaded successfully, a success message is displayed to the user. This code does not yet include a file retention policy to delete old files from the server. This would need to be implemented separately, perhaps as a background job that runs periodically to delete files that are older than a certain age.