Commit 38979178 authored by Andreas Valder's avatar Andreas Valder

added CSRF protection, closes #75

parent bdfe0846
This diff is collapsed.
......@@ -32,18 +32,3 @@ Optional (wird für einzelne Features benötigt):
* python-ldap (Login mit Fachschaftsaccount)
* python-icalendar (SoGo-Kalenderimport für Sitzungsankündigungen)
* python-mysql-connector (wenn MySQL als Datenbank verwendet werden soll)
# Lizenz
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License Version 2
as published by the Free Software Foundation;
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
......@@ -9,6 +9,7 @@ import hashlib
import random
import sched
import traceback
import string
app = Flask(__name__)
......@@ -70,6 +71,21 @@ def mod_required(func):
return func(*args, **kwargs)
return decorator
def csrf_protect(func):
@wraps(func)
def decorator(*args, **kwargs):
if '_csrf_token' in request.values:
token = request.values['_csrf_token']
elif '_csrf_token' in request.get_json():
token = request.get_json()['_csrf_token']
else:
token = none
if not ('_csrf_token' in session) or (session['_csrf_token'] != token ) or not token:
return 'csrf test failed', 403
else:
return func(*args, **kwargs)
return decorator
def evalperm(perms):
cperms = []
lperms = []
......@@ -379,6 +395,7 @@ def login():
modify('INSERT INTO users (name, realname, fsacc, level, calendar_key, rfc6238) VALUES (?, ?, ?, 1, "", "")', user, session['user']['givenName'], user)
dbuser = query('SELECT * FROM users WHERE name = ?', user)
session['user']['dbid'] = dbuser[0]['id']
session['_csrf_token'] = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(128))
return redirect(request.values.get('ref', url_for('index')))
@app.route('/logout', methods=['GET', 'POST'])
......@@ -412,10 +429,12 @@ tabs = {
@app.route('/edit', methods=['GET', 'POST'])
@mod_required
@csrf_protect
def edit(prefix='', ignore=[]):
# All editable tables are expected to have a 'time_updated' field
ignore.append('ref')
ignore.append('prefix')
ignore.append('_csrf_token')
if not prefix and 'prefix' in request.args:
prefix = request.args['prefix']
modify('BEGIN')
......@@ -439,6 +458,7 @@ def edit(prefix='', ignore=[]):
@app.route('/new/<table>', methods=['GET', 'POST'])
@mod_required
@csrf_protect
def create(table):
assert table in tabs
defaults = {'created_by': session['user']['dbid'], 'time_created': datetime.now(), 'time_updated': datetime.now()}
......@@ -450,9 +470,9 @@ def create(table):
values.append(val)
args = request.values
if (request.method == 'POST') and (request.get_json()):
args = request.get_json()
for column, val in args.items():
if column == 'ref':
args = request.get_json().items()
for column, val in args:
if (column == 'ref') or (column == '_csrf_token'):
continue
assert column in tabs[table][2]+tabs[table][3]
assert column not in defaults
......
var moderator = {
api: {
csrf_token: '',
init: function () {
},
......@@ -9,6 +10,7 @@ var moderator = {
moderator.api.set_multi(req,reload)
},
set_multi: function(dict,reload) {
dict['_csrf_token'] = moderator.api.csrf_token;
$.ajax({
method: "POST",
url: "/edit",
......@@ -23,6 +25,7 @@ var moderator = {
});
},
add_new: function(value,type,reload) {
value['_csrf_token'] = moderator.api.csrf_token;
$.ajax({
method: "POST",
url: "/new/"+type,
......@@ -42,7 +45,11 @@ var moderator = {
url: url,
dataType: "text",
})
},
setcsrftoken: function (token) {
moderator.api.csrf_token = token;
}
},
editor: {
init: function() {
......
......@@ -148,6 +148,7 @@
<script>
$( function () {
moderator.permissioneditor.setpermissions({{global_permissions|tojson|safe}});
moderator.api.setcsrftoken('{{ session['_csrf_token'] }}');
});
</script>
{% endif %}
......
......@@ -6,7 +6,7 @@
{% from 'macros.html' import moderator_permissioneditor %}
{% extends "base.html" %}
{% block title %} - {{course.title}}{% endblock %}
{% block title %}- {{course.title}}{% endblock %}
{% block content %}
<div class="panel panel-default">
<div class="panel-heading">
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment