UI - add CSRF protection

This commit is contained in:
bunkerity 2021-07-09 16:01:51 +02:00
parent 0d3f7d3925
commit 72a09eac6d
No known key found for this signature in database
GPG Key ID: 3D80806F12602A7C
10 changed files with 27 additions and 19 deletions

View File

@ -1,9 +1,8 @@
FROM alpine FROM alpine
COPY ui/dependencies.sh /tmp RUN apk add py3-pip bash
RUN chmod +x /tmp/dependencies.sh && \ COPY ui/requirements.txt /tmp
/tmp/dependencies.sh && \ RUN pip3 install -r /tmp/requirements.txt
rm -f /tmp/dependencies.sh
COPY gen/ /opt/bunkerized-nginx/gen COPY gen/ /opt/bunkerized-nginx/gen
COPY confs/site/ /opt/bunkerized-nginx/confs/site COPY confs/site/ /opt/bunkerized-nginx/confs/site

View File

@ -1,4 +0,0 @@
#!/bin/sh
apk add py3-pip bash
pip3 install docker flask flask-login requests gunicorn

View File

@ -2,6 +2,7 @@
from flask import Flask, render_template, current_app, request, redirect from flask import Flask, render_template, current_app, request, redirect
from flask_login import LoginManager, login_required, login_user, logout_user from flask_login import LoginManager, login_required, login_user, logout_user
from flask_wtf.csrf import CSRFProtect, CSRFError
from src.Instances import Instances from src.Instances import Instances
from src.User import User from src.User import User
@ -33,11 +34,17 @@ login_manager.init_app(app)
login_manager.login_view = "login" login_manager.login_view = "login"
user = User(vars["ADMIN_USERNAME"], vars["ADMIN_PASSWORD"]) user = User(vars["ADMIN_USERNAME"], vars["ADMIN_PASSWORD"])
app.config["USER"] = user app.config["USER"] = user
@login_manager.user_loader @login_manager.user_loader
def load_user(user_id): def load_user(user_id):
return User(user_id, vars["ADMIN_PASSWORD"]) return User(user_id, vars["ADMIN_PASSWORD"])
# CSRF protection
csrf = CSRFProtect()
csrf.init_app(app)
@app.errorhandler(CSRFError)
def handle_csrf_error(e):
return render_template("error.html", title="Error", error="Wrong CSRF token !"), 401
@app.route('/login', methods=["GET", "POST"]) @app.route('/login', methods=["GET", "POST"])
def login() : def login() :
fail = False fail = False

View File

@ -3,4 +3,5 @@ requests
docker docker
flask-login flask-login
bcrypt bcrypt
gunicorn gunicorn
Flask-WTF

View File

@ -2,13 +2,9 @@
{% block content %} {% block content %}
<div class="row justify-content-center"> <div class="alert alert-danger text-center">
<div class="col col-12 col-md-6 text-center"> Something went wrong...<br /><br />
<div class="alert alert-danger"> {{ error }}
Something went wrong...<br />
{{ error }}
</div>
</div> </div>
</div>
{% endblock %} {% endblock %}

View File

@ -25,6 +25,7 @@
<div class="col col-12 col-lg-6"> <div class="col col-12 col-lg-6">
<form id="form-instance-{{ instance["id"] }}"> <form id="form-instance-{{ instance["id"] }}">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<input type="hidden" name="INSTANCE_ID" value="{{ instance["id"] }}"> <input type="hidden" name="INSTANCE_ID" value="{{ instance["id"] }}">
</form> </form>
<div class="card border-{{ color }} mb-3" style="max-width: 80rem;"> <div class="card border-{{ color }} mb-3" style="max-width: 80rem;">

View File

@ -9,7 +9,13 @@
<img src="img/logo.png" class="mb-4" style="max-width: 200px;"> <img src="img/logo.png" class="mb-4" style="max-width: 200px;">
</div> </div>
<h1 class="h3 mb-3 fw-normal">Authentication required</h1> <h1 class="h3 mb-3 fw-normal">Authentication required</h1>
{% if fail %}
<div class="alert alert-danger fade show text-break" role="alert">
Wrong username and/or password...
</div>
{% endif %}
<form action="login" method="POST"> <form action="login" method="POST">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div class="form-floating"> <div class="form-floating">
<input type="text" id="username" class="form-control" name="username" placeholder="user"> <input type="text" id="username" class="form-control" name="username" placeholder="user">
<label for="username">Username</label> <label for="username">Username</label>
@ -22,5 +28,4 @@
</form> </form>
</div> </div>
{% endblock %}
{% endblock %}

View File

@ -8,6 +8,7 @@
<div class="modal-body"> <div class="modal-body">
Are you sure you want to delete the configuration of {{ service["SERVER_NAME"] }} ? Are you sure you want to delete the configuration of {{ service["SERVER_NAME"] }} ?
<form id="form-delete-{{ id_server_name }}"> <form id="form-delete-{{ id_server_name }}">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<input type="hidden" value="{{ service["SERVER_NAME"] }}" name="SERVER_NAME"> <input type="hidden" value="{{ service["SERVER_NAME"] }}" name="SERVER_NAME">
</form> </form>
</div> </div>

View File

@ -17,6 +17,7 @@
{% endfor %} {% endfor %}
</ul> </ul>
<form id="form-edit-{{ id_server_name }}"> <form id="form-edit-{{ id_server_name }}">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<input type="hidden" value="{{ service["SERVER_NAME"] }}" name="OLD_SERVER_NAME"> <input type="hidden" value="{{ service["SERVER_NAME"] }}" name="OLD_SERVER_NAME">
<div class="tab-content" id="edit-content-{{ id_server_name }}"> <div class="tab-content" id="edit-content-{{ id_server_name }}">
{% set check = {"class": "show active"} %} {% set check = {"class": "show active"} %}

View File

@ -17,6 +17,7 @@
{% endfor %} {% endfor %}
</ul> </ul>
<form id="form-new"> <form id="form-new">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div class="tab-content" id="new-content"> <div class="tab-content" id="new-content">
{% set check = {"class": "show active"} %} {% set check = {"class": "show active"} %}
{% for k, v in config["CONFIG"].get_settings().items() %} {% for k, v in config["CONFIG"].get_settings().items() %}