++ 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]]
-=-=-=-=-=-=-=-=-=-=-=-

  • ... Narpat Mali via lists.openembedded.org
    • ... Narpat Mali via lists.openembedded.org
      • ... Sanjaykumar kantibhai Chitroda -X (schitrod - E-INFO CHIPS INC at Cisco) via lists.openembedded.org
        • ... Narpat Mali via lists.openembedded.org

Reply via email to