def test_tar_path_traversal_attack(self): # Test for vulnerability to path-traversal attacks. with tempfile.TemporaryDirectory() as tmpdir: tmpdir = pathlib.Path(tmpdir) dest = tmpdir / "dest" dest.mkdir() for link_dest in ("../nonexistant", "/nonexistant"): tar = tmpdir / "symlink-path-traversal.tgz" filename = tmpdir / "link" filename.symlink_to(link_dest) with utils.cd(tmpdir): with tarfile.open(tar, mode="w:gz") as tf: tf.add("link") with self.assertRaises(ValueError): utils.untar(tar, dest) rm_f(filename) rm_f(tar) for name in ("../nonexistant", "/nonexistant"): tar = tmpdir / "path-traversal.tgz" filename = tmpdir / "test-thing" with open(filename, "w") as f: print("blah", file=f) with utils.cd(tmpdir): with tarfile.open(tar, mode="w:gz") as tf: def filt(info): info.name = name # path the file will be extracted to return info tf.add("test-thing", filter=filt) with self.assertRaises(ValueError): utils.untar(tar, dest) rm_f(filename) rm_f(tar)
def test_bad_tar_members(self): # Pretend we downloaded a tarball containing a FIFO or device file. # There is no reasonable use for these types of files in stdpopsim, # so their presence likely indicates a maliciously crafted tarball. # Creating a character or block special device file requires root # privileges, so we instead modify the ``type`` field of each file # in the tar. with tempfile.TemporaryDirectory() as tmpdir: tmpdir = pathlib.Path(tmpdir) dest = tmpdir / "dest" dest.mkdir() for filename, type_ in [ ("fifo", tarfile.FIFOTYPE), ("char-device", tarfile.CHRTYPE), ("block-device", tarfile.BLKTYPE), ]: tar = tmpdir / "irregular-type.tgz" filename = tmpdir / "irregular" with open(filename, "w") as f: print("blah", file=f) with utils.cd(tmpdir): with tarfile.open(tar, mode="w:gz") as tf: def filt(info): info.type = type_ # lie about the type return info tf.add("irregular", filter=filt) with self.assertRaises(ValueError): utils.untar(tar, dest) rm_f(filename) rm_f(tar)
def test_untar(self): with tempfile.TemporaryDirectory() as tmpdir: tmpdir = pathlib.Path(tmpdir) test_files = ["foo", "bar", "baz"] sha_list = [] for name in test_files: filename = tmpdir / name with open(filename, "wb") as f: f.write(name.encode()) # Record checksums for later. sha_list.append(utils.sha256(filename)) tar = tmpdir / "test.tgz" with utils.cd(tmpdir): with tarfile.open(tar, mode="w:gz") as tf: for name in test_files: tf.add(name) dest = tmpdir / "dest" dest.mkdir() utils.untar(tar, dest) for name, sha in zip(test_files, sha_list): filename = dest / name self.assertTrue(filename.exists()) # Check that extracted files have the same checksums as # the files we put in the tar. self.assertEqual(utils.sha256(filename), sha)