From 5c62c725b1922ab94808ac577d71e0f4c09573b2 Mon Sep 17 00:00:00 2001 From: liningjie Date: Mon, 30 Sep 2024 02:55:37 +0800 Subject: [PATCH] Fix CVE-2024-49767 (cherry picked from commit c7566002c0a7d671ce568caacd3be66f7a70d536) --- ...ax_form_memory_size-another-level-up.patch | 83 +++++++++++++++++++ python-werkzeug.spec | 6 +- 2 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 CVE-2024-49767--apply-max_form_memory_size-another-level-up.patch diff --git a/CVE-2024-49767--apply-max_form_memory_size-another-level-up.patch b/CVE-2024-49767--apply-max_form_memory_size-another-level-up.patch new file mode 100644 index 0000000..63ceb8c --- /dev/null +++ b/CVE-2024-49767--apply-max_form_memory_size-another-level-up.patch @@ -0,0 +1,83 @@ +From 8760275afb72bd10b57d92cb4d52abf759b2f3a7 Mon Sep 17 00:00:00 2001 +From: David Lord +Date: Fri, 25 Oct 2024 06:46:50 -0700 +Subject: [PATCH] apply max_form_memory_size another level up in the parser + +--- + src/werkzeug/formparser.py | 11 +++++++++++ + src/werkzeug/sansio/multipart.py | 2 ++ + tests/test_formparser.py | 12 ++++++++++++ + 3 files changed, 25 insertions(+) + +diff --git a/src/werkzeug/formparser.py b/src/werkzeug/formparser.py +index bebb2fc..b82af82 100644 +--- a/src/werkzeug/formparser.py ++++ b/src/werkzeug/formparser.py +@@ -405,6 +405,7 @@ class MultiPartParser: + def parse( + self, stream: t.IO[bytes], boundary: bytes, content_length: t.Optional[int] + ) -> t.Tuple[MultiDict, MultiDict]: ++ field_size: int | None = None + container: t.Union[t.IO[bytes], t.List[bytes]] + _write: t.Callable[[bytes], t.Any] + +@@ -431,13 +432,23 @@ class MultiPartParser: + while not isinstance(event, (Epilogue, NeedData)): + if isinstance(event, Field): + current_part = event ++ field_size = 0 + container = [] + _write = container.append + elif isinstance(event, File): + current_part = event ++ field_size = None + container = self.start_file_streaming(event, content_length) + _write = container.write + elif isinstance(event, Data): ++ if self.max_form_memory_size is not None and field_size is not None: ++ # Ensure that accumulated data events do not exceed limit. ++ # Also checked within single event in MultipartDecoder. ++ field_size += len(event.data) ++ ++ if field_size > self.max_form_memory_size: ++ raise RequestEntityTooLarge() ++ + _write(event.data) + if not event.more_data: + if isinstance(current_part, Field): +diff --git a/src/werkzeug/sansio/multipart.py b/src/werkzeug/sansio/multipart.py +index 2684e5d..e2b0e79 100644 +--- a/src/werkzeug/sansio/multipart.py ++++ b/src/werkzeug/sansio/multipart.py +@@ -142,6 +142,8 @@ class MultipartDecoder: + self.max_form_memory_size is not None + and len(self.buffer) + len(data) > self.max_form_memory_size + ): ++ # Ensure that data within single event does not exceed limit. ++ # Also checked across accumulated events in MultiPartParser. + raise RequestEntityTooLarge() + else: + self.buffer.extend(data) +diff --git a/tests/test_formparser.py b/tests/test_formparser.py +index 4c518b1..05fa84e 100644 +--- a/tests/test_formparser.py ++++ b/tests/test_formparser.py +@@ -455,3 +455,15 @@ class TestMultiPartParser: + ) as request: + assert request.files["rfc2231"].filename == "a b c d e f.txt" + assert request.files["rfc2231"].read() == b"file contents" ++ ++ ++def test_multipart_max_form_memory_size() -> None: ++ """max_form_memory_size is tracked across multiple data events.""" ++ data = b"--bound\r\nContent-Disposition: form-field; name=a\r\n\r\n" ++ data += b"a" * 15 + b"\r\n--bound--" ++ # The buffer size is less than the max size, so multiple data events will be ++ # returned. The field size is greater than the max. ++ parser = formparser.MultiPartParser(max_form_memory_size=10, buffer_size=5) ++ ++ with pytest.raises(RequestEntityTooLarge): ++ parser.parse(io.BytesIO(data), b"bound", None) +-- +2.33.0 + diff --git a/python-werkzeug.spec b/python-werkzeug.spec index 56a37b9..1a0f0ba 100644 --- a/python-werkzeug.spec +++ b/python-werkzeug.spec @@ -1,7 +1,7 @@ %global _empty_manifest_terminate_build 0 Name: python-werkzeug Version: 2.2.3 -Release: 2 +Release: 3 Summary: The comprehensive WSGI web application library. License: BSD-3-Clause URL: https://palletsprojects.com/p/werkzeug/ @@ -11,6 +11,7 @@ Source1: https://github.com/Yelp/ephemeral-port-reserve/blob/master/ephem Patch01: CVE-2024-34069-restrict-debugger-trusted-hosts.patch Patch02: CVE-2024-34069-only-require-trusted-host-for-evalex.patch +Patch03: CVE-2024-49767--apply-max_form_memory_size-another-level-up.patch BuildArch: noarch BuildRequires: python3-werkzeug python3-markupsafe @@ -174,6 +175,9 @@ PYTHONPATH=%{buildroot}%{python3_sitelib} pytest -k 'not (test_serving)' %{_docdir}/* %changelog +* Sat Oct 26 2024 liningjie - 2.2.3-3 +- Fix CVE-2024-49767 + * Tue May 07 2024 yinyongkang - 2.2.3-2 - fix CVE-2024-34069 -- Gitee