changeset 33640:ca398a50ca00 stable

subrepo: add tests for git rogue ssh urls (SEC) 'ssh://' has an exploit that will pass the url blindly to the ssh command, allowing a malicious person to have a subrepo with '-oProxyCommand' which could run arbitrary code on a user's machine. In addition, at least on Windows, a pipe '|' is able to execute arbitrary commands. When this happens, let's throw a big abort into the user's face so that they can inspect what's going on.
author Sean Farley <sean@farley.io>
date Mon, 31 Jul 2017 14:55:11 -0700
parents 173ecccb9ee7
children 00a75672a9cb
files mercurial/subrepo.py tests/test-subrepo-git.t
diffstat 2 files changed, 58 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/subrepo.py	Mon Jul 31 16:44:17 2017 -0700
+++ b/mercurial/subrepo.py	Mon Jul 31 14:55:11 2017 -0700
@@ -1543,6 +1543,9 @@
 
     def _fetch(self, source, revision):
         if self._gitmissing():
+            # SEC: check for safe ssh url
+            util.checksafessh(source)
+
             source = self._abssource(source)
             self.ui.status(_('cloning subrepo %s from %s\n') %
                             (self._relpath, source))
--- a/tests/test-subrepo-git.t	Mon Jul 31 16:44:17 2017 -0700
+++ b/tests/test-subrepo-git.t	Mon Jul 31 14:55:11 2017 -0700
@@ -1173,3 +1173,58 @@
   [255]
   $ f -Dq pwned.txt
   pwned: you asked for it
+
+test for ssh exploit with git subrepos 2017-07-25
+
+  $ hg init malicious-proxycommand
+  $ cd malicious-proxycommand
+  $ echo 's = [git]ssh://-oProxyCommand=rm${IFS}non-existent/path' > .hgsub
+  $ git init s
+  Initialized empty Git repository in $TESTTMP/tc/malicious-proxycommand/s/.git/
+  $ cd s
+  $ git commit --allow-empty -m 'empty'
+  [master (root-commit) 153f934] empty
+  $ cd ..
+  $ hg add .hgsub
+  $ hg ci -m 'add subrepo'
+  $ cd ..
+  $ hg clone malicious-proxycommand malicious-proxycommand-clone
+  updating to branch default
+  abort: potentially unsafe url: 'ssh://-oProxyCommand=rm${IFS}non-existent/path' (in subrepo s)
+  [255]
+
+also check that a percent encoded '-' (%2D) doesn't work
+
+  $ cd malicious-proxycommand
+  $ echo 's = [git]ssh://%2DoProxyCommand=rm${IFS}non-existent/path' > .hgsub
+  $ hg ci -m 'change url to percent encoded'
+  $ cd ..
+  $ rm -r malicious-proxycommand-clone
+  $ hg clone malicious-proxycommand malicious-proxycommand-clone
+  updating to branch default
+  abort: potentially unsafe url: 'ssh://-oProxyCommand=rm${IFS}non-existent/path' (in subrepo s)
+  [255]
+
+also check for a pipe
+
+  $ cd malicious-proxycommand
+  $ echo 's = [git]ssh://fakehost|shell/path' > .hgsub
+  $ hg ci -m 'change url to pipe'
+  $ cd ..
+  $ rm -r malicious-proxycommand-clone
+  $ hg clone malicious-proxycommand malicious-proxycommand-clone
+  updating to branch default
+  abort: potentially unsafe url: 'ssh://fakehost|shell/path' (in subrepo s)
+  [255]
+
+also check that a percent encoded '|' (%7C) doesn't work
+
+  $ cd malicious-proxycommand
+  $ echo 's = [git]ssh://fakehost%7Cshell/path' > .hgsub
+  $ hg ci -m 'change url to percent encoded'
+  $ cd ..
+  $ rm -r malicious-proxycommand-clone
+  $ hg clone malicious-proxycommand malicious-proxycommand-clone
+  updating to branch default
+  abort: potentially unsafe url: 'ssh://fakehost|shell/path' (in subrepo s)
+  [255]