From 1955425d20adf8372e979009c59bad9e516272d8db2dec7ffc6d43d207ab8210 Mon Sep 17 00:00:00 2001 From: Matej Cepl Date: Thu, 5 Sep 2024 13:45:40 +0000 Subject: [PATCH] - Add CVE-2024-6232-cookies-quad-complex.patch to avoid quadratic complexity in parsing "-quoted cookie values with backslashes (bsc#1229596, CVE-2024-6232). OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python39?expand=0&rev=199 --- CVE-2024-6232-cookies-quad-complex.patch | 125 +++++++++++++++++++++++ python39.changes | 7 ++ python39.spec | 4 + 3 files changed, 136 insertions(+) create mode 100644 CVE-2024-6232-cookies-quad-complex.patch diff --git a/CVE-2024-6232-cookies-quad-complex.patch b/CVE-2024-6232-cookies-quad-complex.patch new file mode 100644 index 0000000..8522381 --- /dev/null +++ b/CVE-2024-6232-cookies-quad-complex.patch @@ -0,0 +1,125 @@ +From 15eec9d5076b780463c3dc73afcef688651c5295 Mon Sep 17 00:00:00 2001 +From: Serhiy Storchaka +Date: Sat, 17 Aug 2024 16:30:52 +0300 +Subject: [PATCH] gh-123067: Fix quadratic complexity in parsing "-quoted + cookie values with backslashes (GH-123075) + +This fixes CVE-2024-7592. +(cherry picked from commit 44e458357fca05ca0ae2658d62c8c595b048b5ef) + +Co-authored-by: Serhiy Storchaka +--- + Lib/http/cookies.py | 34 ++------ + Lib/test/test_http_cookies.py | 38 ++++++++++ + Misc/NEWS.d/next/Library/2024-08-16-19-13-21.gh-issue-123067.Nx9O4R.rst | 1 + 3 files changed, 47 insertions(+), 26 deletions(-) + create mode 100644 Misc/NEWS.d/next/Library/2024-08-16-19-13-21.gh-issue-123067.Nx9O4R.rst + +--- a/Lib/http/cookies.py ++++ b/Lib/http/cookies.py +@@ -184,8 +184,13 @@ def _quote(str): + return '"' + str.translate(_Translator) + '"' + + +-_OctalPatt = re.compile(r"\\[0-3][0-7][0-7]") +-_QuotePatt = re.compile(r"[\\].") ++_unquote_sub = re.compile(r'\\(?:([0-3][0-7][0-7])|(.))').sub ++ ++def _unquote_replace(m): ++ if m[1]: ++ return chr(int(m[1], 8)) ++ else: ++ return m[2] + + def _unquote(str): + # If there aren't any doublequotes, +@@ -205,30 +210,7 @@ def _unquote(str): + # \012 --> \n + # \" --> " + # +- i = 0 +- n = len(str) +- res = [] +- while 0 <= i < n: +- o_match = _OctalPatt.search(str, i) +- q_match = _QuotePatt.search(str, i) +- if not o_match and not q_match: # Neither matched +- res.append(str[i:]) +- break +- # else: +- j = k = -1 +- if o_match: +- j = o_match.start(0) +- if q_match: +- k = q_match.start(0) +- if q_match and (not o_match or k < j): # QuotePatt matched +- res.append(str[i:k]) +- res.append(str[k+1]) +- i = k + 2 +- else: # OctalPatt matched +- res.append(str[i:j]) +- res.append(chr(int(str[j+1:j+4], 8))) +- i = j + 4 +- return _nulljoin(res) ++ return _unquote_sub(_unquote_replace, str) + + # The _getdate() routine is used to set the expiration time in the cookie's HTTP + # header. By default, _getdate() returns the current time in the appropriate +--- a/Lib/test/test_http_cookies.py ++++ b/Lib/test/test_http_cookies.py +@@ -5,6 +5,7 @@ from test.support import run_unittest, r + import unittest + from http import cookies + import pickle ++from test import support + + + class CookieTests(unittest.TestCase): +@@ -58,6 +59,43 @@ class CookieTests(unittest.TestCase): + for k, v in sorted(case['dict'].items()): + self.assertEqual(C[k].value, v) + ++ def test_unquote(self): ++ cases = [ ++ (r'a="b=\""', 'b="'), ++ (r'a="b=\\"', 'b=\\'), ++ (r'a="b=\="', 'b=='), ++ (r'a="b=\n"', 'b=n'), ++ (r'a="b=\042"', 'b="'), ++ (r'a="b=\134"', 'b=\\'), ++ (r'a="b=\377"', 'b=\xff'), ++ (r'a="b=\400"', 'b=400'), ++ (r'a="b=\42"', 'b=42'), ++ (r'a="b=\\042"', 'b=\\042'), ++ (r'a="b=\\134"', 'b=\\134'), ++ (r'a="b=\\\""', 'b=\\"'), ++ (r'a="b=\\\042"', 'b=\\"'), ++ (r'a="b=\134\""', 'b=\\"'), ++ (r'a="b=\134\042"', 'b=\\"'), ++ ] ++ for encoded, decoded in cases: ++ with self.subTest(encoded): ++ C = cookies.SimpleCookie() ++ C.load(encoded) ++ self.assertEqual(C['a'].value, decoded) ++ ++ @support.requires_resource('cpu') ++ def test_unquote_large(self): ++ n = 10**6 ++ for encoded in r'\\', r'\134': ++ with self.subTest(encoded): ++ data = 'a="b=' + encoded*n + ';"' ++ C = cookies.SimpleCookie() ++ C.load(data) ++ value = C['a'].value ++ self.assertEqual(value[:3], 'b=\\') ++ self.assertEqual(value[-2:], '\\;') ++ self.assertEqual(len(value), n + 3) ++ + def test_load(self): + C = cookies.SimpleCookie() + C.load('Customer="WILE_E_COYOTE"; Version=1; Path=/acme') +--- /dev/null ++++ b/Misc/NEWS.d/next/Library/2024-08-16-19-13-21.gh-issue-123067.Nx9O4R.rst +@@ -0,0 +1 @@ ++Fix quadratic complexity in parsing ``"``-quoted cookie values with backslashes by :mod:`http.cookies`. diff --git a/python39.changes b/python39.changes index 194295b..31d0635 100644 --- a/python39.changes +++ b/python39.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Thu Sep 5 13:44:48 UTC 2024 - Matej Cepl + +- Add CVE-2024-6232-cookies-quad-complex.patch to avoid quadratic + complexity in parsing "-quoted cookie values with backslashes + (bsc#1229596, CVE-2024-6232). + ------------------------------------------------------------------- Thu Sep 5 08:11:45 UTC 2024 - Matej Cepl diff --git a/python39.spec b/python39.spec index d8eebce..dfa2e3f 100644 --- a/python39.spec +++ b/python39.spec @@ -208,6 +208,9 @@ Patch49: CVE-2024-8088-inf-loop-zipfile_Path.patch # PATCH-FIX-UPSTREAM gh120226-fix-sendfile-test-kernel-610.patch gh#python/cpython#120226 mcepl@suse.com # Fix test_sendfile_close_peer_in_the_middle_of_receiving on Linux >= 6.10 (GH-120227) Patch50: gh120226-fix-sendfile-test-kernel-610.patch +# PATCH-FIX-UPSTREAM CVE-2024-6232-cookies-quad-complex.patch bsc#1229596 mcepl@suse.com +# avoid quadratic complexity in parsing "-quoted cookie values with backslashes +Patch51: CVE-2024-6232-cookies-quad-complex.patch BuildRequires: autoconf-archive BuildRequires: automake BuildRequires: fdupes @@ -479,6 +482,7 @@ other applications. %patch -p1 -P 48 %patch -p1 -P 49 %patch -p1 -P 50 +%patch -p1 -P 51 # drop Autoconf version requirement sed -i 's/^AC_PREREQ/dnl AC_PREREQ/' configure.ac