From c7572233121f2915cbd370def7bda980ad1ab838 Mon Sep 17 00:00:00 2001 From: TrellixVulnTeam <112716341+TrellixVulnTeam@users.noreply.github.com> Date: Mon, 10 Oct 2022 19:52:30 -0500 Subject: [PATCH] CVE-2007-4559 Patch (#990) # Patching CVE-2007-4559 Hi, we are security researchers from the Advanced Research Center at [Trellix](https://www.trellix.com). We have began a campaign to patch a widespread bug named CVE-2007-4559. CVE-2007-4559 is a 15 year old bug in the Python tarfile package. By using extract() or extractall() on a tarfile object without sanitizing input, a maliciously crafted .tar file could perform a directory path traversal attack. We found at least one unsantized extractall() in your codebase and are providing a patch for you via pull request. The patch essentially checks to see if all tarfile members will be extracted safely and throws an exception otherwise. We encourage you to use this patch or your own solution to secure against CVE-2007-4559. Further technical information about the vulnerability can be found in this [blog](https://www.trellix.com/en-us/about/newsroom/stories/research/tarfile-exploiting-the-world.html). If you have further questions you may contact us through this projects lead researcher [Kasimir Schulz](mailto:kasimir.schulz@trellix.com). --- dpgen/auto_test/lib/RemoteJob.py | 21 ++++++++++++++++++++- dpgen/dispatcher/SSHContext.py | 21 ++++++++++++++++++++- dpgen/remote/RemoteJob.py | 21 ++++++++++++++++++++- 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/dpgen/auto_test/lib/RemoteJob.py b/dpgen/auto_test/lib/RemoteJob.py index d976b4253..e66df1351 100644 --- a/dpgen/auto_test/lib/RemoteJob.py +++ b/dpgen/auto_test/lib/RemoteJob.py @@ -191,7 +191,26 @@ def _get_files(self, cwd = os.getcwd() os.chdir(self.local_root) with tarfile.open(of, "r:gz") as tar: - tar.extractall() + 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(tar) os.chdir(cwd) # cleanup os.remove(to_f) diff --git a/dpgen/dispatcher/SSHContext.py b/dpgen/dispatcher/SSHContext.py index aca7d8368..7f614f31b 100644 --- a/dpgen/dispatcher/SSHContext.py +++ b/dpgen/dispatcher/SSHContext.py @@ -333,7 +333,26 @@ def _get_files(self, cwd = os.getcwd() os.chdir(self.local_root) with tarfile.open(of, "r:gz") as tar: - tar.extractall() + 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(tar) os.chdir(cwd) # cleanup os.remove(to_f) diff --git a/dpgen/remote/RemoteJob.py b/dpgen/remote/RemoteJob.py index 4cdc76e9c..992fb82f4 100644 --- a/dpgen/remote/RemoteJob.py +++ b/dpgen/remote/RemoteJob.py @@ -288,7 +288,26 @@ def _get_files(self, cwd = os.getcwd() os.chdir(self.local_root) with tarfile.open(of, "r:gz") as tar: - tar.extractall() + 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(tar) os.chdir(cwd) # cleanup os.remove(to_f)