From e50a3a213ed5f5296deeaefe9ec0699010545157 Mon Sep 17 00:00:00 2001 From: TrellixVulnTeam Date: Sun, 30 Oct 2022 23:44:48 +0000 Subject: [PATCH 1/4] Adding tarfile member sanitization to extractall() --- winbuild/build_prepare.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/winbuild/build_prepare.py b/winbuild/build_prepare.py index b4b15cc1ef0..0e585f79652 100644 --- a/winbuild/build_prepare.py +++ b/winbuild/build_prepare.py @@ -474,7 +474,26 @@ def extract_dep(url, filename): zf.extractall(sources_dir) elif filename.endswith(".tar.gz") or filename.endswith(".tgz"): with tarfile.open(file, "r:gz") as tgz: - tgz.extractall(sources_dir) + def is_within_directory(directory, target): + + abs_directory = os.path.abspath(directory) + abs_target = os.path.abspath(target) + + prefix = os.path.commonprefix([abs_directory, abs_target]) + + return prefix == abs_directory + + def safe_extract(tar, path=".", members=None, *, numeric_owner=False): + + for member in tar.getmembers(): + member_path = os.path.join(path, member.name) + if not is_within_directory(path, member_path): + raise Exception("Attempted Path Traversal in Tar File") + + tar.extractall(path, members, numeric_owner=numeric_owner) + + + safe_extract(tgz, sources_dir) else: raise RuntimeError("Unknown archive type: " + filename) From 74c60b47a89502adec658316b06cd0043046d36b Mon Sep 17 00:00:00 2001 From: nulano Date: Sun, 30 Oct 2022 23:45:49 +0000 Subject: [PATCH 2/4] simplify patch, also check zipfile --- winbuild/build_prepare.py | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/winbuild/build_prepare.py b/winbuild/build_prepare.py index 0e585f79652..3cd841484f4 100644 --- a/winbuild/build_prepare.py +++ b/winbuild/build_prepare.py @@ -469,31 +469,23 @@ def extract_dep(url, filename): raise RuntimeError(ex) print("Extracting " + filename) + sources_dir_abs = os.path.abspath(sources_dir) if filename.endswith(".zip"): with zipfile.ZipFile(file) as zf: + for member in zf.namelist(): + member_abspath = os.path.abspath(os.path.join(sources_dir, member)) + member_prefix = os.path.commonprefix([sources_dir_abs, member_abspath]) + if sources_dir_abs != member_prefix: + raise RuntimeError("Attempted Path Traversal in Zip File") zf.extractall(sources_dir) elif filename.endswith(".tar.gz") or filename.endswith(".tgz"): with tarfile.open(file, "r:gz") as tgz: - def is_within_directory(directory, target): - - abs_directory = os.path.abspath(directory) - abs_target = os.path.abspath(target) - - prefix = os.path.commonprefix([abs_directory, abs_target]) - - return prefix == abs_directory - - def safe_extract(tar, path=".", members=None, *, numeric_owner=False): - - for member in tar.getmembers(): - member_path = os.path.join(path, member.name) - if not is_within_directory(path, member_path): - raise Exception("Attempted Path Traversal in Tar File") - - tar.extractall(path, members, numeric_owner=numeric_owner) - - - safe_extract(tgz, sources_dir) + for member in tgz.getmembers(): + member_abspath = os.path.abspath(os.path.join(sources_dir, member.name)) + member_prefix = os.path.commonprefix([sources_dir_abs, member_abspath]) + if sources_dir_abs != member_prefix: + raise RuntimeError("Attempted Path Traversal in Tar File") + tgz.extractall(sources_dir) else: raise RuntimeError("Unknown archive type: " + filename) From c10c6bf8940c2a1bbbc1d01575489cb85e612a12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ondrej=20Baranovi=C4=8D?= Date: Thu, 3 Nov 2022 20:23:59 +0100 Subject: [PATCH 3/4] use os.path.commonpath instead of os.path.commonprefix Co-authored-by: Andrew Murray <3112309+radarhere@users.noreply.github.com> --- winbuild/build_prepare.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/winbuild/build_prepare.py b/winbuild/build_prepare.py index 3cd841484f4..14f8d7ba0f9 100644 --- a/winbuild/build_prepare.py +++ b/winbuild/build_prepare.py @@ -474,7 +474,7 @@ def extract_dep(url, filename): with zipfile.ZipFile(file) as zf: for member in zf.namelist(): member_abspath = os.path.abspath(os.path.join(sources_dir, member)) - member_prefix = os.path.commonprefix([sources_dir_abs, member_abspath]) + member_prefix = os.path.commonpath([sources_dir_abs, member_abspath]) if sources_dir_abs != member_prefix: raise RuntimeError("Attempted Path Traversal in Zip File") zf.extractall(sources_dir) @@ -482,7 +482,7 @@ def extract_dep(url, filename): with tarfile.open(file, "r:gz") as tgz: for member in tgz.getmembers(): member_abspath = os.path.abspath(os.path.join(sources_dir, member.name)) - member_prefix = os.path.commonprefix([sources_dir_abs, member_abspath]) + member_prefix = os.path.commonpath([sources_dir_abs, member_abspath]) if sources_dir_abs != member_prefix: raise RuntimeError("Attempted Path Traversal in Tar File") tgz.extractall(sources_dir) From 8947cbf4d113b112660b15db23fe84f94e128788 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ondrej=20Baranovi=C4=8D?= Date: Fri, 4 Nov 2022 07:31:00 +0100 Subject: [PATCH 4/4] simplify code Co-authored-by: Andrew Murray <3112309+radarhere@users.noreply.github.com> --- winbuild/build_prepare.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/winbuild/build_prepare.py b/winbuild/build_prepare.py index 14f8d7ba0f9..872e74a20b4 100644 --- a/winbuild/build_prepare.py +++ b/winbuild/build_prepare.py @@ -480,8 +480,8 @@ def extract_dep(url, filename): zf.extractall(sources_dir) elif filename.endswith(".tar.gz") or filename.endswith(".tgz"): with tarfile.open(file, "r:gz") as tgz: - for member in tgz.getmembers(): - member_abspath = os.path.abspath(os.path.join(sources_dir, member.name)) + for member in tgz.getnames(): + member_abspath = os.path.abspath(os.path.join(sources_dir, member)) member_prefix = os.path.commonpath([sources_dir_abs, member_abspath]) if sources_dir_abs != member_prefix: raise RuntimeError("Attempted Path Traversal in Tar File")