From 1dcba3a2642244b4adee3ef1d43a2429daaaf82c Mon Sep 17 00:00:00 2001 From: CodeKevin Date: Sat, 6 Feb 2016 15:38:14 -0500 Subject: [PATCH] Fixing CSRF issues and expanding trusted proxies to local network --- CTFd/templates/login.html | 1 + CTFd/templates/register.html | 1 + CTFd/utils.py | 42 ++++++++++++++++++++++++++++++------ CTFd/views.py | 21 ------------------ 4 files changed, 38 insertions(+), 27 deletions(-) diff --git a/CTFd/templates/login.html b/CTFd/templates/login.html index dea491c..26a9a75 100644 --- a/CTFd/templates/login.html +++ b/CTFd/templates/login.html @@ -60,6 +60,7 @@ + diff --git a/CTFd/templates/register.html b/CTFd/templates/register.html index c36896b..6fd7e02 100644 --- a/CTFd/templates/register.html +++ b/CTFd/templates/register.html @@ -56,6 +56,7 @@ + diff --git a/CTFd/utils.py b/CTFd/utils.py index ef41a1e..92fa12b 100644 --- a/CTFd/utils.py +++ b/CTFd/utils.py @@ -1,9 +1,9 @@ -from CTFd.models import db, WrongKeys, Pages, Config +from CTFd.models import db, WrongKeys, Pages, Config, Tracking from CTFd import mail from six.moves.urllib.parse import urlparse, urljoin from functools import wraps -from flask import current_app as app, g, request, redirect, url_for, session, render_template +from flask import current_app as app, g, request, redirect, url_for, session, render_template, abort from flask.ext.mail import Message from socket import inet_aton, inet_ntoa from struct import unpack, pack @@ -18,6 +18,7 @@ import requests import logging import os import sys +import re def init_logs(app): @@ -78,6 +79,7 @@ def init_errors(app): def gateway_error(error): return render_template('errors/502.html'), 502 + def init_utils(app): app.jinja_env.filters['unix_time'] = unix_time app.jinja_env.filters['unix_time_millis'] = unix_time_millis @@ -89,7 +91,7 @@ def init_utils(app): @app.context_processor def inject_user(): - if authed(): + if session: return dict(session) return dict() @@ -100,6 +102,27 @@ def init_utils(app): if not is_setup(): return redirect(url_for('views.setup')) + @app.before_request + def tracker(): + if authed(): + track = Tracking.query.filter_by(ip=ip2long(get_ip()), team=session['id']).first() + if not track: + visit = Tracking(ip=get_ip(), team=session['id']) + db.session.add(visit) + db.session.commit() + else: + track.date = datetime.datetime.utcnow() + db.session.commit() + db.session.close() + + @app.before_request + def csrf(): + if not session.get('nonce'): + session['nonce'] = sha512(os.urandom(10)) + if request.method == "POST": + if session['nonce'] != request.form.get('nonce'): + abort(403) + def ctf_name(): name = get_config('ctf_name') @@ -207,11 +230,18 @@ def unix_time_millis(dt): def get_ip(): - trusted_proxies = {'127.0.0.1'} # define your own set + trusted_proxies = [ + '^127\.0\.0\.1$', + '^::1$', + '^fc00:', + '^10\.', + '^172\.(1[6-9]|2[0-9]|3[0-1])\.', + '^192\.168\.' + ] + combined = "(" + ")|(".join(trusted_proxies) + ")" route = request.access_route + [request.remote_addr] - remote_addr = next((addr for addr in reversed(route) - if addr not in trusted_proxies), request.remote_addr) + remote_addr = next((addr for addr in reversed(route) if re.match(combined, addr)), request.remote_addr) return remote_addr diff --git a/CTFd/views.py b/CTFd/views.py index 7af61de..6e864c4 100644 --- a/CTFd/views.py +++ b/CTFd/views.py @@ -17,27 +17,6 @@ import datetime views = Blueprint('views', __name__) -@views.before_request -def tracker(): - if authed(): - track = Tracking.query.filter_by(ip=ip2long(get_ip()), team=session['id']).first() - if not track: - visit = Tracking(ip=get_ip(), team=session['id']) - db.session.add(visit) - db.session.commit() - else: - track.date = datetime.datetime.utcnow() - db.session.commit() - db.session.close() - - -@views.before_request -def csrf(): - if request.method == "POST": - if session['nonce'] != request.form.get('nonce'): - abort(403) - - @views.before_request def redirect_setup(): if request.path == "/static/css/style.css":