add csrf protection
This commit is contained in:
36
app/auth.py
36
app/auth.py
@@ -1,8 +1,9 @@
|
||||
from flask import session, flash, redirect, url_for, abort
|
||||
from flask import session, flash, redirect, url_for, abort, request, current_app
|
||||
from .models import Sessions, Users
|
||||
from argon2 import PasswordHasher
|
||||
from functools import wraps
|
||||
import secrets
|
||||
import hmac
|
||||
import time
|
||||
import re
|
||||
|
||||
@@ -88,3 +89,36 @@ def mod_only(view_func):
|
||||
abort(403)
|
||||
return view_func(*args, **kwargs)
|
||||
return wrapper
|
||||
|
||||
def csrf_verified(view_func):
|
||||
"""
|
||||
protects a request with a form against csrf and invalidates the csrf token stored in the session.
|
||||
|
||||
requires @login_requred.
|
||||
"""
|
||||
|
||||
@wraps(view_func)
|
||||
def wrapper(*args, **kwargs):
|
||||
if not session.get('csrf'):
|
||||
abort(403)
|
||||
if not request.form.get('csrf'):
|
||||
abort(403)
|
||||
|
||||
parts = request.form['csrf'].split('.')
|
||||
if len(parts) != 2:
|
||||
abort(403)
|
||||
|
||||
given_message = parts[0]
|
||||
rng = bytes.fromhex(parts[1])
|
||||
session_key = session['pyrom_session_key']
|
||||
message = f'd${len(session_key)}${session_key}@{len(rng)}@{rng.hex()}'
|
||||
expected = hmac.digest(current_app.config['SECRET_KEY'].encode('utf-8'), message.encode('utf-8'), 'SHA256').hex()
|
||||
|
||||
if not hmac.compare_digest(given_message, expected):
|
||||
abort(403)
|
||||
|
||||
session.pop('csrf')
|
||||
|
||||
return view_func(*args, **kwargs)
|
||||
return wrapper
|
||||
|
||||
|
||||
Reference in New Issue
Block a user