From b9b8335db91eda6962edd65acbaa8903ba8151d4 Mon Sep 17 00:00:00 2001 From: supermario Date: Wed, 3 Dec 2025 14:53:18 -0500 Subject: [PATCH] Fixed CSRF vulnerability, CVE is being issued --- background_installer.sh | 8 ++++---- requirements.txt | 1 + webserver/pages.py | 4 ++++ webserver/webserver.py | 39 ++++++++++++++++++++++++++------------- 4 files changed, 35 insertions(+), 17 deletions(-) diff --git a/background_installer.sh b/background_installer.sh index 99c1999..921b078 100755 --- a/background_installer.sh +++ b/background_installer.sh @@ -92,9 +92,9 @@ function install_py_deps { python3 -m venv "$VENV_DIR" "$VENV_DIR/bin/python3" -m pip install --upgrade pip if [ "$1" == "neuron" ]; then - "$VENV_DIR/bin/python3" -m pip install flask==2.2.5 werkzeug==2.2.2 flask-login==0.6.2 pyserial pymodbus==2.5.3 flask_jwt_extended flask_sqlalchemy python-dotenv + "$VENV_DIR/bin/python3" -m pip install flask==2.2.5 werkzeug==2.2.2 flask-login==0.6.2 pyserial pymodbus==2.5.3 Flask-WTF==1.2.2 flask_jwt_extended flask_sqlalchemy python-dotenv else - "$VENV_DIR/bin/python3" -m pip install flask==2.3.3 werkzeug==2.3.7 flask-login==0.6.2 pyserial pymodbus==2.5.3 flask_jwt_extended flask_sqlalchemy python-dotenv + "$VENV_DIR/bin/python3" -m pip install flask==2.3.3 werkzeug==2.3.7 flask-login==0.6.2 pyserial pymodbus==2.5.3 Flask-WTF==1.2.2 flask_jwt_extended flask_sqlalchemy python-dotenv fi python3 -m pip install pymodbus==2.5.3 } @@ -279,7 +279,7 @@ if [ "$1" == "win" ]; then #Setting up venv python3 -m venv "$VENV_DIR" "$VENV_DIR/bin/python3" get-pip3.py - "$VENV_DIR/bin/python3" -m pip install flask==2.3.3 werkzeug==2.3.7 flask-login==0.6.2 pyserial pymodbus==2.5.3 flask_jwt_extended flask_sqlalchemy python-dotenv + "$VENV_DIR/bin/python3" -m pip install flask==2.3.3 werkzeug==2.3.7 flask-login==0.6.2 pyserial pymodbus==2.5.3 Flask-WTF==1.2.2 flask_jwt_extended flask_sqlalchemy python-dotenv echo "" echo "[MATIEC COMPILER]" @@ -307,7 +307,7 @@ elif [ "$1" == "win_msys2" ]; then #Setting up venv python3 -m venv "$VENV_DIR" "$VENV_DIR/bin/python3" get-pip3.py - "$VENV_DIR/bin/python3" -m pip install flask==2.3.3 werkzeug==2.3.7 flask-login==0.6.2 pyserial pymodbus==2.5.3 flask_jwt_extended flask_sqlalchemy python-dotenv + "$VENV_DIR/bin/python3" -m pip install flask==2.3.3 werkzeug==2.3.7 flask-login==0.6.2 pyserial pymodbus==2.5.3 Flask-WTF==1.2.2 flask_jwt_extended flask_sqlalchemy python-dotenv echo "" echo "[MATIEC COMPILER]" diff --git a/requirements.txt b/requirements.txt index 06cfa7e..e465fcc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ Flask==1.0.2 Flask-Login==0.4.1 pyserial==3.4 pymodbus==2.2.0 +Flask-WTF==1.2.2 diff --git a/webserver/pages.py b/webserver/pages.py index a3f15f4..2372e49 100644 --- a/webserver/pages.py +++ b/webserver/pages.py @@ -129,6 +129,7 @@ login_head = """ login_body = """

