diff -Nru click-0.4.21.1ubuntu0.1/click/install.py click-0.4.21.1ubuntu0.2/click/install.py --- click-0.4.21.1ubuntu0.1/click/install.py 2015-10-15 08:12:44.000000000 +0000 +++ click-0.4.21.1ubuntu0.2/click/install.py 2015-10-15 15:01:09.000000000 +0000 @@ -234,6 +234,16 @@ 'with system architecture "%s"' % (architecture, dpkg_architecture)) + # This isn't ideally quick, since it has to decompress the data + # part of the package, but dpkg's path filtering code assumes + # that all paths start with "./" so we must check it before + # passing the package to dpkg. + for data_name in package.data: + if data_name != "." and not data_name.startswith("./"): + raise ClickInstallerAuditError( + 'File name "%s" in package does not start with "./"' % + data_name) + if slow: temp_dir = tempfile.mkdtemp(prefix="click") try: @@ -342,7 +352,6 @@ "--instdir", inst_dir, "--admindir", os.path.join(inst_dir, ".click"), "--path-exclude", "*/.click/*", - "--path-exclude", ".click/*", "--log", os.path.join(root_click, "log"), "--no-triggers", "--install", path, diff -Nru click-0.4.21.1ubuntu0.1/click/tests/test_install.py click-0.4.21.1ubuntu0.2/click/tests/test_install.py --- click-0.4.21.1ubuntu0.1/click/tests/test_install.py 2014-04-08 09:41:46.000000000 +0000 +++ click-0.4.21.1ubuntu0.2/click/tests/test_install.py 2015-10-15 15:17:38.000000000 +0000 @@ -23,19 +23,24 @@ ] -from contextlib import contextmanager +from contextlib import ( + closing, + contextmanager, + ) import hashlib import json import os import shutil import stat import subprocess +import tarfile from unittest import skipUnless from debian.deb822 import Deb822 from gi.repository import Click +from click.arfile import ArFile from click.build import ClickBuilder from click.install import ( ClickInstaller, @@ -44,6 +49,7 @@ ) from click.preinst import static_preinst from click.tests.helpers import TestCase, mkfile, mock, touch +from click.versions import spec_version @contextmanager @@ -92,6 +98,7 @@ script.write(contents) Click.ensuredir(data_dir) for name, path in data_files.items(): + Click.ensuredir(os.path.dirname(os.path.join(data_dir, name))) if path is None: touch(os.path.join(data_dir, name)) elif os.path.isdir(path): @@ -300,6 +307,46 @@ ]) self.assertEqual(("test-package", "1.0"), installer.audit(path)) + def test_audit_missing_dot_slash(self): + # Manually construct a package with data paths that do not start + # with "./", which could be used to bypass path filtering. + with self.run_in_subprocess( + "click_get_frameworks_dir") as (enter, preloads): + enter() + path = self.make_fake_package( + control_fields={"Click-Version": "0.2"}, + manifest={ + "name": "test-package", + "version": "1.0", + "framework": "ubuntu-sdk-13.10", + }, + control_scripts={"preinst": static_preinst}, + data_files={".click/tmp.ci/manifest": None}) + # Repack without the leading "./". + data_dir = os.path.join(self.temp_dir, "fake-package") + data_tar_path = os.path.join(self.temp_dir, "data.tar.gz") + control_tar_path = os.path.join(self.temp_dir, "control.tar.gz") + package_path = '%s.click' % data_dir + with closing(tarfile.TarFile.open( + name=data_tar_path, mode="w:gz", format=tarfile.GNU_FORMAT + )) as data_tar: + data_tar.add( + os.path.join(data_dir, ".click"), arcname=".click") + with ArFile(name=package_path, mode="w") as package: + package.add_magic() + package.add_data("debian-binary", b"2.0\n") + package.add_data( + "_click-binary", ("%s\n" % spec_version).encode("UTF-8")) + package.add_file("control.tar.gz", control_tar_path) + package.add_file("data.tar.gz", data_tar_path) + self._setup_frameworks(preloads, frameworks=["ubuntu-sdk-13.10"]) + with mock_quiet_subprocess_call(): + installer = ClickInstaller(self.db) + self.assertRaisesRegex( + ClickInstallerAuditError, + 'File name ".click" in package does not start with "./"', + installer.audit, path) + def test_audit_broken_md5sums(self): with self.run_in_subprocess( "click_get_frameworks_dir") as (enter, preloads): diff -Nru click-0.4.21.1ubuntu0.1/debian/changelog click-0.4.21.1ubuntu0.2/debian/changelog --- click-0.4.21.1ubuntu0.1/debian/changelog 2015-10-15 08:16:49.000000000 +0000 +++ click-0.4.21.1ubuntu0.2/debian/changelog 2015-10-15 15:06:10.000000000 +0000 @@ -1,13 +1,13 @@ -click (0.4.21.1ubuntu0.1) trusty-security; urgency=medium +click (0.4.21.1ubuntu0.2) trusty-security; urgency=medium - * SECURITY UPDATE: fix privilege escalation via crafted manifest that - specifies alternate security policy - - click/install.py: perform proper input sanitization and exclude - installing files into the toplevel .click directory. Patch thanks to - Colin Watson + * SECURITY UPDATE: fix privilege escalation via crafted data.tar.gz that + can be used to install alternate security policy than what is defined + - click/install.py: Forbid installing packages with data tarball members + whose names do not start with "./". Based on patch from Colin Watson. - CVE-2015-XXXX + - LP: #1506467 - -- Jamie Strandboge Thu, 15 Oct 2015 03:12:56 -0500 + -- Jamie Strandboge Thu, 15 Oct 2015 10:05:35 -0500 click (0.4.21.1) trusty; urgency=medium