From e7ad6ea4b1153defc36c56ec6c99cf7a70cdabc5 Mon Sep 17 00:00:00 2001 From: huangduirong Date: Tue, 9 Aug 2022 09:49:14 +0800 Subject: [PATCH] Fix CVE-2022-36359 --- backport-CVE-2022-36359.patch | 74 +++++++++++++++++++++++++++++++++++ python-django.spec | 9 ++++- 2 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 backport-CVE-2022-36359.patch diff --git a/backport-CVE-2022-36359.patch b/backport-CVE-2022-36359.patch new file mode 100644 index 0000000..97dc3ff --- /dev/null +++ b/backport-CVE-2022-36359.patch @@ -0,0 +1,74 @@ +From 8c5a1dfe34ea52cc2af21064a8654bfaa8b7a012 Mon Sep 17 00:00:00 2001 +From: Carlton Gibson +Date: Wed, 27 Jul 2022 10:27:42 +0200 +Subject: [PATCH] [3.2.x] Fixed CVE-2022-36359: Escaped filename in + Content-Disposition header. + +Thanks to Motoyasu Saburi for the report. +--- + django/http/response.py | 4 +++- + docs/releases/3.2.15.txt | 8 ++++++- + tests/responses/test_fileresponse.py | 35 ++++++++++++++++++++++++++++ + 3 files changed, 45 insertions(+), 2 deletions(-) + +diff --git a/django/http/response.py b/django/http/response.py +index 1c22edaff3..73f87d7bda 100644 +--- a/django/http/response.py ++++ b/django/http/response.py +@@ -485,7 +485,9 @@ class FileResponse(StreamingHttpResponse): + disposition = 'attachment' if self.as_attachment else 'inline' + try: + filename.encode('ascii') +- file_expr = 'filename="{}"'.format(filename) ++ file_expr = 'filename="{}"'.format( ++ filename.replace('\\', '\\\\').replace('"', r'\"') ++ ) + except UnicodeEncodeError: + file_expr = "filename*=utf-8''{}".format(quote(filename)) + self.headers['Content-Disposition'] = '{}; {}'.format(disposition, file_expr) +diff --git a/tests/responses/test_fileresponse.py b/tests/responses/test_fileresponse.py +index 46d407bdf5..b4ef82ef3e 100644 +--- a/tests/responses/test_fileresponse.py ++++ b/tests/responses/test_fileresponse.py +@@ -89,3 +89,38 @@ class FileResponseTests(SimpleTestCase): + response.headers['Content-Disposition'], + "attachment; filename*=utf-8''%E7%A5%9D%E6%82%A8%E5%B9%B3%E5%AE%89.odt" + ) ++ ++ def test_content_disposition_escaping(self): ++ # fmt: off ++ tests = [ ++ ( ++ 'multi-part-one";\" dummy".txt', ++ r"multi-part-one\";\" dummy\".txt" ++ ), ++ ] ++ # fmt: on ++ # Non-escape sequence backslashes are path segments on Windows, and are ++ # eliminated by an os.path.basename() check in FileResponse. ++ if sys.platform != "win32": ++ # fmt: off ++ tests += [ ++ ( ++ 'multi-part-one\\";\" dummy".txt', ++ r"multi-part-one\\\";\" dummy\".txt" ++ ), ++ ( ++ 'multi-part-one\\";\\\" dummy".txt', ++ r"multi-part-one\\\";\\\" dummy\".txt" ++ ) ++ ] ++ # fmt: on ++ for filename, escaped in tests: ++ with self.subTest(filename=filename, escaped=escaped): ++ response = FileResponse( ++ io.BytesIO(b"binary content"), filename=filename, as_attachment=True ++ ) ++ response.close() ++ self.assertEqual( ++ response.headers["Content-Disposition"], ++ f'attachment; filename="{escaped}"', ++ ) +-- +2.36.1 + diff --git a/python-django.spec b/python-django.spec index 9d56b23..5abf8fd 100644 --- a/python-django.spec +++ b/python-django.spec @@ -1,13 +1,14 @@ %global _empty_manifest_terminate_build 0 Name: python-django Version: 3.2.12 -Release: 2 +Release: 3 Summary: A high-level Python Web framework that encourages rapid development and clean, pragmatic design. License: Apache-2.0 and Python-2.0 and BSD-3-Clause URL: https://www.djangoproject.com/ Source0: https://github.com/django/django/archive/refs/tags/3.2.12.tar.gz #https://github.com/django/django/commit/a9010fe5555e6086a9d9ae50069579400ef0685e Patch0: CVE-2022-34265.patch +Patch1: backport-CVE-2022-36359.patch BuildArch: noarch @@ -75,6 +76,12 @@ mv %{buildroot}/doclist.lst . %{_docdir}/* %changelog +* Tue Aug 09 2022 huangduirong - 3.2.12-3 +- Type: bugfix +- CVE: CVE-2022-36359 +- SUG: NA +- DESC: Fix CVE-2022-36359 + * Tue Jul 05 2022 yaoxin - 3.2.12-2 - Fix CVE-2022-34265