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
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.
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.
Compliant code
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."
redirect_to uploads_path
return
end
params[:files].each do |file|
if file.size > MAX_FILE_SIZE
flash[:error] = "Each file must be less than #{MAX_FILE_SIZE} MB."
redirect_to uploads_path
return
end
uploaded_file = UploadedFile.create(file: file)
if uploaded_file.errors.any?
flash[:error] = uploaded_file.errors.full_messages.join(", ")
redirect_to uploads_path
return
end
end
flash[:success] = "Files uploaded successfully."
redirect_to uploads_path
end
end
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.