diff --git a/backport-CVE-2021-3733.patch b/backport-CVE-2021-3733.patch new file mode 100644 index 0000000000000000000000000000000000000000..c31849a98307acf134dae579e1ba192c9e785cba --- /dev/null +++ b/backport-CVE-2021-3733.patch @@ -0,0 +1,41 @@ +From ada14995870abddc277addf57dd690a2af04c2da Mon Sep 17 00:00:00 2001 +From: "Miss Islington (bot)" + <31488909+miss-islington@users.noreply.github.com> +Date: Tue, 4 May 2021 05:46:40 -0700 +Subject: [PATCH] bpo-43075: Fix ReDoS in urllib AbstractBasicAuthHandler + (GH-24391) (#25249) + +Fix Regular Expression Denial of Service (ReDoS) vulnerability in +urllib.request.AbstractBasicAuthHandler. The ReDoS-vulnerable regex +has quadratic worst-case complexity and it allows cause a denial of +service when identifying crafted invalid RFCs. This ReDoS issue is on +the client side and needs remote attackers to control the HTTP server. +(cherry picked from commit 7215d1ae25525c92b026166f9d5cac85fb1defe1) + +Co-authored-by: Yeting Li +--- + Lib/urllib/request.py | 2 +- + .../next/Security/2021-01-31-05-28-14.bpo-43075.DoAXqO.rst | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + create mode 100644 Misc/NEWS.d/next/Security/2021-01-31-05-28-14.bpo-43075.DoAXqO.rst + +diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py +index 4f42919b09eae..16b7e1c50985d 100644 +--- a/Lib/urllib/request.py ++++ b/Lib/urllib/request.py +@@ -946,7 +946,7 @@ class AbstractBasicAuthHandler: + # (single quotes are a violation of the RFC, but appear in the wild) + rx = re.compile('(?:^|,)' # start of the string or ',' + '[ \t]*' # optional whitespaces +- '([^ \t]+)' # scheme like "Basic" ++ '([^ \t,]+)' # scheme like "Basic" + '[ \t]+' # mandatory whitespaces + # realm=xxx + # realm='xxx' +diff --git a/Misc/NEWS.d/next/Security/2021-01-31-05-28-14.bpo-43075.DoAXqO.rst b/Misc/NEWS.d/next/Security/2021-01-31-05-28-14.bpo-43075.DoAXqO.rst +new file mode 100644 +index 0000000000000..1c9f727e965fb +--- /dev/null ++++ b/Misc/NEWS.d/next/Security/2021-01-31-05-28-14.bpo-43075.DoAXqO.rst +@@ -0,0 +1 @@ ++Fix Regular Expression Denial of Service (ReDoS) vulnerability in :class:`urllib.request.AbstractBasicAuthHandler`. The ReDoS-vulnerable regex has quadratic worst-case complexity and it allows cause a denial of service when identifying crafted invalid RFCs. This ReDoS issue is on the client side and needs remote attackers to control the HTTP server. diff --git a/backport-CVE-2021-3737.patch b/backport-CVE-2021-3737.patch new file mode 100644 index 0000000000000000000000000000000000000000..a8bb85ee9cfc9c89627e5e0d192366a3cc7dcad9 --- /dev/null +++ b/backport-CVE-2021-3737.patch @@ -0,0 +1,120 @@ +From 078b146f062d212919d0ba25e34e658a8234aa63 Mon Sep 17 00:00:00 2001 +From: "Miss Islington (bot)" + <31488909+miss-islington@users.noreply.github.com> +Date: Thu, 6 May 2021 10:10:13 -0700 +Subject: [PATCH] bpo-44022: Fix http client infinite line reading (DoS) after + a HTTP 100 Continue (GH-25916) (GH-25934) + +Fixes http.client potential denial of service where it could get stuck reading lines from a malicious server after a 100 Continue response. + +Co-authored-by: Gregory P. Smith +(cherry picked from commit 47895e31b6f626bc6ce47d175fe9d43c1098909d) + +Co-authored-by: Gen Xu +--- + Lib/http/client.py | 38 ++++++++++--------- + Lib/test/test_httplib.py | 10 ++++- + .../2021-05-05-17-37-04.bpo-44022.bS3XJ9.rst | 2 + + 3 files changed, 32 insertions(+), 18 deletions(-) + create mode 100644 Misc/NEWS.d/next/Security/2021-05-05-17-37-04.bpo-44022.bS3XJ9.rst + +diff --git a/Lib/http/client.py b/Lib/http/client.py +index 04cd8f7d84986..b756f607d344e 100644 +--- a/Lib/http/client.py ++++ b/Lib/http/client.py +@@ -204,15 +204,11 @@ def getallmatchingheaders(self, name): + lst.append(line) + return lst + +-def parse_headers(fp, _class=HTTPMessage): +- """Parses only RFC2822 headers from a file pointer. +- +- email Parser wants to see strings rather than bytes. +- But a TextIOWrapper around self.rfile would buffer too many bytes +- from the stream, bytes which we later need to read as bytes. +- So we read the correct bytes here, as bytes, for email Parser +- to parse. ++def _read_headers(fp): ++ """Reads potential header lines into a list from a file pointer. + ++ Length of line is limited by _MAXLINE, and number of ++ headers is limited by _MAXHEADERS. + """ + headers = [] + while True: +@@ -224,6 +220,19 @@ def parse_headers(fp, _class=HTTPMessage): + raise HTTPException("got more than %d headers" % _MAXHEADERS) + if line in (b'\r\n', b'\n', b''): + break ++ return headers ++ ++def parse_headers(fp, _class=HTTPMessage): ++ """Parses only RFC2822 headers from a file pointer. ++ ++ email Parser wants to see strings rather than bytes. ++ But a TextIOWrapper around self.rfile would buffer too many bytes ++ from the stream, bytes which we later need to read as bytes. ++ So we read the correct bytes here, as bytes, for email Parser ++ to parse. ++ ++ """ ++ headers = _read_headers(fp) + hstring = b''.join(headers).decode('iso-8859-1') + return email.parser.Parser(_class=_class).parsestr(hstring) + +@@ -311,15 +320,10 @@ def begin(self): + if status != CONTINUE: + break + # skip the header from the 100 response +- while True: +- skip = self.fp.readline(_MAXLINE + 1) +- if len(skip) > _MAXLINE: +- raise LineTooLong("header line") +- skip = skip.strip() +- if not skip: +- break +- if self.debuglevel > 0: +- print("header:", skip) ++ skipped_headers = _read_headers(self.fp) ++ if self.debuglevel > 0: ++ print("headers:", skipped_headers) ++ del skipped_headers + + self.code = self.status = status + self.reason = reason.strip() +diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py +index 3fa0691d3ad8f..8333aa0eeef6a 100644 +--- a/Lib/test/test_httplib.py ++++ b/Lib/test/test_httplib.py +@@ -998,6 +998,14 @@ def test_overflowing_header_line(self): + resp = client.HTTPResponse(FakeSocket(body)) + self.assertRaises(client.LineTooLong, resp.begin) + ++ def test_overflowing_header_limit_after_100(self): ++ body = ( ++ 'HTTP/1.1 100 OK\r\n' ++ 'r\n' * 32768 ++ ) ++ resp = client.HTTPResponse(FakeSocket(body)) ++ self.assertRaises(client.HTTPException, resp.begin) ++ + def test_overflowing_chunked_line(self): + body = ( + 'HTTP/1.1 200 OK\r\n' +@@ -1402,7 +1410,7 @@ def readline(self, limit): + class OfflineTest(TestCase): + def test_all(self): + # Documented objects defined in the module should be in __all__ +- expected = {"responses"} # White-list documented dict() object ++ expected = {"responses"} # Allowlist documented dict() object + # HTTPMessage, parse_headers(), and the HTTP status code constants are + # intentionally omitted for simplicity + blacklist = {"HTTPMessage", "parse_headers"} +diff --git a/Misc/NEWS.d/next/Security/2021-05-05-17-37-04.bpo-44022.bS3XJ9.rst b/Misc/NEWS.d/next/Security/2021-05-05-17-37-04.bpo-44022.bS3XJ9.rst +new file mode 100644 +index 0000000000000..cf6b63e396155 +--- /dev/null ++++ b/Misc/NEWS.d/next/Security/2021-05-05-17-37-04.bpo-44022.bS3XJ9.rst +@@ -0,0 +1,2 @@ ++mod:`http.client` now avoids infinitely reading potential HTTP headers after a ++``100 Continue`` status response from the server. diff --git a/backport-bpo-44022-Improve-the-regression-test.patch b/backport-bpo-44022-Improve-the-regression-test.patch new file mode 100644 index 0000000000000000000000000000000000000000..886a30e9c47adda7d5cad126d5504c2378c2b9ba --- /dev/null +++ b/backport-bpo-44022-Improve-the-regression-test.patch @@ -0,0 +1,33 @@ +From fee96422e6f0056561cf74fef2012cc066c9db86 Mon Sep 17 00:00:00 2001 +From: "Miss Islington (bot)" + <31488909+miss-islington@users.noreply.github.com> +Date: Wed, 2 Jun 2021 21:23:40 -0700 +Subject: [PATCH] bpo-44022: Improve the regression test. (GH-26503) (GH-26507) + +It wasn't actually detecting the regression due to the +assertion being too lenient. +(cherry picked from commit e60ab843cbb016fb6ff8b4f418641ac05a9b2fcc) + +Co-authored-by: Gregory P. Smith +--- + Lib/test/test_httplib.py | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py +index 8333aa0eeef6a..a65044eea60dc 100644 +--- a/Lib/test/test_httplib.py ++++ b/Lib/test/test_httplib.py +@@ -1004,7 +1004,12 @@ def test_overflowing_header_limit_after_100(self): + 'r\n' * 32768 + ) + resp = client.HTTPResponse(FakeSocket(body)) +- self.assertRaises(client.HTTPException, resp.begin) ++ with self.assertRaises(client.HTTPException) as cm: ++ resp.begin() ++ # We must assert more because other reasonable errors that we ++ # do not want can also be HTTPException derived. ++ self.assertIn('got more than ', str(cm.exception)) ++ self.assertIn('headers', str(cm.exception)) + + def test_overflowing_chunked_line(self): + body = ( diff --git a/python3.spec b/python3.spec index 3c8c1dc4ddf5c1e62c9c2eca10cc9c0b3f4378ee..0586e55aede0e0c51e85940e861c1a41cb063bb1 100644 --- a/python3.spec +++ b/python3.spec @@ -3,7 +3,7 @@ Summary: Interpreter of the Python3 programming language URL: https://www.python.org/ Version: 3.7.9 -Release: 16 +Release: 17 License: Python %global branchversion 3.7 @@ -149,6 +149,9 @@ Patch6039: backport-37169-Rewrite-_PyObject_IsFreed-unit-tests-GH-13.patch Patch6040: backport-44363-Get-test_capi-passing-with-address-sanitiz.patch Patch6041: backport-36253-Remove-use-after-free-reference-in-ctypes-.patch Patch6042: backport-36356-Fix-memory-leak-in-_asynciomodule.c-GH-165.patch +Patch6043: backport-CVE-2021-3733.patch +Patch6044: backport-CVE-2021-3737.patch +Patch6045: backport-bpo-44022-Improve-the-regression-test.patch patch9000: Don-t-override-PYTHONPATH-which-is-already-set.patch @@ -285,6 +288,9 @@ rm Lib/ensurepip/_bundled/*.whl %patch6040 -p1 %patch6041 -p1 %patch6042 -p1 +%patch6043 -p1 +%patch6044 -p1 +%patch6045 -p1 %patch9000 -p1 sed -i "s/generic_os/%{_vendor}/g" Lib/platform.py @@ -887,6 +893,12 @@ export BEP_GTDLIST="$BEP_GTDLIST_TMP" %{_mandir}/*/* %changelog +* Fri Sep 24 2021 shixuantong - 3.7.9-17 +- Type:CVE +- CVE:CVE-2021-3733 CVE-2021-3737 +- SUG:NA +- DESC:fix CVE-2021-3733 CVE-2021-3737 + * Thu Aug 19 2021 hehuazhen - 3.7.9-16 - Type:bugfix - CVE:NA