From b906a859f349aedcce66e138bfe62394f04e1cbb Mon Sep 17 00:00:00 2001 From: Abhilash Raj Date: Tue, 16 Jul 2019 08:05:19 -0700 Subject: [PATCH 1/3] bpo-37461: Fix infinite loop in parsing of specially crafted email headers. Some crafted email header would cause the get_parameter method to run in an infinite loop causing a DoS attack surface when parsing those headers. This patch fixes that by making sure the DQUOTE character is handled to prevent going into an infinite loop. --- Lib/email/_header_value_parser.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index aefc457f678165e..ff6e980cc4a7ae5 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -2494,7 +2494,10 @@ def get_parameter(value): # Treat the rest of value as bare quoted string content. v = Value() while value: - if value[0] in WSP: + if value[0] == '"': + token = ValueTerminal('"', 'DQUOTE') + value = value[1:] + elif value[0] in WSP: token, value = get_fws(value) else: token, value = get_qcontent(value) From 23a1fbc1d7ef5fb4d19977a13787f6bb87635cda Mon Sep 17 00:00:00 2001 From: Abhilash Raj Date: Tue, 16 Jul 2019 08:18:58 -0700 Subject: [PATCH 2/3] Add test and NEWS entry. --- Lib/test/test_email/test__header_value_parser.py | 7 +++++++ .../next/Security/2019-07-16-08-11-00.bpo-37461.1Ahz7O.rst | 2 ++ 2 files changed, 9 insertions(+) create mode 100644 Misc/NEWS.d/next/Security/2019-07-16-08-11-00.bpo-37461.1Ahz7O.rst diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py index c4e1a9f99495a49..533a1cbb3362e68 100644 --- a/Lib/test/test_email/test__header_value_parser.py +++ b/Lib/test/test_email/test__header_value_parser.py @@ -2710,6 +2710,13 @@ def mime_parameters_as_value(self, # Defects are apparent missing *0*, and two 'out of sequence'. [errors.InvalidHeaderDefect]*3), + # bpo-37461: Check that we don't go into an infinite loop. + 'extra_dquote': ( + 'r*="\'a\'\\"""', + ' r="\\""', + 'r*=\'a\'"', + [('r', '"')], + [errors.InvalidHeaderDefect]*2), } @parameterize diff --git a/Misc/NEWS.d/next/Security/2019-07-16-08-11-00.bpo-37461.1Ahz7O.rst b/Misc/NEWS.d/next/Security/2019-07-16-08-11-00.bpo-37461.1Ahz7O.rst new file mode 100644 index 000000000000000..4bfd350c0b404eb --- /dev/null +++ b/Misc/NEWS.d/next/Security/2019-07-16-08-11-00.bpo-37461.1Ahz7O.rst @@ -0,0 +1,2 @@ +Fix an inifite loop when parsing specially crafted email headers. Patch by +Abhilash Raj. From cc4ed701d9f647485ca0452cc17affbd1030fde0 Mon Sep 17 00:00:00 2001 From: Abhilash Raj Date: Wed, 17 Jul 2019 06:32:36 -0700 Subject: [PATCH 3/3] Fix the test to invoke the right infinite loop. --- Lib/email/_header_value_parser.py | 6 +++--- Lib/test/test_email/test__header_value_parser.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index ff6e980cc4a7ae5..43a1ef874751584 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -2494,11 +2494,11 @@ def get_parameter(value): # Treat the rest of value as bare quoted string content. v = Value() while value: - if value[0] == '"': + if value[0] in WSP: + token, value = get_fws(value) + elif value[0] == '"': token = ValueTerminal('"', 'DQUOTE') value = value[1:] - elif value[0] in WSP: - token, value = get_fws(value) else: token, value = get_qcontent(value) v.append(token) diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py index 533a1cbb3362e68..a83915d6d059cf0 100644 --- a/Lib/test/test_email/test__header_value_parser.py +++ b/Lib/test/test_email/test__header_value_parser.py @@ -2712,7 +2712,7 @@ def mime_parameters_as_value(self, # bpo-37461: Check that we don't go into an infinite loop. 'extra_dquote': ( - 'r*="\'a\'\\"""', + 'r*="\'a\'\\"', ' r="\\""', 'r*=\'a\'"', [('r', '"')],