Mercurial > kallithea
changeset 7397:3ee4ac068369 stable
hg: explicit handling of the 'batch' protocol command - consider it a "push" command if any of the batch commands are
This change mitigates some privilege escalation problems like CVE-2018-1000132
which was fixed in Mercurial 4.5.1 and currently is described on
https://www.mercurial-scm.org/wiki/WhatsNew#Mercurial_4.5.1_.2F_4.5.2_.282018-03-06.29 .
author | Mads Kiilerich <mads@kiilerich.com> |
---|---|
date | Sun, 21 Oct 2018 15:18:43 +0200 |
parents | 21084a951cd9 |
children | ba444b73e01a |
files | kallithea/lib/middleware/simplehg.py |
diffstat | 1 files changed, 30 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/kallithea/lib/middleware/simplehg.py Thu Oct 11 02:06:50 2018 +0200 +++ b/kallithea/lib/middleware/simplehg.py Sun Oct 21 15:18:43 2018 +0200 @@ -31,6 +31,7 @@ import os import logging import traceback +import urllib from paste.httpheaders import REMOTE_USER, AUTH_TYPE from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError, \ @@ -66,6 +67,24 @@ return ishg_path +def get_header_hgarg(environ): + """Decode the special Mercurial encoding of big requests over multiple headers. + >>> get_header_hgarg({}) + '' + >>> get_header_hgarg({'HTTP_X_HGARG_0': ' ', 'HTTP_X_HGARG_1': 'a','HTTP_X_HGARG_2': '','HTTP_X_HGARG_3': 'b+c %20'}) + 'ab+c %20' + """ + chunks = [] + i = 1 + while True: + v = environ.get('HTTP_X_HGARG_%d' % i) + if v is None: + break + chunks.append(v) + i += 1 + return ''.join(chunks) + + class SimpleHg(BaseVCSController): def _handle_request(self, environ, start_response): @@ -278,6 +297,17 @@ parts = qry.split('=', 1) if len(parts) == 2 and parts[0] == 'cmd': cmd = parts[1] + if cmd == 'batch': + hgarg = get_header_hgarg(environ) + if not hgarg.startswith('cmds='): + return 'push' # paranoid and safe + for cmd_arg in hgarg[5:].split(';'): + cmd, _args = urllib.unquote_plus(cmd_arg).split(' ', 1) + op = mapping.get(cmd, 'pull') + if op != 'pull': + assert op == 'push' + return 'push' + return 'pull' return mapping.get(cmd, 'pull') raise Exception('Unable to detect pull/push action !!'