From d1e5fc7d3708d877353ca64dd4aa7cfd1cde4cb4 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Mon, 26 Oct 2020 22:06:28 +0100 Subject: [PATCH] security: fix remote code execution via cache action, CVE-2020-25074 An attacker with "write" permissions can upload specifically made malicious code via the normal wiki attachment upload functionality and later execute it on the server (as the same uid/gid as the wiki server process) by using the vulnerable MoinMoin cache action. --- MoinMoin/action/cache.py | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/MoinMoin/action/cache.py b/MoinMoin/action/cache.py index a38967e8c..f0bb23ee0 100644 --- a/MoinMoin/action/cache.py +++ b/MoinMoin/action/cache.py @@ -103,6 +103,19 @@ def key(request, wikiname=None, itemname=None, attachname=None, content=None, se return key +def valid_key(key): + # make sure the key looks like keys generated by key() + if not isinstance(key, unicode): + # key is None (not given in url args) or something unexpected + return False + try: + int(key, 16) # try to evaluate as hex number + except ValueError: + # was not a hex number + return False + return len(key) == 40 # hmac-sha1 hexdigest == 40 hex chars + + def put(request, key, data, filename=None, content_type=None, @@ -234,14 +247,14 @@ def _do_remove(request, key): remove(request, key) -def _do(request, do, key): - if do == 'get': - _do_get(request, key) - elif do == 'remove': - _do_remove(request, key) - def execute(pagename, request): do = request.values.get('do') key = request.values.get('key') - _do(request, do, key) + valid = valid_key(key) # validate untrusted input + if valid and do == 'get': + _do_get(request, key) + elif valid and do == 'remove': + _do_remove(request, key) + else: + request.status_code = 404