diff --git a/CVE-2021-42096-CVE-2021-42097.patch b/CVE-2021-42096-CVE-2021-42097.patch new file mode 100644 index 0000000000000000000000000000000000000000..1a7ef25cee9f8a15714b658d9b34a148f20676d0 --- /dev/null +++ b/CVE-2021-42096-CVE-2021-42097.patch @@ -0,0 +1,153 @@ +Origin: https://bazaar.launchpad.net/~mailman-coders/mailman/2.1/revision/1873 +Author: Mark Sapiro +Bug: https://bugs.launchpad.net/mailman/+bug/1947639, + https://bugs.launchpad.net/mailman/+bug/1947640 +Subject: Fixes for CVEs 2021-42096 and 2021-42097. + +Security +- A potential for a list member to carry out an off-line brute force + attack to obtain the list admin password has been reported by Andre + Protas, Richard Cloke and Andy Nuttall of Apple. This is fixed. + CVE-2021-42096 (LP:#1947639) +- A CSRF attack via the user options page could allow takeover of a users + account. This is fixed. CVE-2021-42097 (LP:#1947640) + +=== modified file 'Mailman/CSRFcheck.py' +--- + Mailman/CSRFcheck.py | 22 +++++++++++++++++++--- + Mailman/Cgi/options.py | 25 ++++++++++++------------- + Mailman/SecurityManager.py | 1 + + 3 files changed, 32 insertions(+), 16 deletions(-) + +diff --git a/Mailman/CSRFcheck.py b/Mailman/CSRFcheck.py +index a1e78d9..0940b7e 100644 +--- a/Mailman/CSRFcheck.py ++++ b/Mailman/CSRFcheck.py +@@ -18,11 +18,13 @@ + """ Cross-Site Request Forgery checker """ + + import time ++import urllib + import marshal + import binascii + + from Mailman import mm_cfg +-from Mailman.Utils import sha_new ++from Mailman.Logging.Syslog import syslog ++from Mailman.Utils import UnobscureEmail, sha_new + + keydict = { + 'user': mm_cfg.AuthUser, +@@ -37,6 +39,10 @@ keydict = { + def csrf_token(mlist, contexts, user=None): + """ create token by mailman cookie generation algorithm """ + ++ if user: ++ # Unmunge a munged email address. ++ user = UnobscureEmail(urllib.unquote(user)) ++ + for context in contexts: + key, secret = mlist.AuthContextInfo(context, user) + if key: +@@ -49,9 +55,8 @@ def csrf_token(mlist, contexts, user=None): + token = binascii.hexlify(marshal.dumps((issued, keymac))) + return token + +-def csrf_check(mlist, token): ++def csrf_check(mlist, token, options_user=None): + """ check token by mailman cookie validation algorithm """ +- + try: + issued, keymac = marshal.loads(binascii.unhexlify(token)) + key, received_mac = keymac.split(':', 1) +@@ -62,6 +67,17 @@ def csrf_check(mlist, token): + key, user = key.split('+', 1) + else: + user = None ++ if user: ++ # This is for CVE-2021-42097. The token is a user token because ++ # of the fix for CVE-2021-42096 but it must match the user for ++ # whom the options page is requested. ++ raw_user = UnobscureEmail(urllib.unquote(user)) ++ if options_user and options_user != raw_user: ++ syslog('mischief', ++ 'Form for user %s submitted with CSRF token ' ++ 'issued for %s.', ++ options_user, raw_user) ++ return False + context = keydict.get(key) + key, secret = mlist.AuthContextInfo(context, user) + assert key +diff --git a/Mailman/Cgi/options.py b/Mailman/Cgi/options.py +index 386b308..980fc09 100644 +--- a/Mailman/Cgi/options.py ++++ b/Mailman/Cgi/options.py +@@ -54,9 +54,6 @@ except NameError: + True = 1 + False = 0 + +-AUTH_CONTEXTS = (mm_cfg.AuthListAdmin, mm_cfg.AuthSiteAdmin, +- mm_cfg.AuthListModerator, mm_cfg.AuthUser) +- + + def main(): + global _ +@@ -124,15 +121,6 @@ def main(): + print doc.Format() + return + +- if set(params) - set(safe_params): +- csrf_checked = csrf_check(mlist, cgidata.getfirst('csrf_token')) +- else: +- csrf_checked = True +- # if password is present, void cookie to force password authentication. +- if cgidata.getfirst('password'): +- os.environ['HTTP_COOKIE'] = '' +- csrf_checked = True +- + # Set the language for the page. If we're coming from the listinfo cgi, + # we might have a 'language' key in the cgi data. That was an explicit + # preference to view the page in, so we should honor that here. If that's +@@ -168,6 +156,16 @@ def main(): + user = user[-1] + + # Avoid cross-site scripting attacks ++ if set(params) - set(safe_params): ++ csrf_checked = csrf_check(mlist, cgidata.getfirst('csrf_token'), ++ Utils.UnobscureEmail(urllib.unquote(user))) ++ else: ++ csrf_checked = True ++ # if password is present, void cookie to force password authentication. ++ if cgidata.getfirst('password'): ++ os.environ['HTTP_COOKIE'] = '' ++ csrf_checked = True ++ + safeuser = Utils.websafe(user) + try: + Utils.ValidateEmail(user) +@@ -867,8 +865,9 @@ def options_page(mlist, doc, user, cpuser, userlang, message=''): + mlist.FormatButton('othersubs', + _('List my other subscriptions'))) + replacements[''] = ( ++ # Always make the CSRF token for the user. CVE-2021-42096 + mlist.FormatFormStart('options', user, mlist=mlist, +- contexts=AUTH_CONTEXTS, user=user)) ++ contexts=[mm_cfg.AuthUser], user=user)) + replacements[''] = user + replacements[''] = presentable_user + replacements[''] = mlist.FormatButton( +diff --git a/Mailman/SecurityManager.py b/Mailman/SecurityManager.py +index 9b7f03f..e9e5ce5 100644 +--- a/Mailman/SecurityManager.py ++++ b/Mailman/SecurityManager.py +@@ -104,6 +104,7 @@ class SecurityManager: + if user is None: + # A bad system error + raise TypeError, 'No user supplied for AuthUser context' ++ user = Utils.UnobscureEmail(urllib.unquote(user)) + secret = self.getMemberPassword(user) + userdata = urllib.quote(Utils.ObscureEmail(user), safe='') + key += 'user+%s' % userdata +-- +2.23.0 + diff --git a/mailman.spec b/mailman.spec index 512b40e585404fff3fd9a701c0558f585b8aa63f..c8844bb212dc4b91c13de111ed4c3b565c1a1d7c 100644 --- a/mailman.spec +++ b/mailman.spec @@ -3,7 +3,7 @@ Name: mailman Version: 2.1.29 -Release: 7 +Release: 8 Epoch: 3 Summary: GNU Mailing List Manager License: GPLv2+ @@ -30,6 +30,7 @@ Patch22: mailman-2.1.15-check_perms.patch Patch23: CVE-2020-12108.patch Patch24: CVE-2020-12137.patch Patch25: CVE-2020-15011.patch +Patch26: CVE-2021-42096-CVE-2021-42097.patch BuildRequires: automake gcc python2-devel systemd python2-dns Requires(pre): shadow-utils @@ -424,6 +425,9 @@ exit 0 %dir %attr(775,root,%{name}) /var/lock/%{name} %changelog +* Tue Oct 26 2021 wangkai - 2.1.29-8 +- Fix CVE-2021-42096 + * Mon Oct 25 2021 yaoxin - 2.1.29-7 - Fix CVE-2020-15011