From c74a996dff35ba3a980431d110a81c9449fab04f Mon Sep 17 00:00:00 2001 From: TrellixVulnTeam Date: Fri, 4 Nov 2022 05:30:14 +0000 Subject: [PATCH] Adding tarfile member sanitization to extractall() --- enot/pac_cache/cache.py | 24 +++++++++++++++++++++++- enot/utils/file_utils.py | 21 ++++++++++++++++++++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/enot/pac_cache/cache.py b/enot/pac_cache/cache.py index 91f36ee..a64a3c2 100644 --- a/enot/pac_cache/cache.py +++ b/enot/pac_cache/cache.py @@ -70,7 +70,29 @@ def unpackage(self, package: Package): # TODO move me to package? use current d ensure_empty(unpack_dir) info('Extract ' + enotpack) with tarfile.open(enotpack) as pack: - pack.extractall(unpack_dir) + + import os + + 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(pack, unpack_dir) package.path = unpack_dir # update path pointer copy_file(enotpack, join(unpack_dir, package.name + '.ep')) diff --git a/enot/utils/file_utils.py b/enot/utils/file_utils.py index e48fac9..37d9fbb 100644 --- a/enot/utils/file_utils.py +++ b/enot/utils/file_utils.py @@ -34,7 +34,26 @@ def tar(path: str, dirs: list, dst: str): def untar(path: str, dst: str): with tarfile.open(path, 'r') as archive: - archive.extractall(dst) + 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(archive, dst) # TODO catch read errors