1
0
mirror of https://github.com/ARM-software/devlib.git synced 2025-01-31 02:00:45 +00:00

Mitigate CVE-2007-4995

Prevent potential directory path traversal attacks (see
https://www.trellix.com/en-us/about/newsroom/stories/research/tarfile-exploiting-the-world.html)
This commit is contained in:
setrofim 2022-11-18 09:14:12 +00:00 committed by Marc Bonnici
parent 678822f9e4
commit cc3498d315
4 changed files with 29 additions and 5 deletions

View File

@ -22,7 +22,7 @@ import tempfile
from devlib.module import FlashModule from devlib.module import FlashModule
from devlib.exception import HostError from devlib.exception import HostError
from devlib.utils.android import fastboot_flash_partition, fastboot_command from devlib.utils.android import fastboot_flash_partition, fastboot_command
from devlib.utils.misc import merge_dicts from devlib.utils.misc import merge_dicts, safe_extract
class FastbootFlashModule(FlashModule): class FastbootFlashModule(FlashModule):
@ -86,7 +86,7 @@ class FastbootFlashModule(FlashModule):
self._validate_image_bundle(image_bundle) self._validate_image_bundle(image_bundle)
extract_dir = tempfile.mkdtemp() extract_dir = tempfile.mkdtemp()
with tarfile.open(image_bundle) as tar: with tarfile.open(image_bundle) as tar:
tar.extractall(path=extract_dir) safe_extract(tar, path=extract_dir)
files = [tf.name for tf in tar.getmembers()] files = [tf.name for tf in tar.getmembers()]
if self.partitions_file_name not in files: if self.partitions_file_name not in files:
extract_dir = os.path.join(extract_dir, files[0]) extract_dir = os.path.join(extract_dir, files[0])

View File

@ -21,6 +21,7 @@ from subprocess import CalledProcessError
from devlib.module import HardRestModule, BootModule, FlashModule from devlib.module import HardRestModule, BootModule, FlashModule
from devlib.exception import TargetError, TargetStableError, HostError from devlib.exception import TargetError, TargetStableError, HostError
from devlib.utils.misc import safe_extract
from devlib.utils.serial_port import open_serial_connection, pulse_dtr, write_characters from devlib.utils.serial_port import open_serial_connection, pulse_dtr, write_characters
from devlib.utils.uefi import UefiMenu, UefiConfig from devlib.utils.uefi import UefiMenu, UefiConfig
from devlib.utils.uboot import UbootMenu from devlib.utils.uboot import UbootMenu
@ -354,7 +355,7 @@ class VersatileExpressFlashModule(FlashModule):
validate_image_bundle(bundle) validate_image_bundle(bundle)
self.logger.debug('Extracting {} into {}...'.format(bundle, self.vemsd_mount)) self.logger.debug('Extracting {} into {}...'.format(bundle, self.vemsd_mount))
with tarfile.open(bundle) as tar: with tarfile.open(bundle) as tar:
tar.extractall(self.vemsd_mount) safe_extract(tar, self.vemsd_mount)
def _overlay_images(self, images): def _overlay_images(self, images):
for dest, src in images.items(): for dest, src in images.items():

View File

@ -61,7 +61,7 @@ from devlib.utils.misc import memoized, isiterable, convert_new_lines, groupby_v
from devlib.utils.misc import commonprefix, merge_lists from devlib.utils.misc import commonprefix, merge_lists
from devlib.utils.misc import ABI_MAP, get_cpu_name, ranges_to_list from devlib.utils.misc import ABI_MAP, get_cpu_name, ranges_to_list
from devlib.utils.misc import batch_contextmanager, tls_property, _BoundTLSProperty, nullcontext from devlib.utils.misc import batch_contextmanager, tls_property, _BoundTLSProperty, nullcontext
from devlib.utils.misc import strip_bash_colors from devlib.utils.misc import strip_bash_colors, safe_extract
from devlib.utils.types import integer, boolean, bitmask, identifier, caseless_string, bytes_regex from devlib.utils.types import integer, boolean, bitmask, identifier, caseless_string, bytes_regex
import devlib.utils.asyn as asyn import devlib.utils.asyn as asyn
@ -827,7 +827,7 @@ class Target(object):
await self.pull.asyn(tar_file_name, tmpfile) await self.pull.asyn(tar_file_name, tmpfile)
# Decompress # Decompress
with tarfile.open(tmpfile, 'r') as f: with tarfile.open(tmpfile, 'r') as f:
f.extractall(outdir) safe_extract(f, outdir)
os.remove(tmpfile) os.remove(tmpfile)
# execution # execution

View File

@ -991,3 +991,26 @@ def groupby_value(dct):
tuple(map(itemgetter(0), _items)): v tuple(map(itemgetter(0), _items)): v
for v, _items in groupby(items, key=key) for v, _items in groupby(items, key=key)
} }
def safe_extract(tar, path=".", members=None, *, numeric_owner=False):
"""
A wrapper around TarFile.extract all to mitigate CVE-2007-4995
(see https://www.trellix.com/en-us/about/newsroom/stories/research/tarfile-exploiting-the-world.html)
"""
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)
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