From 9c3591a4679865104cc98b25c25567875ef41da5 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 7 Apr 2013 11:11:32 +0530 Subject: [PATCH] When extracting zip files do not allow maliciously created zip files to overwrite other files on the system --- src/calibre/utils/localunzip.py | 8 +++++++- src/calibre/utils/zipfile.py | 11 +++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/calibre/utils/localunzip.py b/src/calibre/utils/localunzip.py index 4fd3006076..289b9d46c0 100644 --- a/src/calibre/utils/localunzip.py +++ b/src/calibre/utils/localunzip.py @@ -174,7 +174,13 @@ def _extractall(f, path=None, file_info=None): has_data_descriptors = header.flags & (1 << 3) seekval = header.compressed_size + (16 if has_data_descriptors else 0) found = True - parts = header.filename.split('/') + # Sanitize path changing absolute to relative paths and removing .. and + # . + fname = header.filename.replace(os.sep, '/') + fname = os.path.splitdrive(fname)[1] + parts = [x for x in fname.split('/') if x not in {'', os.path.pardir, os.path.curdir}] + if not parts: + continue if header.uncompressed_size == 0: # Directory f.seek(f.tell()+seekval) diff --git a/src/calibre/utils/zipfile.py b/src/calibre/utils/zipfile.py index 95e556418c..566823b639 100644 --- a/src/calibre/utils/zipfile.py +++ b/src/calibre/utils/zipfile.py @@ -1099,10 +1099,13 @@ class ZipFile: base_target = targetpath # Added by Kovid - # don't include leading "/" from file name if present - fname = member.filename - if fname.startswith('/'): - fname = fname[1:] + # Sanitize path, changing absolute paths to relative paths + # and removing .. and . (changed by Kovid) + fname = member.filename.replace(os.sep, '/') + fname = os.path.splitdrive(fname)[1] + fname = '/'.join(x for x in fname.split('/') if x not in {'', os.path.curdir, os.path.pardir}) + if not fname: + raise BadZipfile('The member %r has an invalid name'%member.filename) targetpath = os.path.normpath(os.path.join(base_target, fname))