mirror of
https://github.com/django/django.git
synced 2025-10-24 06:06:09 +00:00
[4.2.x] Fixed CVE-2023-31047, Fixed #31710 -- Prevented potential bypass of validation when uploading multiple files using one form field.
Thanks Moataz Al-Sharida and nawaik for reports. Co-authored-by: Shai Berger <shai@platonix.com> Co-authored-by: nessita <124304+nessita@users.noreply.github.com>
This commit is contained in:
@@ -6,4 +6,18 @@ Django 3.2.19 release notes
|
||||
|
||||
Django 3.2.19 fixes a security issue with severity "low" in 3.2.18.
|
||||
|
||||
...
|
||||
CVE-2023-31047: Potential bypass of validation when uploading multiple files using one form field
|
||||
=================================================================================================
|
||||
|
||||
Uploading multiple files using one form field has never been supported by
|
||||
:class:`.forms.FileField` or :class:`.forms.ImageField` as only the last
|
||||
uploaded file was validated. Unfortunately, :ref:`uploading_multiple_files`
|
||||
topic suggested otherwise.
|
||||
|
||||
In order to avoid the vulnerability, :class:`~django.forms.ClearableFileInput`
|
||||
and :class:`~django.forms.FileInput` form widgets now raise ``ValueError`` when
|
||||
the ``multiple`` HTML attribute is set on them. To prevent the exception and
|
||||
keep the old behavior, set ``allow_multiple_selected`` to ``True``.
|
||||
|
||||
For more details on using the new attribute and handling of multiple files
|
||||
through a single field, see :ref:`uploading_multiple_files`.
|
||||
|
||||
@@ -6,4 +6,18 @@ Django 4.1.9 release notes
|
||||
|
||||
Django 4.1.9 fixes a security issue with severity "low" in 4.1.8.
|
||||
|
||||
...
|
||||
CVE-2023-31047: Potential bypass of validation when uploading multiple files using one form field
|
||||
=================================================================================================
|
||||
|
||||
Uploading multiple files using one form field has never been supported by
|
||||
:class:`.forms.FileField` or :class:`.forms.ImageField` as only the last
|
||||
uploaded file was validated. Unfortunately, :ref:`uploading_multiple_files`
|
||||
topic suggested otherwise.
|
||||
|
||||
In order to avoid the vulnerability, :class:`~django.forms.ClearableFileInput`
|
||||
and :class:`~django.forms.FileInput` form widgets now raise ``ValueError`` when
|
||||
the ``multiple`` HTML attribute is set on them. To prevent the exception and
|
||||
keep the old behavior, set ``allow_multiple_selected`` to ``True``.
|
||||
|
||||
For more details on using the new attribute and handling of multiple files
|
||||
through a single field, see :ref:`uploading_multiple_files`.
|
||||
|
||||
@@ -7,6 +7,22 @@ Django 4.2.1 release notes
|
||||
Django 4.2.1 fixes a security issue with severity "low" and several bugs in
|
||||
4.2.
|
||||
|
||||
CVE-2023-31047: Potential bypass of validation when uploading multiple files using one form field
|
||||
=================================================================================================
|
||||
|
||||
Uploading multiple files using one form field has never been supported by
|
||||
:class:`.forms.FileField` or :class:`.forms.ImageField` as only the last
|
||||
uploaded file was validated. Unfortunately, :ref:`uploading_multiple_files`
|
||||
topic suggested otherwise.
|
||||
|
||||
In order to avoid the vulnerability, :class:`~django.forms.ClearableFileInput`
|
||||
and :class:`~django.forms.FileInput` form widgets now raise ``ValueError`` when
|
||||
the ``multiple`` HTML attribute is set on them. To prevent the exception and
|
||||
keep the old behavior, set ``allow_multiple_selected`` to ``True``.
|
||||
|
||||
For more details on using the new attribute and handling of multiple files
|
||||
through a single field, see :ref:`uploading_multiple_files`.
|
||||
|
||||
Bugfixes
|
||||
========
|
||||
|
||||
|
||||
@@ -144,11 +144,27 @@ a :class:`~django.core.files.File` like object to the
|
||||
instance = ModelWithFileField(file_field=content_file)
|
||||
instance.save()
|
||||
|
||||
.. _uploading_multiple_files:
|
||||
|
||||
Uploading multiple files
|
||||
------------------------
|
||||
|
||||
If you want to upload multiple files using one form field, set the ``multiple``
|
||||
HTML attribute of field's widget:
|
||||
..
|
||||
Tests in tests.forms_tests.field_tests.test_filefield.MultipleFileFieldTest
|
||||
should be updated after any changes in the following snippets.
|
||||
|
||||
If you want to upload multiple files using one form field, create a subclass
|
||||
of the field's widget and set the ``allow_multiple_selected`` attribute on it
|
||||
to ``True``.
|
||||
|
||||
In order for such files to be all validated by your form (and have the value of
|
||||
the field include them all), you will also have to subclass ``FileField``. See
|
||||
below for an example.
|
||||
|
||||
.. admonition:: Multiple file field
|
||||
|
||||
Django is likely to have a proper multiple file field support at some point
|
||||
in the future.
|
||||
|
||||
.. code-block:: python
|
||||
:caption: ``forms.py``
|
||||
@@ -156,10 +172,26 @@ HTML attribute of field's widget:
|
||||
from django import forms
|
||||
|
||||
|
||||
class MultipleFileInput(forms.ClearableFileInput):
|
||||
allow_multiple_selected = True
|
||||
|
||||
|
||||
class MultipleFileField(forms.FileField):
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs.setdefault("widget", MultipleFileInput())
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def clean(self, data, initial=None):
|
||||
single_file_clean = super().clean
|
||||
if isinstance(data, (list, tuple)):
|
||||
result = [single_file_clean(d, initial) for d in data]
|
||||
else:
|
||||
result = single_file_clean(data, initial)
|
||||
return result
|
||||
|
||||
|
||||
class FileFieldForm(forms.Form):
|
||||
file_field = forms.FileField(
|
||||
widget=forms.ClearableFileInput(attrs={"multiple": True})
|
||||
)
|
||||
file_field = MultipleFileField()
|
||||
|
||||
Then override the ``post`` method of your
|
||||
:class:`~django.views.generic.edit.FormView` subclass to handle multiple file
|
||||
@@ -180,14 +212,32 @@ uploads:
|
||||
def post(self, request, *args, **kwargs):
|
||||
form_class = self.get_form_class()
|
||||
form = self.get_form(form_class)
|
||||
files = request.FILES.getlist("file_field")
|
||||
if form.is_valid():
|
||||
for f in files:
|
||||
... # Do something with each file.
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
|
||||
def form_valid(self, form):
|
||||
files = form.cleaned_data["file_field"]
|
||||
for f in files:
|
||||
... # Do something with each file.
|
||||
return super().form_valid()
|
||||
|
||||
.. warning::
|
||||
|
||||
This will allow you to handle multiple files at the form level only. Be
|
||||
aware that you cannot use it to put multiple files on a single model
|
||||
instance (in a single field), for example, even if the custom widget is used
|
||||
with a form field related to a model ``FileField``.
|
||||
|
||||
.. versionchanged:: 3.2.19
|
||||
|
||||
In previous versions, there was no support for the ``allow_multiple_selected``
|
||||
class attribute, and users were advised to create the widget with the HTML
|
||||
attribute ``multiple`` set through the ``attrs`` argument. However, this
|
||||
caused validation of the form field to be applied only to the last file
|
||||
submitted, which could have adverse security implications.
|
||||
|
||||
Upload Handlers
|
||||
===============
|
||||
|
||||
|
||||
Reference in New Issue
Block a user