Insecure file upload - Files Limit - Python

Insecure file upload - Files Limit - Python

Need

Enforce file upload limits and implement proper file management

Context

  • Usage of Python 3 for developing Python applications
  • Usage of Django for building web applications in Python

Description

Non compliant code

        from django.http import JsonResponse
from django.views import View
from .models import Document
from .forms import DocumentForm

class UploadFileView(View):
    def post(self, request):
        form = DocumentForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            return JsonResponse({'message': 'File uploaded successfully.'}, status=200)
        else:
            return JsonResponse({'message': 'File upload failed.'}, status=400)
        
        

The above code represents a Django view that allows users to upload files to the server. The UploadFileView class handles the POST method, where it expects a file to be uploaded.

The post method of UploadFileView uses Django's forms to handle the file upload. It creates a DocumentForm instance, passing the request.POST and request.FILES as arguments. The request.FILES contains all the uploaded files.

The form.is_valid() checks whether the uploaded file meets the requirements defined in the DocumentForm. If the form is valid, it saves the file to the server using form.save() and returns a success message. If the form is not valid, it returns a failure message.

The vulnerability in this code is that there is no limit to the number of files a user can upload. A malicious user can exploit this by uploading a large number of files, potentially filling up the server's storage and causing a Denial of Service (DoS). Additionally, uploading a new file does not delete the previous one from the server, further exacerbating the potential for storage exhaustion.

Steps

  • Implement a file upload limit per user per unit of time. This can be done by keeping track of the number of files a user has uploaded within a certain time frame.
  • Delete or overwrite old files when a new one is uploaded. This can be done by checking if a file already exists for the user before saving a new one.
  • Implement a system-wide limit on the total number of files that can be stored. This can be done by keeping track of the total number of files stored and preventing new uploads when the limit is reached.
  • Consider using a third-party service for file storage if the number of files is expected to be large. This can help manage storage and prevent the server from being overwhelmed.

Compliant code

        from django.http import JsonResponse
from django.views import View
from .models import Document
from .forms import DocumentForm
from django.utils import timezone
from datetime import timedelta

class UploadFileView(View):
    FILE_UPLOAD_LIMIT = 10
    TIME_LIMIT = timedelta(hours=1)

    def post(self, request):
        form = DocumentForm(request.POST, request.FILES)
        if form.is_valid():
            user = request.user
            now = timezone.now()
            recent_uploads = Document.objects.filter(user=user, uploaded_at__gte=now-self.TIME_LIMIT).count()

            if recent_uploads >= self.FILE_UPLOAD_LIMIT:
                return JsonResponse({'message': 'Upload limit reached.'}, status=400)

            existing_file = Document.objects.filter(user=user).first()
            if existing_file:
                existing_file.delete()

            form.save()
            return JsonResponse({'message': 'File uploaded successfully.'}, status=200)
        else:
            return JsonResponse({'message': 'File upload failed.'}, status=400)
        
        

The updated code now includes a limit on the number of files a user can upload within a certain time frame (1 hour in this case). This is done by counting the number of files the user has uploaded within the last hour and comparing it to a predefined limit (10 files in this case). If the user has reached or exceeded the limit, the server responds with a message indicating that the upload limit has been reached.

In addition, the code now checks if a file already exists for the user before saving a new one. If a file does exist, it is deleted before the new file is saved. This ensures that each user can only have one file stored on the server at a time.

These changes help prevent the server from being overwhelmed by a large number of file uploads and ensure that old files are not left on the server when new ones are uploaded.

References