Hello community, here is the log from the commit of package bzr for openSUSE:Factory checked in at 2018-05-17 18:05:40 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/bzr (Old) and /work/SRC/openSUSE:Factory/.bzr.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "bzr" Thu May 17 18:05:40 2018 rev:43 rq:610039 version:2.7.0 Changes: -------- --- /work/SRC/openSUSE:Factory/bzr/bzr.changes 2018-05-15 10:34:27.453862045 +0200 +++ /work/SRC/openSUSE:Factory/.bzr.new/bzr.changes 2018-05-17 18:06:09.610252977 +0200 @@ -1,0 +2,6 @@ +Thu May 17 09:54:54 UTC 2018 - bwiedem...@suse.com + +- Add bzr-2.7.0-ssh_hostnames-lp1710979 to avoid code execution + (boo#1058214, CVE-2017-14176) + +------------------------------------------------------------------- New: ---- bzr-2.7.0-ssh_hostnames-lp1710979 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ bzr.spec ++++++ --- /var/tmp/diff_new_pack.lU51ik/_old 2018-05-17 18:06:10.250229572 +0200 +++ /var/tmp/diff_new_pack.lU51ik/_new 2018-05-17 18:06:10.250229572 +0200 @@ -29,6 +29,8 @@ Patch0: bzr-doc-timestamp.patch # FIX-UPSTREAM-PATCH: fix for python 2.7.13 and later (boo#1020047) Patch1: python-2_7_13.patch +# FIX-UPSTREAM-PATCH: avoid code execution (boo#1020047) +Patch2: bzr-2.7.0-ssh_hostnames-lp1710979 BuildRequires: fdupes BuildRequires: python-Cython BuildRequires: python-devel @@ -59,6 +61,7 @@ %setup -q %patch0 -p1 %patch1 -p0 +%patch2 -p1 sed -i "s|\"share/locale\"|\"locale\"|" setup.py # Fix the locale installation path %build ++++++ bzr-2.7.0-ssh_hostnames-lp1710979 ++++++ Description: Refuse to connect to ssh hostnames starting with a dash. Fixes LP:1710979 Author: Jelmer Vernooij <jel...@jelmer.uk> Origin: commit, Revision ID: jel...@jelmer.uk-20170819145828-qk2p7qlg5j2fbsiz * Security fix: hostnames starting with a dash in bzr+ssh URLs are now filtered out when using a subprocess SSH client. . Thanks to Augie Fackler for reporting. (Jelmer Vernooij, #1710979, boo#1058214) === modified file 'bzrlib/tests/test_ssh_transport.py' --- bzrlib/tests/test_ssh_transport.py | 38 ++++++++++++++++++++++++++++++++++++- bzrlib/transport/ssh.py | 16 +++++++++++++-- 2 files changed, 51 insertions(+), 3 deletions(-) Index: b/bzrlib/tests/test_ssh_transport.py =================================================================== --- a/bzrlib/tests/test_ssh_transport.py +++ b/bzrlib/tests/test_ssh_transport.py @@ -22,6 +22,7 @@ from bzrlib.transport.ssh import ( SSHCorpSubprocessVendor, LSHSubprocessVendor, SSHVendorManager, + StrangeHostname, ) @@ -161,6 +162,19 @@ class SSHVendorManagerTests(TestCase): class SubprocessVendorsTests(TestCase): + def test_openssh_command_tricked(self): + vendor = OpenSSHSubprocessVendor() + self.assertEqual( + vendor._get_vendor_specific_argv( + "user", "-oProxyCommand=blah", 100, command=["bzr"]), + ["ssh", "-oForwardX11=no", "-oForwardAgent=no", + "-oClearAllForwardings=yes", + "-oNoHostAuthenticationForLocalhost=yes", + "-p", "100", + "-l", "user", + "--", + "-oProxyCommand=blah", "bzr"]) + def test_openssh_command_arguments(self): vendor = OpenSSHSubprocessVendor() self.assertEqual( @@ -171,6 +185,7 @@ class SubprocessVendorsTests(TestCase): "-oNoHostAuthenticationForLocalhost=yes", "-p", "100", "-l", "user", + "--", "host", "bzr"] ) @@ -184,9 +199,16 @@ class SubprocessVendorsTests(TestCase): "-oNoHostAuthenticationForLocalhost=yes", "-p", "100", "-l", "user", - "-s", "host", "sftp"] + "-s", "--", "host", "sftp"] ) + def test_openssh_command_tricked(self): + vendor = SSHCorpSubprocessVendor() + self.assertRaises( + StrangeHostname, + vendor._get_vendor_specific_argv, + "user", "-oProxyCommand=host", 100, command=["bzr"]) + def test_sshcorp_command_arguments(self): vendor = SSHCorpSubprocessVendor() self.assertEqual( @@ -209,6 +231,13 @@ class SubprocessVendorsTests(TestCase): "-s", "sftp", "host"] ) + def test_lsh_command_tricked(self): + vendor = LSHSubprocessVendor() + self.assertRaises( + StrangeHostname, + vendor._get_vendor_specific_argv, + "user", "-oProxyCommand=host", 100, command=["bzr"]) + def test_lsh_command_arguments(self): vendor = LSHSubprocessVendor() self.assertEqual( @@ -231,6 +260,13 @@ class SubprocessVendorsTests(TestCase): "--subsystem", "sftp", "host"] ) + def test_plink_command_tricked(self): + vendor = PLinkSubprocessVendor() + self.assertRaises( + StrangeHostname, + vendor._get_vendor_specific_argv, + "user", "-oProxyCommand=host", 100, command=["bzr"]) + def test_plink_command_arguments(self): vendor = PLinkSubprocessVendor() self.assertEqual( Index: b/bzrlib/transport/ssh.py =================================================================== --- a/bzrlib/transport/ssh.py +++ b/bzrlib/transport/ssh.py @@ -46,6 +46,10 @@ else: from paramiko.sftp_client import SFTPClient +class StrangeHostname(errors.BzrError): + _fmt = "Refusing to connect to strange SSH hostname %(hostname)s" + + SYSTEM_HOSTKEYS = {} BZR_HOSTKEYS = {} @@ -360,6 +364,11 @@ class SubprocessVendor(SSHVendor): # tests, but beware of using PIPE which may hang due to not being read. _stderr_target = None + @staticmethod + def _check_hostname(arg): + if arg.startswith('-'): + raise StrangeHostname(hostname=arg) + def _connect(self, argv): # Attempt to make a socketpair to use as stdin/stdout for the SSH # subprocess. We prefer sockets to pipes because they support @@ -424,9 +433,9 @@ class OpenSSHSubprocessVendor(Subprocess if username is not None: args.extend(['-l', username]) if subsystem is not None: - args.extend(['-s', host, subsystem]) + args.extend(['-s', '--', host, subsystem]) else: - args.extend([host] + command) + args.extend(['--', host] + command) return args register_ssh_vendor('openssh', OpenSSHSubprocessVendor()) @@ -439,6 +448,7 @@ class SSHCorpSubprocessVendor(Subprocess def _get_vendor_specific_argv(self, username, host, port, subsystem=None, command=None): + self._check_hostname(host) args = [self.executable_path, '-x'] if port is not None: args.extend(['-p', str(port)]) @@ -460,6 +470,7 @@ class LSHSubprocessVendor(SubprocessVend def _get_vendor_specific_argv(self, username, host, port, subsystem=None, command=None): + self._check_hostname(host) args = [self.executable_path] if port is not None: args.extend(['-p', str(port)]) @@ -481,6 +492,7 @@ class PLinkSubprocessVendor(SubprocessVe def _get_vendor_specific_argv(self, username, host, port, subsystem=None, command=None): + self._check_hostname(host) args = [self.executable_path, '-x', '-a', '-ssh', '-2', '-batch'] if port is not None: args.extend(['-P', str(port)])