aboutsummaryrefslogtreecommitdiffstats
path: root/Mailman/Cgi/admin.py
diff options
context:
space:
mode:
authorMark Sapiro <msapiro@value.net>2012-02-05 13:19:39 -0800
committerMark Sapiro <msapiro@value.net>2012-02-05 13:19:39 -0800
commitfdd6141b978cdc0876263d962f996eb88964537b (patch)
tree6836790556e26d896b791946fc60df5d0f88ab8a /Mailman/Cgi/admin.py
parent3c1fe7bcb3c10650cd039c800aa1356886586873 (diff)
downloadmailman2-fdd6141b978cdc0876263d962f996eb88964537b.tar.gz
mailman2-fdd6141b978cdc0876263d962f996eb88964537b.tar.xz
mailman2-fdd6141b978cdc0876263d962f996eb88964537b.zip
Added Tokio Kikuchi's Cross-site Request Forgery hardening to the admin UI.
Diffstat (limited to '')
-rw-r--r--Mailman/Cgi/admin.py32
1 files changed, 26 insertions, 6 deletions
diff --git a/Mailman/Cgi/admin.py b/Mailman/Cgi/admin.py
index 569aa61c..d881241c 100644
--- a/Mailman/Cgi/admin.py
+++ b/Mailman/Cgi/admin.py
@@ -1,4 +1,4 @@
-# Copyright (C) 1998-2011 by the Free Software Foundation, Inc.
+# Copyright (C) 1998-2012 by the Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@@ -41,6 +41,7 @@ from Mailman.htmlformat import *
from Mailman.Cgi import Auth
from Mailman.Logging.Syslog import syslog
from Mailman.Utils import sha_new
+from Mailman.CSRFcheck import csrf_check
# Set up i18n
_ = i18n._
@@ -55,6 +56,8 @@ except NameError:
True = 1
False = 0
+AUTH_CONTEXTS = (mm_cfg.AuthListAdmin, mm_cfg.AuthSiteAdmin)
+
def main():
@@ -83,6 +86,18 @@ def main():
# If the user is not authenticated, we're done.
cgidata = cgi.FieldStorage(keep_blank_values=1)
+ # CSRF check
+ safe_params = ['VARHELP', 'adminpw', 'admlogin']
+ params = cgidata.keys()
+ if set(params) - set(safe_params):
+ csrf_checked = csrf_check(mlist, cgidata.getvalue('csrf_token'))
+ else:
+ csrf_checked = True
+ # if password is present, void cookie to force password authentication.
+ if cgidata.getvalue('adminpw'):
+ os.environ['HTTP_COOKIE'] = ''
+ csrf_checked = True
+
if not mlist.WebAuthenticate((mm_cfg.AuthListAdmin,
mm_cfg.AuthSiteAdmin),
cgidata.getvalue('adminpw', '')):
@@ -174,8 +189,12 @@ def main():
signal.signal(signal.SIGTERM, sigterm_handler)
if cgidata.keys():
- # There are options to change
- change_options(mlist, category, subcat, cgidata, doc)
+ if csrf_checked:
+ # There are options to change
+ change_options(mlist, category, subcat, cgidata, doc)
+ else:
+ doc.addError(
+ _('The form lifetime has expired. (request forgery check)'))
# Let the list sanity check the changed values
mlist.CheckValues()
# Additional sanity checks
@@ -362,7 +381,7 @@ def option_help(mlist, varhelp):
url = '%s/%s/%s' % (mlist.GetScriptURL('admin'), category, subcat)
else:
url = '%s/%s' % (mlist.GetScriptURL('admin'), category)
- form = Form(url)
+ form = Form(url, mlist=mlist, contexts=AUTH_CONTEXTS)
valtab = Table(cellspacing=3, cellpadding=4, width='100%')
add_options_table_item(mlist, category, subcat, valtab, item, detailsp=0)
form.AddItem(valtab)
@@ -408,9 +427,10 @@ def show_results(mlist, doc, category, subcat, cgidata):
encoding = 'multipart/form-data'
if subcat:
form = Form('%s/%s/%s' % (adminurl, category, subcat),
- encoding=encoding)
+ encoding=encoding, mlist=mlist, contexts=AUTH_CONTEXTS)
else:
- form = Form('%s/%s' % (adminurl, category), encoding=encoding)
+ form = Form('%s/%s' % (adminurl, category),
+ encoding=encoding, mlist=mlist, contexts=AUTH_CONTEXTS)
# This holds the two columns of links
linktable = Table(valign='top', width='100%')
linktable.AddRow([Center(Bold(_("Configuration Categories"))),