From 4bd002aee978813bc664cf186ef38ff4e8bbe1cd Mon Sep 17 00:00:00 2001 From: mdipierro Date: Wed, 4 May 2016 09:11:55 -0500 Subject: [PATCH] fixed CSRF in admin enabled/disable. thanks Nerendra Bhati --- applications/admin/controllers/default.py | 2 +- applications/admin/models/access.py | 12 ++++++++---- applications/admin/views/default/site.html | 2 +- applications/examples/static/css/stupid.css | 2 +- fabfile.py | 5 +++-- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/applications/admin/controllers/default.py b/applications/admin/controllers/default.py index afdee6c9..300370bb 100644 --- a/applications/admin/controllers/default.py +++ b/applications/admin/controllers/default.py @@ -533,8 +533,8 @@ def delete(): redirect(URL(sender, anchor=request.vars.id2)) return dict(dialog=dialog, filename=filename) - def enable(): + if not URL.verify(request, hmac_key=session.hmac_key): raise HTTP(401) app = get_app() filename = os.path.join(apath(app, r=request), 'DISABLED') if is_gae: diff --git a/applications/admin/models/access.py b/applications/admin/models/access.py index d27ff5b5..fa1ee01c 100644 --- a/applications/admin/models/access.py +++ b/applications/admin/models/access.py @@ -4,6 +4,7 @@ import time from gluon import portalocker from gluon.admin import apath from gluon.fileutils import read_file +from gluon.utils import web2py_uuid # ########################################################### # ## make sure administrator is on localhost or https # ########################################################### @@ -49,15 +50,18 @@ except IOError: def verify_password(password): session.pam_user = None if DEMO_MODE: - return True + ret = True elif not _config.get('password'): - return False + ret - False elif _config['password'].startswith('pam_user:'): session.pam_user = _config['password'][9:].strip() import gluon.contrib.pam - return gluon.contrib.pam.authenticate(session.pam_user, password) + ret = gluon.contrib.pam.authenticate(session.pam_user, password) else: - return _config['password'] == CRYPT()(password)[0] + ret = _config['password'] == CRYPT()(password)[0] + if ret: + session.hmac_key = web2py_uuid() + return ret # ########################################################### diff --git a/applications/admin/views/default/site.html b/applications/admin/views/default/site.html index d5240668..586eb8bc 100644 --- a/applications/admin/views/default/site.html +++ b/applications/admin/views/default/site.html @@ -56,7 +56,7 @@ {{pass}} - {{=button_enable(URL('enable',args=a), a) if a!='admin' else ''}} + {{=button_enable(URL('enable',args=a, hmac_key=session.hmac_key), a) if a!='admin' else ''}} {{pass}} diff --git a/applications/examples/static/css/stupid.css b/applications/examples/static/css/stupid.css index 71484488..2dd896a0 100644 --- a/applications/examples/static/css/stupid.css +++ b/applications/examples/static/css/stupid.css @@ -68,7 +68,7 @@ header, main, footer {display:block; with:100%} /* IE fix */ input:not([type]), input:not([type=checkbox]):not([type=radio]):not([type=button]):not([type=submit]), [type=file]:before {outline:none; padding:0.5em 1em; margin:0.5px; border-bottom:1px solid #ddd; width:100%} textarea {width:100%; border:1px solid #ddd; padding:4px 8px; outline:none; outline:none} select {-webkit-appearance:none; outline:none; padding:0.5em 1em; border-radius:0; margin:0.5px; border-bottom:1px solid #ddd; width:100%;background-color:transparent} -input, textarea, select, button {font-size:12px} +input, textarea, select, button, .btn {font-size:12px} input:not([type]):hover, input:not([type=checkbox]):not([type=radio]):not([type=button]):not([type=submit]):hover, select:hover, textarea:hover {background-color:#fbf6d9; transition:background-color 1s ease} input:invalid, input.error {background:#cc1f00;color:white} diff --git a/fabfile.py b/fabfile.py index 5226c530..6e6fcdb4 100644 --- a/fabfile.py +++ b/fabfile.py @@ -115,8 +115,9 @@ def deploy(appname=None, all=False): """fab -H username@host deploy:appname,all""" appname = appname or os.path.split(os.getcwd())[-1] appfolder = applications+'/'+appname - if os.path.exists('_update.zip'): - os.unlink('_update.zip') + zipfile = os.path.join(appfolder, '_update.zip') + if os.path.exists(zipfile): + os.unlink(zipfile) backup = mkdir_or_backup(appname)