Package: release.debian.org
Severity: normal
Tags: bookworm
X-Debbugs-Cc: python-torn...@packages.debian.org
Control: affects -1 + src:python-tornado
User: release.debian....@packages.debian.org
Usertags: pu

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

[ Reason ]
This upload intends to fix the vulnerabilities CVE-2024-52804 and
CVE-2023-28370.

CVE-2023-28370 allows a remote unauthenticated attacker to redirect a user to
an arbitrary web site and conduct a phishing attack by having a user access a
specially crafted URL.

CVE-2024-52804 can lead to excessive CPU consumption when parsing
maliciously-crafted cookie headers.
 
[ Impact ]
Users of Debian Bookworm will continue to be vulnerable to the mentioned issues
if the update is not approved.

[ Tests ]
For both issues, tests have been added or adjusted. The tests are run during
build and via autopkgtest and ran successfully.

[ Risks ]
The changes are quite simple. However, regressions are always possible. The
fact that the tests are successful reduce the risk of regressions.

[ Checklist ]
  [x] *all* changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in (old)stable
  [x] the issue is verified as fixed in unstable

[ Changes ]
For CVE-2023-28370, the fix simply leads to a refusal of attempts to redirect
to URLs that could be misinterpreted.

For CVE-2024-52804, a quadratic algorithm, originally copied from Python 3.5,
is replaced with the implementation copied from the Python 3.13 standard
library.

[ Other info ]
All patches contain links to the original reports and commits.

-----BEGIN PGP SIGNATURE-----

iQIzBAEBCgAdFiEEvu1N7VVEpMA+KD3HS80FZ8KW0F0FAmdzRCwACgkQS80FZ8KW
0F2UPhAAsIbmA/9NykDhNg0Pu7ZFkRZK3gIhX58B4vsjMQp6oRAUgYYaINQPsrIj
YtEkjIkkil2be8oBip8zIzAI/FdB5BZ8cUz/BHCUC7wIjznsdMbsL/yHhWvZ6KXe
THXypEr1qPueCWIhcJE7LKuoYekmlRsHS8DzlN/Q9IeqObmHz0OQudPruylBd+Y8
uvqNZ1MLiXNTQGBK6FrjiL2CXxOwt52nSVd1xLHzJgPFPHL6Yytu6rp2iq0HKvnV
T0IoRtOMk2CA2uMx2Wh4fUIbgDRJPZ34TdbJW8Kuq4Rqwq1+v5tmOkRNGGyVpcUg
GMp6FH9JPPgk4nit/zC8l5ZH5vs9WU93G8//B3kfFty2XbbKTK8mGaRnbQe9Fss/
rr5JtGVxLc7ozdnlCcf6rmQhbo+ZkeBNKKgkSR34iHKK4SNgTIE5Juh1Tvd6K0ZU
5HmxEbSX8mATYflyupnFvtLaHJ0piSObsWkRL5jlTwf0BSntjdhBWTWIo9IuWQcY
U2WW/xXnYRr2BPMIAYrVctd6jnjYzpE4zn7cMUaEpUmEqTATAvUo932KMT7ueraj
Ymy7f6nJcpqq6LiQ9FJ8NV3700OwFUKA94juxaq13OW3lkEwpFnEjlRyDV7BrFdL
SiyEQolqoyZvUMl0JTyruDJEPjT1LZx2/xSkqKzfOR7IpVdy1jo=
=qDcm
-----END PGP SIGNATURE-----
diff -Nru python-tornado-6.2.0/debian/changelog 
python-tornado-6.2.0/debian/changelog
--- python-tornado-6.2.0/debian/changelog       2022-11-20 13:24:11.000000000 
+0100
+++ python-tornado-6.2.0/debian/changelog       2024-12-31 01:53:59.000000000 
+0100
@@ -1,3 +1,21 @@
+python-tornado (6.2.0-3+deb12u1) bookworm; urgency=medium
+
+  * Non-maintainer upload by the Debian LTS team.
+  * d/patches/CVE-2024-52804.patch: Fix CVE-2024-52804 (closes: #1088112).
+    - The algorithm used for parsing HTTP cookies in Tornado versions prior to
+      6.4.2 sometimes has quadratic complexity, leading to excessive CPU
+      consumption when parsing maliciously-crafted cookie headers. This
+      parsing occurs in the event loop thread and may block the processing of
+      other requests.
+  * d/patches/CVE-2023-28370-1.patch,
+    d/patches/CVE-2023-28370-2.patch: Fix CVE-2023-28370 (closes: #1036875).
+    - Open redirect vulnerability in Tornado versions 6.3.1 and earlier allows
+      a remote unauthenticated attacker to redirect a user to an arbitrary web
+      site and conduct a phishing attack by having user access a specially
+      crafted URL.
+
+ -- Daniel Leidert <dleid...@debian.org>  Tue, 31 Dec 2024 01:53:59 +0100
+
 python-tornado (6.2.0-3) unstable; urgency=medium
 
   [ Debian Janitor ]
diff -Nru python-tornado-6.2.0/debian/gbp.conf 
python-tornado-6.2.0/debian/gbp.conf
--- python-tornado-6.2.0/debian/gbp.conf        1970-01-01 01:00:00.000000000 
+0100
+++ python-tornado-6.2.0/debian/gbp.conf        2024-12-31 01:53:59.000000000 
+0100
@@ -0,0 +1,4 @@
+[DEFAULT]
+upstream-branch = upstream
+debian-branch = debian/bookworm
+pristine-tar = True
diff -Nru python-tornado-6.2.0/debian/patches/CVE-2023-28370-1.patch 
python-tornado-6.2.0/debian/patches/CVE-2023-28370-1.patch
--- python-tornado-6.2.0/debian/patches/CVE-2023-28370-1.patch  1970-01-01 
01:00:00.000000000 +0100
+++ python-tornado-6.2.0/debian/patches/CVE-2023-28370-1.patch  2024-12-31 
01:53:59.000000000 +0100
@@ -0,0 +1,41 @@
+From: Ben Darnell <b...@bendarnell.com>
+Date: Sat, 13 May 2023 20:58:52 -0400
+Subject: web: Fix an open redirect in StaticFileHandler
+
+Under some configurations the default_filename redirect could be exploited
+to redirect to an attacker-controlled site. This change refuses to redirect
+to URLs that could be misinterpreted.
+
+A test case for the specific vulnerable configuration will follow after the
+patch has been available.
+
+Reviewed-By: Daniel Leidert <dleid...@debian.org>
+Origin: https://github.com/tornadoweb/tornado/pull/3266
+Bug: https://github.com/advisories/GHSA-hj3f-6gcp-jg8j
+Bug-Debian: https://bugs.debian.org/1036875
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2023-28370
+Bug-Freexian-Security: 
https://deb.freexian.com/extended-lts/tracker/CVE-2023-28370
+---
+ tornado/web.py | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/tornado/web.py b/tornado/web.py
+index cd6a81b..05b571e 100644
+--- a/tornado/web.py
++++ b/tornado/web.py
+@@ -2806,6 +2806,15 @@ class StaticFileHandler(RequestHandler):
+             # but there is some prefix to the path that was already
+             # trimmed by the routing
+             if not self.request.path.endswith("/"):
++                if self.request.path.startswith("//"):
++                    # A redirect with two initial slashes is a 
"protocol-relative" URL.
++                    # This means the next path segment is treated as a 
hostname instead
++                    # of a part of the path, making this effectively an open 
redirect.
++                    # Reject paths starting with two slashes to prevent this.
++                    # This is only reachable under certain configurations.
++                    raise HTTPError(
++                        403, "cannot redirect path with two initial slashes"
++                    )
+                 self.redirect(self.request.path + "/", permanent=True)
+                 return None
+             absolute_path = os.path.join(absolute_path, self.default_filename)
diff -Nru python-tornado-6.2.0/debian/patches/CVE-2023-28370-2.patch 
python-tornado-6.2.0/debian/patches/CVE-2023-28370-2.patch
--- python-tornado-6.2.0/debian/patches/CVE-2023-28370-2.patch  1970-01-01 
01:00:00.000000000 +0100
+++ python-tornado-6.2.0/debian/patches/CVE-2023-28370-2.patch  2024-12-31 
01:53:59.000000000 +0100
@@ -0,0 +1,63 @@
+From: Ben Darnell <b...@bendarnell.com>
+Date: Tue, 6 Jun 2023 22:48:05 -0400
+Subject: test: Add test for open redirect fixed in 6.3.2
+
+Reviewed-By: Daniel Leidert <dleid...@debian.org>
+Origin: https://github.com/tornadoweb/tornado/pull/3276
+Bug: https://github.com/advisories/GHSA-hj3f-6gcp-jg8j
+Bug-Debian: https://bugs.debian.org/1036875
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2023-28370
+Bug-Freexian-Security: 
https://deb.freexian.com/extended-lts/tracker/CVE-2023-28370
+---
+ tornado/test/web_test.py | 31 ++++++++++++++++++++++++++++++-
+ 1 file changed, 30 insertions(+), 1 deletion(-)
+
+diff --git a/tornado/test/web_test.py b/tornado/test/web_test.py
+index 396ba6d..7e33033 100644
+--- a/tornado/test/web_test.py
++++ b/tornado/test/web_test.py
+@@ -1426,6 +1426,35 @@ class StaticDefaultFilenameTest(WebTestCase):
+         self.assertTrue(response.headers["Location"].endswith("/static/dir/"))
+ 
+ 
++class StaticDefaultFilenameRootTest(WebTestCase):
++    def get_app_kwargs(self):
++        return dict(
++            static_path=os.path.abspath(relpath("static")),
++            static_handler_args=dict(default_filename="index.html"),
++            static_url_prefix="/",
++        )
++
++    def get_handlers(self):
++        return []
++
++    def get_http_client(self):
++        # simple_httpclient only: curl doesn't let you send a request starting
++        # with two slashes.
++        return SimpleAsyncHTTPClient()
++
++    def test_no_open_redirect(self):
++        # This test verifies that the open redirect that affected some 
configurations
++        # prior to Tornado 6.3.2 is no longer possible. The vulnerability 
required
++        # a static_url_prefix of "/" and a default_filename (any value) to be 
set.
++        # The absolute server-side path to the static directory must also be 
known.
++        with ExpectLog(gen_log, ".*cannot redirect path with two initial 
slashes"):
++            response = self.fetch(
++                f"//evil.com/../{os.path.dirname(__file__)}/static/dir",
++                follow_redirects=False,
++            )
++        self.assertEqual(response.code, 403)
++
++
+ class StaticFileWithPathTest(WebTestCase):
+     def get_app_kwargs(self):
+         return dict(
+@@ -2837,7 +2866,7 @@ class XSRFTest(SimpleHandlerTestCase):
+             body=b"",
+             headers=dict(
+                 {"X-Xsrftoken": self.xsrf_token},  # type: ignore
+-                **self.cookie_headers()
++                **self.cookie_headers(),
+             ),
+         )
+         self.assertEqual(response.code, 200)
diff -Nru python-tornado-6.2.0/debian/patches/CVE-2024-52804.patch 
python-tornado-6.2.0/debian/patches/CVE-2024-52804.patch
--- python-tornado-6.2.0/debian/patches/CVE-2024-52804.patch    1970-01-01 
01:00:00.000000000 +0100
+++ python-tornado-6.2.0/debian/patches/CVE-2024-52804.patch    2024-12-31 
01:53:59.000000000 +0100
@@ -0,0 +1,144 @@
+From: Ben Darnell <b...@bendarnell.com>
+Date: Thu, 21 Nov 2024 14:48:05 -0500
+Subject: httputil: Fix quadratic performance of cookie parsing
+
+Maliciously-crafted cookies can cause Tornado to
+spend an unreasonable amount of CPU time and block
+the event loop.
+
+This change replaces the quadratic algorithm with
+a more efficient one. The implementation is copied
+from the Python 3.13 standard library (the
+previous one was from Python 3.5).
+
+Fixes CVE-2024-52804
+See CVE-2024-7592 for a similar vulnerability in cpython.
+
+Thanks to github.com/kexinoh for the report.
+
+Reviewed-By: Daniel Leidert <dleid...@debian.org>
+Origin: 
https://github.com/tornadoweb/tornado/commit/d5ba4a1695fbf7c6a3e54313262639b198291533.patch
+Bug: 
https://github.com/tornadoweb/tornado/security/advisories/GHSA-8w49-h785-mj3c
+Bug-Debian: https://bugs.debian.org/1088112
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2024-52804
+Bug-Freexian-Security: 
https://deb.freexian.com/extended-lts/tracker/CVE-2024-52804
+---
+ tornado/httputil.py           | 38 ++++++++++-------------------------
+ tornado/test/httputil_test.py | 46 +++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 56 insertions(+), 28 deletions(-)
+
+diff --git a/tornado/httputil.py b/tornado/httputil.py
+index 9c341d4..f74eced 100644
+--- a/tornado/httputil.py
++++ b/tornado/httputil.py
+@@ -1053,15 +1053,20 @@ def qs_to_qsl(qs: Dict[str, List[AnyStr]]) -> 
Iterable[Tuple[str, AnyStr]]:
+             yield (k, v)
+ 
+ 
+-_OctalPatt = re.compile(r"\\[0-3][0-7][0-7]")
+-_QuotePatt = re.compile(r"[\\].")
+-_nulljoin = "".join
++_unquote_sub = re.compile(r"\\(?:([0-3][0-7][0-7])|(.))").sub
++
++
++def _unquote_replace(m: re.Match) -> str:
++    if m[1]:
++        return chr(int(m[1], 8))
++    else:
++        return m[2]
+ 
+ 
+ def _unquote_cookie(s: str) -> str:
+     """Handle double quotes and escaping in cookie values.
+ 
+-    This method is copied verbatim from the Python 3.5 standard
++    This method is copied verbatim from the Python 3.13 standard
+     library (http.cookies._unquote) so we don't have to depend on
+     non-public interfaces.
+     """
+@@ -1082,30 +1087,7 @@ def _unquote_cookie(s: str) -> str:
+     #    \012 --> \n
+     #    \"   --> "
+     #
+-    i = 0
+-    n = len(s)
+-    res = []
+-    while 0 <= i < n:
+-        o_match = _OctalPatt.search(s, i)
+-        q_match = _QuotePatt.search(s, i)
+-        if not o_match and not q_match:  # Neither matched
+-            res.append(s[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(s[i:k])
+-            res.append(s[k + 1])
+-            i = k + 2
+-        else:  # OctalPatt matched
+-            res.append(s[i:j])
+-            res.append(chr(int(s[j + 1 : j + 4], 8)))
+-            i = j + 4
+-    return _nulljoin(res)
++    return _unquote_sub(_unquote_replace, s)
+ 
+ 
+ def parse_cookie(cookie: str) -> Dict[str, str]:
+diff --git a/tornado/test/httputil_test.py b/tornado/test/httputil_test.py
+index 0fad403..25faf66 100644
+--- a/tornado/test/httputil_test.py
++++ b/tornado/test/httputil_test.py
+@@ -519,3 +519,49 @@ class ParseCookieTest(unittest.TestCase):
+         self.assertEqual(
+             parse_cookie("  =  b  ;  ;  =  ;   c  =  ;  "), {"": "b", "c": ""}
+         )
++
++    def test_unquote(self):
++        # Copied from
++        # 
https://github.com/python/cpython/blob/dc7a2b6522ec7af41282bc34f405bee9b306d611/Lib/test/test_http_cookies.py#L62
++        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 = parse_cookie(encoded)
++                self.assertEqual(c["a"], decoded)
++
++    def test_unquote_large(self):
++        # Adapted from
++        # 
https://github.com/python/cpython/blob/dc7a2b6522ec7af41282bc34f405bee9b306d611/Lib/test/test_http_cookies.py#L87
++        # Modified from that test because we handle semicolons differently 
from the stdlib.
++        #
++        # This is a performance regression test: prior to improvements in 
Tornado 6.4.2, this test
++        # would take over a minute with n= 100k. Now it runs in tens of 
milliseconds.
++        n = 100000
++        for encoded in r"\\", r"\134":
++            with self.subTest(encoded):
++                start = time.time()
++                data = 'a="b=' + encoded * n + '"'
++                value = parse_cookie(data)["a"]
++                end = time.time()
++                self.assertEqual(value[:3], "b=\\")
++                self.assertEqual(value[-3:], "\\\\\\")
++                self.assertEqual(len(value), n + 2)
++
++                # Very loose performance check to avoid false positives
++                self.assertLess(end - start, 1, "Test took too long")
diff -Nru python-tornado-6.2.0/debian/patches/series 
python-tornado-6.2.0/debian/patches/series
--- python-tornado-6.2.0/debian/patches/series  2022-11-20 13:24:11.000000000 
+0100
+++ python-tornado-6.2.0/debian/patches/series  2024-12-31 01:53:59.000000000 
+0100
@@ -4,3 +4,6 @@
 0006-Use-local-objects.inv-for-intersphinx-mapping.patch
 0007-Higher-test_gc-timeout.patch
 ignore-py310-deprecation-warnings.patch
+CVE-2024-52804.patch
+CVE-2023-28370-1.patch
+CVE-2023-28370-2.patch

Reply via email to