Inadequate file size control - Ruby

Inadequate file size control - Ruby

Need

Implementation of file size restrictions and validation

Context

  • Usage of Ruby 2.0+ for developing Ruby applications
  • Usage of Rails framework for building web applications

Description

Non compliant code

        class UploadController < ApplicationController
  def upload
    uploaded_io = params[:file]
    File.open(Rails.root.join('public', 'uploads', uploaded_io.original_filename), 'wb') do |file|
      file.write(uploaded_io.read)
    end
    redirect_to root_url
  end
end
        
        

The above code is a simple implementation of a file upload feature in a Ruby on Rails application. The upload method in the UploadController handles the file upload process.

When a file is uploaded through a form on a webpage, the file data is included in the params hash with the key :file. This file data is then written to a new file in the 'public/uploads' directory. The name of the new file is the same as the original name of the uploaded file.

The vulnerability lies in the fact that there is no control over the size of the file being uploaded. This means a user could potentially upload a very large file, which could lead to several issues such as filling up the server's storage, slowing down the server, or even crashing it.

The uploaded_io.read line is where the entire file is read into memory before being written to the new file. If the uploaded file is very large, this could potentially use up a lot of memory and slow down or even crash the server.

Furthermore, there is no error handling in the code. If something goes wrong during the file upload process, such as the server running out of storage space, the application could crash.

Steps

  • Implement server-side file size validation before saving the uploaded file.
  • Retrieve the file size from the uploaded_io object.
  • Compare the file size with a predefined maximum file size limit.
  • If the file size exceeds the limit, reject the upload and return an appropriate error message.
  • Ensure that the maximum file size limit is configurable and can be easily adjusted if needed.
  • Consider using a gem or library that provides file size validation functionality.
  • Handle any potential exceptions or errors that may occur during the file size validation process.

Compliant code

        class UploadController < ApplicationController
  MAX_FILE_SIZE = 10.megabytes # Set your maximum file size limit here

  def upload
    uploaded_io = params[:file]

    if uploaded_io.size > MAX_FILE_SIZE
      flash[:error] = "File size exceeds the maximum limit of #{MAX_FILE_SIZE / 1.megabyte} MB."
      redirect_to root_url
      return
    end

    begin
      File.open(Rails.root.join('public', 'uploads', uploaded_io.original_filename), 'wb') do |file|
        file.write(uploaded_io.read)
      end
    rescue => e
      flash[:error] = "An error occurred while uploading the file: #{e.message}"
      redirect_to root_url
      return
    end

    redirect_to root_url
  end
end
        
        

The updated code now includes a server-side file size validation before saving the uploaded file.

The MAX_FILE_SIZE constant is defined at the top of the UploadController class. This constant represents the maximum file size limit for file uploads. In this example, the limit is set to 10 megabytes, but you can adjust this value according to your needs.

In the upload action, the size of the uploaded file is retrieved using uploaded_io.size. This size is then compared with the MAX_FILE_SIZE limit. If the file size exceeds the limit, an error message is added to the flash and the user is redirected back to the root URL. The file upload process is then terminated using return.

If the file size is within the limit, the file is written to the server as before. However, the file writing process is now wrapped in a begin-rescue block to handle any potential exceptions or errors that may occur during this process. If an error occurs, an error message is added to the flash and the user is redirected back to the root URL.

This updated code ensures that the system performs an adequate control of the size of the files that can be uploaded to the server, thereby fixing the identified vulnerability.

References