From 4e9cb40f148a057457c393133d9b5d4c05d3a6de Mon Sep 17 00:00:00 2001 From: TrellixVulnTeam Date: Fri, 6 Jan 2023 09:35:46 +0000 Subject: [PATCH] Adding tarfile member sanitization to extractall() --- .../export_unity_package_test.py | 84 ++++++++++++++++++- 1 file changed, 80 insertions(+), 4 deletions(-) diff --git a/source/ExportUnityPackage/export_unity_package_test.py b/source/ExportUnityPackage/export_unity_package_test.py index b6a1ca74..a38d9287 100755 --- a/source/ExportUnityPackage/export_unity_package_test.py +++ b/source/ExportUnityPackage/export_unity_package_test.py @@ -2685,7 +2685,26 @@ def test_package_write(self): "7311924048bd457bac6d713576c952da/asset.meta", "7311924048bd457bac6d713576c952da/pathname"], unitypackage_file.getnames()) - unitypackage_file.extractall(self.staging_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) + + + safe_extract(unitypackage_file, self.staging_dir) self.assertTrue(filecmp.cmp( os.path.join(self.assets_dir, "Firebase/Plugins/Firebase.App.dll"), os.path.join(self.staging_dir, @@ -2845,7 +2864,26 @@ def test_package_write_with_includes_and_export(self): "275bd6b96a28470986154b9a995e191c/asset.meta", "275bd6b96a28470986154b9a995e191c/pathname" ], unitypackage_file.getnames()) - unitypackage_file.extractall(self.staging_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) + + + safe_extract(unitypackage_file, self.staging_dir) self.assertTrue( filecmp.cmp( os.path.join(self.assets_dir, @@ -3045,7 +3083,26 @@ def test_package_write_upm(self): "package/Documentation~", "package/Documentation~/index.md", ], unitypackage_file.getnames()) - unitypackage_file.extractall(self.staging_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) + + + safe_extract(unitypackage_file, self.staging_dir) self.assertTrue( filecmp.cmp( @@ -3153,7 +3210,26 @@ def test_package_write_upm_documentation_as_file(self): "package/Documentation~", "package/Documentation~/index.md", ], upm_package_file.getnames()) - upm_package_file.extractall(self.staging_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) + + + safe_extract(upm_package_file, self.staging_dir) self.assertTrue( filecmp.cmp(