security: add CSRF protection globally

The decorator @check_csrf can be used to check CSRF protection when 
using GET links (like delete a post or logout)
This commit is contained in:
Darks 2020-09-26 14:48:30 +02:00
parent 8edeb052e2
commit 0d8dd70956
Signed by: Darks
GPG Key ID: 7515644268BE1433
4 changed files with 24 additions and 1 deletions

View File

@ -3,6 +3,7 @@ from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_login import LoginManager
from flask_mail import Mail
from flask_wtf.csrf import CSRFProtect
from config import Config
app = Flask(__name__)
@ -15,11 +16,13 @@ if Config.SECRET_KEY == "a-random-secret-key":
db = SQLAlchemy(app)
migrate = Migrate(app, db)
mail = Mail(app)
csrf = CSRFProtect(app)
login = LoginManager(app)
login.login_view = 'login'
login.login_message = "Veuillez vous authentifier avant de continuer."
# Register converters (needed for routing)
from app.utils.converters import *
app.url_map.converters['forum'] = ForumConverter

View File

@ -7,6 +7,7 @@ from app.models.user import Member
from app.models.priv import Group
from app.utils.render import render
from app.utils.send_mail import send_validation_mail
from app.utils.check_csrf import check_csrf
import datetime
@ -68,6 +69,7 @@ def login():
@app.route('/deconnexion')
@login_required
@check_csrf
def logout():
logout_user()
flash('Déconnexion réussie', 'info')

View File

@ -36,7 +36,7 @@
<path fill="#ffffff" d="M12,15.5A3.5,3.5 0 0,1 8.5,12A3.5,3.5 0 0,1 12,8.5A3.5,3.5 0 0,1 15.5,12A3.5,3.5 0 0,1 12,15.5M19.43,12.97C19.47,12.65 19.5,12.33 19.5,12C19.5,11.67 19.47,11.34 19.43,11L21.54,9.37C21.73,9.22 21.78,8.95 21.66,8.73L19.66,5.27C19.54,5.05 19.27,4.96 19.05,5.05L16.56,6.05C16.04,5.66 15.5,5.32 14.87,5.07L14.5,2.42C14.46,2.18 14.25,2 14,2H10C9.75,2 9.54,2.18 9.5,2.42L9.13,5.07C8.5,5.32 7.96,5.66 7.44,6.05L4.95,5.05C4.73,4.96 4.46,5.05 4.34,5.27L2.34,8.73C2.21,8.95 2.27,9.22 2.46,9.37L4.57,11C4.53,11.34 4.5,11.67 4.5,12C4.5,12.33 4.53,12.65 4.57,12.97L2.46,14.63C2.27,14.78 2.21,15.05 2.34,15.27L4.34,18.73C4.46,18.95 4.73,19.03 4.95,18.95L7.44,17.94C7.96,18.34 8.5,18.68 9.13,18.93L9.5,21.58C9.54,21.82 9.75,22 10,22H14C14.25,22 14.46,21.82 14.5,21.58L14.87,18.93C15.5,18.67 16.04,18.34 16.56,17.94L19.05,18.95C19.27,19.03 19.54,18.95 19.66,18.73L21.66,15.27C21.78,15.05 21.73,14.78 21.54,14.63L19.43,12.97Z"></path>
</svg>Paramètres
</a>
<a href="{{ url_for('logout') }}">
<a href="{{ url_for('logout', csrf_token=csrf_token()) }}">
<svg viewBox="0 0 24 24">
<path fill="#ffffff" d="M17,17.25V14H10V10H17V6.75L22.25,12L17,17.25M13,2A2,2 0 0,1 15,4V8H13V4H4V20H13V16H15V20A2,2 0 0,1 13,22H4A2,2 0 0,1 2,20V4A2,2 0 0,1 4,2H13Z"></path>
</svg>Déconnexion

18
app/utils/check_csrf.py Normal file
View File

@ -0,0 +1,18 @@
from functools import wraps
from flask import request, abort
from flask_wtf import csrf
from wtforms.validators import ValidationError
from app import app
def check_csrf(func):
"""
Check csrf_token GET parameter
"""
@wraps(func)
def wrapped(*args, **kwargs):
try:
csrf.validate_csrf(request.args.get('csrf_token'))
except ValidationError:
abort(404)
return func(*args, **kwargs)
return wrapped