diff options
author | Soumya Sambu <soumya.sambu@windriver.com> | 2024-12-27 08:33:32 +0000 |
---|---|---|
committer | Armin Kuster <akuster808@gmail.com> | 2024-12-31 09:04:08 -0500 |
commit | c59e8e9dbcec838eb7699f40a1768bbe7adb3288 (patch) | |
tree | a410ecdeaab3ad1ccb8c110365f9be86bf81c47f | |
parent | c3deda05a749f484a68666ad6de03f690f7bc84b (diff) | |
download | meta-openembedded-c59e8e9dbcec838eb7699f40a1768bbe7adb3288.tar.gz |
python3-werkzeug: Fix CVE-2024-49767
Werkzeug is a Web Server Gateway Interface web application library. Applications
using `werkzeug.formparser.MultiPartParser` corresponding to a version of Werkzeug
prior to 3.0.6 to parse `multipart/form-data` requests (e.g. all flask applications)
are vulnerable to a relatively simple but effective resource exhaustion (denial of
service) attack. A specifically crafted form submission request can cause the parser
to allocate and block 3 to 8 times the upload size in main memory. There is no upper
limit; a single upload at 1 Gbit/s can exhaust 32 GB of RAM in less than 60 seconds.
Werkzeug version 3.0.6 fixes this issue.
Reference:
https://nvd.nist.gov/vuln/detail/CVE-2024-49767
Upstream-patch:
https://github.com/pallets/werkzeug/commit/8760275afb72bd10b57d92cb4d52abf759b2f3a7
Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
-rw-r--r-- | meta-python/recipes-devtools/python/python3-werkzeug/CVE-2024-49767.patch | 87 | ||||
-rw-r--r-- | meta-python/recipes-devtools/python/python3-werkzeug_2.1.1.bb | 3 |
2 files changed, 89 insertions, 1 deletions
diff --git a/meta-python/recipes-devtools/python/python3-werkzeug/CVE-2024-49767.patch b/meta-python/recipes-devtools/python/python3-werkzeug/CVE-2024-49767.patch new file mode 100644 index 0000000000..279c6e522d --- /dev/null +++ b/meta-python/recipes-devtools/python/python3-werkzeug/CVE-2024-49767.patch | |||
@@ -0,0 +1,87 @@ | |||
1 | From 8760275afb72bd10b57d92cb4d52abf759b2f3a7 Mon Sep 17 00:00:00 2001 | ||
2 | From: David Lord <davidism@gmail.com> | ||
3 | Date: Fri, 25 Oct 2024 06:46:50 -0700 | ||
4 | Subject: [PATCH] apply max_form_memory_size another level up in the parser | ||
5 | |||
6 | CVE: CVE-2024-49767 | ||
7 | |||
8 | Upstream-Status: Backport [https://github.com/pallets/werkzeug/commit/8760275afb72bd10b57d92cb4d52abf759b2f3a7] | ||
9 | |||
10 | Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com> | ||
11 | --- | ||
12 | src/werkzeug/formparser.py | 11 +++++++++++ | ||
13 | src/werkzeug/sansio/multipart.py | 2 ++ | ||
14 | tests/test_formparser.py | 12 ++++++++++++ | ||
15 | 3 files changed, 25 insertions(+) | ||
16 | |||
17 | diff --git a/src/werkzeug/formparser.py b/src/werkzeug/formparser.py | ||
18 | index bebb2fc..b82af82 100644 | ||
19 | --- a/src/werkzeug/formparser.py | ||
20 | +++ b/src/werkzeug/formparser.py | ||
21 | @@ -405,6 +405,7 @@ class MultiPartParser: | ||
22 | def parse( | ||
23 | self, stream: t.IO[bytes], boundary: bytes, content_length: t.Optional[int] | ||
24 | ) -> t.Tuple[MultiDict, MultiDict]: | ||
25 | + field_size: int | None = None | ||
26 | container: t.Union[t.IO[bytes], t.List[bytes]] | ||
27 | _write: t.Callable[[bytes], t.Any] | ||
28 | |||
29 | @@ -431,13 +432,23 @@ class MultiPartParser: | ||
30 | while not isinstance(event, (Epilogue, NeedData)): | ||
31 | if isinstance(event, Field): | ||
32 | current_part = event | ||
33 | + field_size = 0 | ||
34 | container = [] | ||
35 | _write = container.append | ||
36 | elif isinstance(event, File): | ||
37 | current_part = event | ||
38 | + field_size = None | ||
39 | container = self.start_file_streaming(event, content_length) | ||
40 | _write = container.write | ||
41 | elif isinstance(event, Data): | ||
42 | + if self.max_form_memory_size is not None and field_size is not None: | ||
43 | + # Ensure that accumulated data events do not exceed limit. | ||
44 | + # Also checked within single event in MultipartDecoder. | ||
45 | + field_size += len(event.data) | ||
46 | + | ||
47 | + if field_size > self.max_form_memory_size: | ||
48 | + raise RequestEntityTooLarge() | ||
49 | + | ||
50 | _write(event.data) | ||
51 | if not event.more_data: | ||
52 | if isinstance(current_part, Field): | ||
53 | diff --git a/src/werkzeug/sansio/multipart.py b/src/werkzeug/sansio/multipart.py | ||
54 | index e7d742b..a91fedd 100644 | ||
55 | --- a/src/werkzeug/sansio/multipart.py | ||
56 | +++ b/src/werkzeug/sansio/multipart.py | ||
57 | @@ -137,6 +137,8 @@ class MultipartDecoder: | ||
58 | self.max_form_memory_size is not None | ||
59 | and len(self.buffer) + len(data) > self.max_form_memory_size | ||
60 | ): | ||
61 | + # Ensure that data within single event does not exceed limit. | ||
62 | + # Also checked across accumulated events in MultiPartParser. | ||
63 | raise RequestEntityTooLarge() | ||
64 | else: | ||
65 | self.buffer.extend(data) | ||
66 | diff --git a/tests/test_formparser.py b/tests/test_formparser.py | ||
67 | index 834324f..1a178dd 100644 | ||
68 | --- a/tests/test_formparser.py | ||
69 | +++ b/tests/test_formparser.py | ||
70 | @@ -459,3 +459,15 @@ class TestMultiPartParser: | ||
71 | ) | ||
72 | assert request.files["rfc2231"].filename == "a b c d e f.txt" | ||
73 | assert request.files["rfc2231"].read() == b"file contents" | ||
74 | + | ||
75 | + | ||
76 | +def test_multipart_max_form_memory_size() -> None: | ||
77 | + """max_form_memory_size is tracked across multiple data events.""" | ||
78 | + data = b"--bound\r\nContent-Disposition: form-field; name=a\r\n\r\n" | ||
79 | + data += b"a" * 15 + b"\r\n--bound--" | ||
80 | + # The buffer size is less than the max size, so multiple data events will be | ||
81 | + # returned. The field size is greater than the max. | ||
82 | + parser = formparser.MultiPartParser(max_form_memory_size=10, buffer_size=5) | ||
83 | + | ||
84 | + with pytest.raises(RequestEntityTooLarge): | ||
85 | + parser.parse(io.BytesIO(data), b"bound", None) | ||
86 | -- | ||
87 | 2.40.0 | ||
diff --git a/meta-python/recipes-devtools/python/python3-werkzeug_2.1.1.bb b/meta-python/recipes-devtools/python/python3-werkzeug_2.1.1.bb index 12f6dff17d..5529686aac 100644 --- a/meta-python/recipes-devtools/python/python3-werkzeug_2.1.1.bb +++ b/meta-python/recipes-devtools/python/python3-werkzeug_2.1.1.bb | |||
@@ -15,7 +15,8 @@ PYPI_PACKAGE = "Werkzeug" | |||
15 | SRC_URI += "file://CVE-2023-25577.patch \ | 15 | SRC_URI += "file://CVE-2023-25577.patch \ |
16 | file://CVE-2023-23934.patch \ | 16 | file://CVE-2023-23934.patch \ |
17 | file://CVE-2024-34069-0001.patch \ | 17 | file://CVE-2024-34069-0001.patch \ |
18 | file://CVE-2024-34069-0002.patch" | 18 | file://CVE-2024-34069-0002.patch \ |
19 | file://CVE-2024-49767.patch" | ||
19 | 20 | ||
20 | SRC_URI[sha256sum] = "f8e89a20aeabbe8a893c24a461d3ee5dad2123b05cc6abd73ceed01d39c3ae74" | 21 | SRC_URI[sha256sum] = "f8e89a20aeabbe8a893c24a461d3ee5dad2123b05cc6abd73ceed01d39c3ae74" |
21 | 22 | ||