]> granicus.if.org Git - python/commitdiff
Fixes Issue #6972: The zipfile module no longer overwrites files outside of
authorGregory P. Smith <greg@krypto.org>
Fri, 1 Feb 2013 19:31:31 +0000 (11:31 -0800)
committerGregory P. Smith <greg@krypto.org>
Fri, 1 Feb 2013 19:31:31 +0000 (11:31 -0800)
its destination path when extracting malicious zip files.

1  2 
Doc/library/zipfile.rst
Lib/test/test_zipfile.py
Lib/zipfile.py
Misc/NEWS

Simple merge
index b0c529fb94af38bc95da2eef290f955fd0e5b034,85cd0742b7f2dc05e497f8c7818becfc0996b0af..81e30368e04c38a99934e21121e8adc9b8aeaf40
@@@ -539,9 -441,86 +533,83 @@@ class TestsWithSourceFile(unittest.Test
          # remove the test file subdirectories
          shutil.rmtree(os.path.join(os.getcwd(), 'ziptest2dir'))
  
 -    def test_writestr_compression(self):
+     def check_file(self, filename, content):
+         self.assertTrue(os.path.isfile(filename))
+         with open(filename, 'rb') as f:
+             self.assertEqual(f.read(), content)
+     def test_extract_hackers_arcnames(self):
+         hacknames = [
+             ('../foo/bar', 'foo/bar'),
+             ('foo/../bar', 'foo/bar'),
+             ('foo/../../bar', 'foo/bar'),
+             ('foo/bar/..', 'foo/bar'),
+             ('./../foo/bar', 'foo/bar'),
+             ('/foo/bar', 'foo/bar'),
+             ('/foo/../bar', 'foo/bar'),
+             ('/foo/../../bar', 'foo/bar'),
+             ('//foo/bar', 'foo/bar'),
+             ('../../foo../../ba..r', 'foo../ba..r'),
+         ]
+         if os.path.sep == '\\':  # Windows.
+             hacknames.extend([
+                 (r'..\foo\bar', 'foo/bar'),
+                 (r'..\/foo\/bar', 'foo/bar'),
+                 (r'foo/\..\/bar', 'foo/bar'),
+                 (r'foo\/../\bar', 'foo/bar'),
+                 (r'C:foo/bar', 'foo/bar'),
+                 (r'C:/foo/bar', 'foo/bar'),
+                 (r'C://foo/bar', 'foo/bar'),
+                 (r'C:\foo\bar', 'foo/bar'),
+                 (r'//conky/mountpoint/foo/bar', 'foo/bar'),
+                 (r'\\conky\mountpoint\foo\bar', 'foo/bar'),
+                 (r'///conky/mountpoint/foo/bar', 'conky/mountpoint/foo/bar'),
+                 (r'\\\conky\mountpoint\foo\bar', 'conky/mountpoint/foo/bar'),
+                 (r'//conky//mountpoint/foo/bar', 'conky/mountpoint/foo/bar'),
+                 (r'\\conky\\mountpoint\foo\bar', 'conky/mountpoint/foo/bar'),
+                 (r'//?/C:/foo/bar', 'foo/bar'),
+                 (r'\\?\C:\foo\bar', 'foo/bar'),
+                 (r'C:/../C:/foo/bar', 'C_/foo/bar'),
+                 (r'a:b\c<d>e|f"g?h*i', 'b/c_d_e_f_g_h_i'),
+             ])
+         for arcname, fixedname in hacknames:
+             content = b'foobar' + arcname.encode()
+             with zipfile.ZipFile(TESTFN2, 'w', zipfile.ZIP_STORED) as zipfp:
+                 zipfp.writestr(arcname, content)
+             targetpath = os.path.join('target', 'subdir', 'subsub')
+             correctfile = os.path.join(targetpath, *fixedname.split('/'))
+             with zipfile.ZipFile(TESTFN2, 'r') as zipfp:
+                 writtenfile = zipfp.extract(arcname, targetpath)
+                 self.assertEqual(writtenfile, correctfile)
+             self.check_file(correctfile, content)
+             shutil.rmtree('target')
+             with zipfile.ZipFile(TESTFN2, 'r') as zipfp:
+                 zipfp.extractall(targetpath)
+             self.check_file(correctfile, content)
+             shutil.rmtree('target')
+             correctfile = os.path.join(os.getcwd(), *fixedname.split('/'))
+             with zipfile.ZipFile(TESTFN2, 'r') as zipfp:
+                 writtenfile = zipfp.extract(arcname)
+                 self.assertEqual(writtenfile, correctfile)
+             self.check_file(correctfile, content)
+             shutil.rmtree(fixedname.split('/')[0])
+             with zipfile.ZipFile(TESTFN2, 'r') as zipfp:
+                 zipfp.extractall()
+             self.check_file(correctfile, content)
+             shutil.rmtree(fixedname.split('/')[0])
+             os.remove(TESTFN2)
 +    def test_writestr_compression_stored(self):
          zipfp = zipfile.ZipFile(TESTFN2, "w")
          zipfp.writestr("a.txt", "hello world", compress_type=zipfile.ZIP_STORED)
 -        if zlib:
 -            zipfp.writestr("b.txt", "hello world", compress_type=zipfile.ZIP_DEFLATED)
 -
          info = zipfp.getinfo('a.txt')
          self.assertEqual(info.compress_type, zipfile.ZIP_STORED)
  
diff --cc Lib/zipfile.py
Simple merge
diff --cc Misc/NEWS
Simple merge