Use your credentials to login

+ <<<>>>


@@ -1012,6 +1013,7 @@ add_user_tail = """ + <<<>>>

@@ -1177,6 +1179,7 @@ settings_tail = """


+ <<<>>>
@@ -1420,6 +1423,7 @@ hardware_tail = """

+ <<<>>>


diff --git a/webserver/webserver.py b/webserver/webserver.py index 3c582ea..f5f63bc 100644 --- a/webserver/webserver.py +++ b/webserver/webserver.py @@ -26,10 +26,14 @@ from credentials import CertGen from restapi import app_restapi, restapi_bp, db, register_callback_get, register_callback_post from dataclasses import dataclass, field from enum import Enum, auto +from flask_wtf import CSRFProtect +from flask_wtf.csrf import generate_csrf app = flask.Flask(__name__) app.secret_key = str(os.urandom(16)) +csrf = CSRFProtect(app) +csrf.init_app(app) login_manager = flask_login.LoginManager() login_manager.init_app(app) @@ -601,7 +605,7 @@ def index(): @app.route('/login', methods=['GET', 'POST']) def login(): if flask.request.method == 'GET': - return pages.login_head + pages.login_body + return (pages.login_head + pages.login_body).replace('<<<>>>', f"" ) username = flask.request.form['username'] password = flask.request.form['password'] @@ -626,9 +630,9 @@ def login(): flask_login.login_user(user) return flask.redirect(flask.url_for('dashboard')) else: - return pages.login_head + pages.bad_login_body + return (pages.login_head + pages.bad_login_body).replace('<<<>>>', f"" ) - return pages.login_head + pages.bad_login_body + return (pages.login_head + pages.bad_login_body).replace('<<<>>>', f"" ) except Error as e: print("error connecting to the database" + str(e)) @@ -788,6 +792,7 @@ def programs(): action = "upload-program" method = "post">
+ <<<>>> @@ -802,7 +807,7 @@ def programs(): else: return_str += 'Error connecting to the database. Make sure that your openplc.db file is not corrupt.' - return return_str + return return_str.replace('<<<>>>', f"" ) @app.route('/reload-program', methods=['GET', 'POST']) @@ -902,6 +907,7 @@ def update_program(): action = "update-program-action" method = "post">
+ <<<>>> @@ -914,7 +920,7 @@ def update_program(): """ - return return_str + return return_str.replace('<<<>>>', f"" ) @app.route('/update-program-action', methods=['GET', 'POST']) @@ -1024,7 +1030,9 @@ def upload_program(): method = "post" onsubmit = "return validateForm()"> + + <<<>>> """ @@ -1035,6 +1043,7 @@ def upload_program(): return_str += """

+ <<<>>>
@@ -1056,7 +1065,7 @@ def upload_program(): """ - return return_str + return return_str.replace('<<<>>>', f"" ) @app.route('/upload-program-action', methods=['GET', 'POST']) @@ -1237,6 +1246,7 @@ def modbus(): return_str += """
+ <<<>>>
Add new device
@@ -1250,7 +1260,7 @@ def modbus(): else: return_str += 'Error connecting to the database. Make sure that your openplc.db file is not corrupt.' - return return_str + return return_str.replace('<<<>>>', f"" ) @app.route('/add-modbus-device', methods=['GET', 'POST']) @@ -1291,6 +1301,7 @@ def add_modbus_device(): method = "post" onsubmit = "return validateForm()"> + <<<>>> " ) elif (flask.request.method == 'POST'): devname = flask.request.form.get('device_name') @@ -1701,7 +1712,7 @@ def monitoring(): """ - return return_str + return return_str.replace('<<<>>>', f"" ) @app.route('/monitor-update', methods=['GET', 'POST']) def monitor_update(): @@ -1946,7 +1957,7 @@ def hardware():

PSM is a powerful bridge that connects OpenPLC core to Python. You can use PSM to write your own OpenPLC driver in pure Python. See below for a sample driver that switches %IX0.0 every second