Jul 22 - Update protect admin page with fail2ban
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import hmac
|
||||
import logging
|
||||
import re
|
||||
from functools import wraps
|
||||
|
||||
@@ -12,6 +13,8 @@ from app import db, log_action, Section, Topic
|
||||
|
||||
admin_bp = Blueprint("admin", __name__, url_prefix="/admin")
|
||||
|
||||
auth_log = logging.getLogger("jqc.auth")
|
||||
|
||||
MEDIA_TYPES = ("none", "image", "video", "embed")
|
||||
|
||||
|
||||
@@ -39,14 +42,24 @@ def login():
|
||||
|
||||
user_ok = hmac.compare_digest(username, expected_user)
|
||||
pass_ok = bool(pw_hash) and check_password_hash(pw_hash, password)
|
||||
|
||||
# Sanitize the attacker-controlled username before logging: collapse all
|
||||
# whitespace (kills CR/LF log-injection) and cap length. The real client
|
||||
# IP is logged LAST so a crafted username can't spoof the '... from <ip>'
|
||||
# token the fail2ban filter anchors on at end-of-line.
|
||||
safe_user = re.sub(r"\s+", " ", username).strip()[:64] or "-"
|
||||
client_ip = request.remote_addr or "-"
|
||||
|
||||
if user_ok and pass_ok:
|
||||
session.clear()
|
||||
session["admin"] = username
|
||||
auth_log.info("LOGIN OK user=%s from %s", safe_user, client_ip)
|
||||
dest = request.args.get("next", "")
|
||||
# only allow local admin redirects
|
||||
if not dest.startswith("/admin"):
|
||||
dest = url_for("admin.dashboard")
|
||||
return redirect(dest)
|
||||
auth_log.warning("FAILED LOGIN user=%s from %s", safe_user, client_ip)
|
||||
flash("Incorrect username or password.", "error")
|
||||
|
||||
return render_template("admin/login.html")
|
||||
|
||||
Reference in New Issue
Block a user