++ Armin Hi Narpat,
FYI, meta-oe layer kirkstone branch python3-django package is already bump to 4.2.1 version with following commit: https://github.com/openembedded/meta-openembedded/commit/84782522d145f55e4076699c4bb00bcb4cec98da python3-django version 4.2.1 https://github.com/django/django/commits/4.2.1 has fix available for CVE-2023-31047: https://github.com/django/django/commit/21b1b1fc03e5f9e9f8c977ee6e35618dd3b353dd If you still have any query for the same: you can connect with Armin ([email protected]). Thanks, Sanjay -----Original Message----- From: [email protected] <[email protected]> On Behalf Of Narpat Mali via lists.openembedded.org Sent: Thursday, June 15, 2023 8:29 PM To: [email protected] Cc: [email protected] Subject: Re: [oe] [meta-python][kirkstone][PATCH 1/1] python3-django: fix for CVE-2023-31047 Reminder. On 26-05-2023 19:11, Narpat Mali via lists.openembedded.org wrote: > From: Narpat Mali <[email protected]> > > In Django 3.2 before 3.2.19, 4.x before 4.1.9, and 4.2 before 4.2.1, > it was possible to bypass validation when using one form field to > upload multiple files. This multiple upload has never been supported > by forms.FileField or forms.ImageField (only the last uploaded file > was validated). However, Django's "Uploading multiple files" > documentation suggested otherwise. > > Since, there is no ptest available for python3-django so have not > tested the patch changes at runtime. > > Signed-off-by: Narpat Mali <[email protected]> > --- > .../python3-django/CVE-2023-31047.patch | 352 ++++++++++++++++++ > .../python/python3-django_2.2.28.bb | 2 + > 2 files changed, 354 insertions(+) > create mode 100644 > meta-python/recipes-devtools/python/python3-django/CVE-2023-31047.patc > h > > diff --git > a/meta-python/recipes-devtools/python/python3-django/CVE-2023-31047.pa > tch > b/meta-python/recipes-devtools/python/python3-django/CVE-2023-31047.pa > tch > new file mode 100644 > index 0000000000..ab29a2ed97 > --- /dev/null > +++ b/meta-python/recipes-devtools/python/python3-django/CVE-2023-3104 > +++ 7.patch > @@ -0,0 +1,352 @@ > +From fd3215dec5d50aa1f09cb1f8eba193524e7379f3 Mon Sep 17 00:00:00 > +2001 > +From: Mariusz Felisiak <[email protected]> > +Date: Thu, 25 May 2023 14:49:15 +0000 > +Subject: [PATCH] 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 <[email protected]> > +Co-authored-by: nessita <[email protected]> > + > +CVE: CVE-2023-31047 > + > +Upstream-Status: Backport > +[https://github.com/django/django/commit/fb4c55d9ec4bb812a7fb91fa2051 > +0d91645e411b] > + > +Signed-off-by: Narpat Mali <[email protected]> > +--- > + django/forms/widgets.py | 26 ++++++- > + docs/releases/2.2.28.txt | 18 +++++ > + docs/topics/http/file-uploads.txt | 65 ++++++++++++++++-- > + .../forms_tests/field_tests/test_filefield.py | 68 ++++++++++++++++++- > + .../widget_tests/test_clearablefileinput.py | 5 ++ > + .../widget_tests/test_fileinput.py | 44 ++++++++++++ > + 6 files changed, 218 insertions(+), 8 deletions(-) > + > +diff --git a/django/forms/widgets.py b/django/forms/widgets.py index > +e37036c..d0cc131 100644 > +--- a/django/forms/widgets.py > ++++ b/django/forms/widgets.py > +@@ -372,17 +372,41 @@ class MultipleHiddenInput(HiddenInput): > + > + > + class FileInput(Input): > ++ allow_multiple_selected = False > + input_type = 'file' > + needs_multipart_form = True > + template_name = 'django/forms/widgets/file.html' > + > ++ def __init__(self, attrs=None): > ++ if ( > ++ attrs is not None > ++ and not self.allow_multiple_selected > ++ and attrs.get("multiple", False) > ++ ): > ++ raise ValueError( > ++ "%s doesn't support uploading multiple files." > ++ % self.__class__.__qualname__ > ++ ) > ++ if self.allow_multiple_selected: > ++ if attrs is None: > ++ attrs = {"multiple": True} > ++ else: > ++ attrs.setdefault("multiple", True) > ++ super().__init__(attrs) > ++ > + def format_value(self, value): > + """File input never renders a value.""" > + return > + > + def value_from_datadict(self, data, files, name): > + "File widgets take data from FILES, not POST" > +- return files.get(name) > ++ getter = files.get > ++ if self.allow_multiple_selected: > ++ try: > ++ getter = files.getlist > ++ except AttributeError: > ++ pass > ++ return getter(name) > + > + def value_omitted_from_data(self, data, files, name): > + return name not in files > +diff --git a/docs/releases/2.2.28.txt b/docs/releases/2.2.28.txt > +index 43270fc..854c6b0 100644 > +--- a/docs/releases/2.2.28.txt > ++++ b/docs/releases/2.2.28.txt > +@@ -20,3 +20,21 @@ CVE-2022-28347: Potential SQL injection via > +``QuerySet.explain(**options)`` on P :meth:`.QuerySet.explain` > +method was subject to SQL injection in option names, using a > +suitably crafted dictionary, with dictionary expansion, as the > ``**options`` argument. > ++ > ++Backporting the CVE-2023-31047 fix on Django 2.2.28. > ++ > ++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`. > +diff --git a/docs/topics/http/file-uploads.txt > +b/docs/topics/http/file-uploads.txt > +index 21a6f06..c1ffb80 100644 > +--- a/docs/topics/http/file-uploads.txt > ++++ b/docs/topics/http/file-uploads.txt > +@@ -127,19 +127,54 @@ field in the model:: > + form = UploadFileForm() > + return render(request, 'upload.html', {'form': form}) > + > ++.. _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 > + > + 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 @@ -159,14 +194,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``. > ++ > ++.. backportedfix:: 2.2.28 > ++ > ++ 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 > + =============== > + > +diff --git a/tests/forms_tests/field_tests/test_filefield.py > +b/tests/forms_tests/field_tests/test_filefield.py > +index 3357444..ba559ee 100644 > +--- a/tests/forms_tests/field_tests/test_filefield.py > ++++ b/tests/forms_tests/field_tests/test_filefield.py > +@@ -1,7 +1,8 @@ > + import pickle > + > + from django.core.files.uploadedfile import SimpleUploadedFile -from > +django.forms import FileField, ValidationError > ++from django.core.validators import validate_image_file_extension > ++from django.forms import FileField, FileInput, ValidationError > + from django.test import SimpleTestCase > + > + > +@@ -82,3 +83,68 @@ class FileFieldTest(SimpleTestCase): > + > + def test_file_picklable(self): > + > + self.assertIsInstance(pickle.loads(pickle.dumps(FileField())), > + FileField) > ++ > ++ > ++class MultipleFileInput(FileInput): > ++ allow_multiple_selected = True > ++ > ++ > ++class MultipleFileField(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 MultipleFileFieldTest(SimpleTestCase): > ++ def test_file_multiple(self): > ++ f = MultipleFileField() > ++ files = [ > ++ SimpleUploadedFile("name1", b"Content 1"), > ++ SimpleUploadedFile("name2", b"Content 2"), > ++ ] > ++ self.assertEqual(f.clean(files), files) > ++ > ++ def test_file_multiple_empty(self): > ++ f = MultipleFileField() > ++ files = [ > ++ SimpleUploadedFile("empty", b""), > ++ SimpleUploadedFile("nonempty", b"Some Content"), > ++ ] > ++ msg = "'The submitted file is empty.'" > ++ with self.assertRaisesMessage(ValidationError, msg): > ++ f.clean(files) > ++ with self.assertRaisesMessage(ValidationError, msg): > ++ f.clean(files[::-1]) > ++ > ++ def test_file_multiple_validation(self): > ++ f = > ++ MultipleFileField(validators=[validate_image_file_extension]) > ++ > ++ good_files = [ > ++ SimpleUploadedFile("image1.jpg", b"fake JPEG"), > ++ SimpleUploadedFile("image2.png", b"faux image"), > ++ SimpleUploadedFile("image3.bmp", b"fraudulent bitmap"), > ++ ] > ++ self.assertEqual(f.clean(good_files), good_files) > ++ > ++ evil_files = [ > ++ SimpleUploadedFile("image1.sh", b"#!/bin/bash -c 'echo > pwned!'\n"), > ++ SimpleUploadedFile("image2.png", b"faux image"), > ++ SimpleUploadedFile("image3.jpg", b"fake JPEG"), > ++ ] > ++ > ++ evil_rotations = ( > ++ evil_files[i:] + evil_files[:i] # Rotate by i. > ++ for i in range(len(evil_files)) > ++ ) > ++ msg = "File extension “sh” is not allowed. Allowed extensions are: " > ++ for rotated_evil_files in evil_rotations: > ++ with self.assertRaisesMessage(ValidationError, msg): > ++ f.clean(rotated_evil_files) > +diff --git > +a/tests/forms_tests/widget_tests/test_clearablefileinput.py > +b/tests/forms_tests/widget_tests/test_clearablefileinput.py > +index 2ba376d..8d9e38a 100644 > +--- a/tests/forms_tests/widget_tests/test_clearablefileinput.py > ++++ b/tests/forms_tests/widget_tests/test_clearablefileinput.py > +@@ -161,3 +161,8 @@ class ClearableFileInputTest(WidgetTest): > + self.assertIs(widget.value_omitted_from_data({}, {}, 'field'), True) > + self.assertIs(widget.value_omitted_from_data({}, {'field': 'x'}, > 'field'), False) > + self.assertIs(widget.value_omitted_from_data({'field-clear': > +'y'}, {}, 'field'), False) > ++ > ++ def test_multiple_error(self): > ++ msg = "ClearableFileInput doesn't support uploading multiple files." > ++ with self.assertRaisesMessage(ValueError, msg): > ++ ClearableFileInput(attrs={"multiple": True}) > +diff --git a/tests/forms_tests/widget_tests/test_fileinput.py > +b/tests/forms_tests/widget_tests/test_fileinput.py > +index bbd7c7f..24daf5d 100644 > +--- a/tests/forms_tests/widget_tests/test_fileinput.py > ++++ b/tests/forms_tests/widget_tests/test_fileinput.py > +@@ -1,4 +1,6 @@ > ++from django.core.files.uploadedfile import SimpleUploadedFile > + from django.forms import FileInput > ++from django.utils.datastructures import MultiValueDict > + > + from .base import WidgetTest > + > +@@ -18,3 +20,45 @@ class FileInputTest(WidgetTest): > + def test_value_omitted_from_data(self): > + self.assertIs(self.widget.value_omitted_from_data({}, {}, 'field'), > True) > + self.assertIs(self.widget.value_omitted_from_data({}, > +{'field': 'value'}, 'field'), False) > ++ > ++ def test_multiple_error(self): > ++ msg = "FileInput doesn't support uploading multiple files." > ++ with self.assertRaisesMessage(ValueError, msg): > ++ FileInput(attrs={"multiple": True}) > ++ > ++ def test_value_from_datadict_multiple(self): > ++ class MultipleFileInput(FileInput): > ++ allow_multiple_selected = True > ++ > ++ file_1 = SimpleUploadedFile("something1.txt", b"content 1") > ++ file_2 = SimpleUploadedFile("something2.txt", b"content 2") > ++ # Uploading multiple files is allowed. > ++ widget = MultipleFileInput(attrs={"multiple": True}) > ++ value = widget.value_from_datadict( > ++ data={"name": "Test name"}, > ++ files=MultiValueDict({"myfile": [file_1, file_2]}), > ++ name="myfile", > ++ ) > ++ self.assertEqual(value, [file_1, file_2]) > ++ # Uploading multiple files is not allowed. > ++ widget = FileInput() > ++ value = widget.value_from_datadict( > ++ data={"name": "Test name"}, > ++ files=MultiValueDict({"myfile": [file_1, file_2]}), > ++ name="myfile", > ++ ) > ++ self.assertEqual(value, file_2) > ++ > ++ def test_multiple_default(self): > ++ class MultipleFileInput(FileInput): > ++ allow_multiple_selected = True > ++ > ++ tests = [ > ++ (None, True), > ++ ({"class": "myclass"}, True), > ++ ({"multiple": False}, False), > ++ ] > ++ for attrs, expected in tests: > ++ with self.subTest(attrs=attrs): > ++ widget = MultipleFileInput(attrs=attrs) > ++ self.assertIs(widget.attrs["multiple"], expected) > +-- > +2.40.0 > diff --git > a/meta-python/recipes-devtools/python/python3-django_2.2.28.bb > b/meta-python/recipes-devtools/python/python3-django_2.2.28.bb > index 9ef988176e..77a1a2a740 100644 > --- a/meta-python/recipes-devtools/python/python3-django_2.2.28.bb > +++ b/meta-python/recipes-devtools/python/python3-django_2.2.28.bb > @@ -5,6 +5,8 @@ UPSTREAM_CHECK_REGEX = > "/${PYPI_PACKAGE}/(?P<pver>(2\.2\.\d*)+)/" > > inherit setuptools3 > > +SRC_URI += "file://CVE-2023-31047.patch" > + > SRC_URI[sha256sum] = > "0200b657afbf1bc08003845ddda053c7641b9b24951e52acd51f6abda33a7413" > > RDEPENDS:${PN} += "\ > > >
-=-=-=-=-=-=-=-=-=-=-=- Links: You receive all messages sent to this group. View/Reply Online (#103322): https://lists.openembedded.org/g/openembedded-devel/message/103322 Mute This Topic: https://lists.openembedded.org/mt/99149928/21656 Group Owner: [email protected] Unsubscribe: https://lists.openembedded.org/g/openembedded-devel/unsub [[email protected]] -=-=-=-=-=-=-=-=-=-=-=-
