From 45f10eb791f19fb7b0e72e92b7046449452191ba Mon Sep 17 00:00:00 2001 From: Charalampos Stratakis Date: Fri, 23 Aug 2024 15:08:45 +0200 Subject: [PATCH] Security fix for CVE-2024-8088 Resolves: RHEL-55959 --- ...22905-sanitize-names-in-zipfile-path.patch | 128 ++++++++++++++++++ python3.11.spec | 10 +- 2 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 00436-cve-2024-8088-gh-122905-sanitize-names-in-zipfile-path.patch diff --git a/00436-cve-2024-8088-gh-122905-sanitize-names-in-zipfile-path.patch b/00436-cve-2024-8088-gh-122905-sanitize-names-in-zipfile-path.patch new file mode 100644 index 0000000..098c8af --- /dev/null +++ b/00436-cve-2024-8088-gh-122905-sanitize-names-in-zipfile-path.patch @@ -0,0 +1,128 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Jason R. Coombs" +Date: Mon, 19 Aug 2024 19:28:20 -0400 +Subject: [PATCH] 00436: [CVE-2024-8088] gh-122905: Sanitize names in + zipfile.Path. + +Co-authored-by: Jason R. Coombs +--- + Lib/test/test_zipfile.py | 17 ++++++ + Lib/zipfile.py | 61 ++++++++++++++++++- + ...-08-11-14-08-04.gh-issue-122905.7tDsxA.rst | 1 + + 3 files changed, 78 insertions(+), 1 deletion(-) + create mode 100644 Misc/NEWS.d/next/Library/2024-08-11-14-08-04.gh-issue-122905.7tDsxA.rst + +diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py +index 4de6f379a4..8bdc7a1b7d 100644 +--- a/Lib/test/test_zipfile.py ++++ b/Lib/test/test_zipfile.py +@@ -3651,6 +3651,23 @@ def test_extract_orig_with_implied_dirs(self, alpharep): + zipfile.Path(zf) + zf.extractall(source_path.parent) + ++ def test_malformed_paths(self): ++ """ ++ Path should handle malformed paths. ++ """ ++ data = io.BytesIO() ++ zf = zipfile.ZipFile(data, "w") ++ zf.writestr("/one-slash.txt", b"content") ++ zf.writestr("//two-slash.txt", b"content") ++ zf.writestr("../parent.txt", b"content") ++ zf.filename = '' ++ root = zipfile.Path(zf) ++ assert list(map(str, root.iterdir())) == [ ++ 'one-slash.txt', ++ 'two-slash.txt', ++ 'parent.txt', ++ ] ++ + + class EncodedMetadataTests(unittest.TestCase): + file_names = ['\u4e00', '\u4e8c', '\u4e09'] # Han 'one', 'two', 'three' +diff --git a/Lib/zipfile.py b/Lib/zipfile.py +index 86829abce4..b7bf9ef7e3 100644 +--- a/Lib/zipfile.py ++++ b/Lib/zipfile.py +@@ -9,6 +9,7 @@ + import itertools + import os + import posixpath ++import re + import shutil + import stat + import struct +@@ -2243,7 +2244,65 @@ def _difference(minuend, subtrahend): + return itertools.filterfalse(set(subtrahend).__contains__, minuend) + + +-class CompleteDirs(ZipFile): ++class SanitizedNames: ++ """ ++ ZipFile mix-in to ensure names are sanitized. ++ """ ++ ++ def namelist(self): ++ return list(map(self._sanitize, super().namelist())) ++ ++ @staticmethod ++ def _sanitize(name): ++ r""" ++ Ensure a relative path with posix separators and no dot names. ++ Modeled after ++ https://github.com/python/cpython/blob/bcc1be39cb1d04ad9fc0bd1b9193d3972835a57c/Lib/zipfile/__init__.py#L1799-L1813 ++ but provides consistent cross-platform behavior. ++ >>> san = SanitizedNames._sanitize ++ >>> san('/foo/bar') ++ 'foo/bar' ++ >>> san('//foo.txt') ++ 'foo.txt' ++ >>> san('foo/.././bar.txt') ++ 'foo/bar.txt' ++ >>> san('foo../.bar.txt') ++ 'foo../.bar.txt' ++ >>> san('\\foo\\bar.txt') ++ 'foo/bar.txt' ++ >>> san('D:\\foo.txt') ++ 'D/foo.txt' ++ >>> san('\\\\server\\share\\file.txt') ++ 'server/share/file.txt' ++ >>> san('\\\\?\\GLOBALROOT\\Volume3') ++ '?/GLOBALROOT/Volume3' ++ >>> san('\\\\.\\PhysicalDrive1\\root') ++ 'PhysicalDrive1/root' ++ Retain any trailing slash. ++ >>> san('abc/') ++ 'abc/' ++ Raises a ValueError if the result is empty. ++ >>> san('../..') ++ Traceback (most recent call last): ++ ... ++ ValueError: Empty filename ++ """ ++ ++ def allowed(part): ++ return part and part not in {'..', '.'} ++ ++ # Remove the drive letter. ++ # Don't use ntpath.splitdrive, because that also strips UNC paths ++ bare = re.sub('^([A-Z]):', r'\1', name, flags=re.IGNORECASE) ++ clean = bare.replace('\\', '/') ++ parts = clean.split('/') ++ joined = '/'.join(filter(allowed, parts)) ++ if not joined: ++ raise ValueError("Empty filename") ++ return joined + '/' * name.endswith('/') ++ ++ ++class CompleteDirs(SanitizedNames, ZipFile): + """ + A ZipFile subclass that ensures that implied directories + are always included in the namelist. +diff --git a/Misc/NEWS.d/next/Library/2024-08-11-14-08-04.gh-issue-122905.7tDsxA.rst b/Misc/NEWS.d/next/Library/2024-08-11-14-08-04.gh-issue-122905.7tDsxA.rst +new file mode 100644 +index 0000000000..1be44c906c +--- /dev/null ++++ b/Misc/NEWS.d/next/Library/2024-08-11-14-08-04.gh-issue-122905.7tDsxA.rst +@@ -0,0 +1 @@ ++:class:`zipfile.Path` objects now sanitize names from the zipfile. diff --git a/python3.11.spec b/python3.11.spec index 035893c..8bffa67 100644 --- a/python3.11.spec +++ b/python3.11.spec @@ -20,7 +20,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 6%{?dist} +Release: 7%{?dist} License: Python @@ -394,6 +394,10 @@ Patch431: 00431-CVE-2024-4032.patch # about newlines. Patch435: 00435-gh-121650-encode-newlines-in-headers-and-verify-headers-are-sound-gh-122233.patch +# 00436 # 1acd6db660ad1124ab7ae449a841608dd9d9062d +# [CVE-2024-8088] gh-122905: Sanitize names in zipfile.Path. +Patch436: 00436-cve-2024-8088-gh-122905-sanitize-names-in-zipfile-path.patch + # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1672,6 +1676,10 @@ CheckPython optimized # ====================================================== %changelog +* Fri Aug 23 2024 Charalampos Stratakis - 3.11.9-7 +- Security fix for CVE-2024-8088 +Resolves: RHEL-55959 + * Thu Aug 15 2024 Charalampos Stratakis - 3.11.9-6 - Security fix for CVE-2024-6923 Resolves: RHEL-53038