CVE-2024-21645: Improper Neutralization of Special Elements in Output Used by a Downstream Component ('Injection') (CWE-74)
value: pyLoad is the free and open-source Download Manager written in pure Python. A log injection vulnerability was identified in `pyload` allowing any unauthenticated actor to inject arbitrary messages into the logs gathered by `pyload`. Forged or otherwise, corrupted log files can be used to cover an attacker’s tracks or even to implicate another party in the commission of a malicious act. This vulnerability has been patched in version 0.5.0b3.dev77.

CWE description: The product constructs all or part of a command, data structure, or record using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify how it is parsed or interpreted when it is sent to a downstream component.
CVSS v3 base score: 5.3
Published: 2024-01-08T14:15Z
Repository: https://github.com/pyload/pyload
Language: Python
Files changed: src/pyload/webui/app/blueprints/api_blueprint.py, src/pyload/webui/app/blueprints/app_blueprint.py
Commit date: 2024-01-06 02:37:41 +0200
Commit message: fix GHSA-ghmw-rwh8-6qmr security advisory

Diff: diff --git a/src/pyload/webui/app/blueprints/api_blueprint.py b/src/pyload/webui/app/blueprints/api_blueprint.py
index fca23ab457..02dc3e3697 100644
--- a/src/pyload/webui/app/blueprints/api_blueprint.py
+++ b/src/pyload/webui/app/blueprints/api_blueprint.py
@@ -84,16 +84,17 @@ def login():
     password = flask.request.form["password"]
 
     api = flask.current_app.config["PYLOAD_API"]
     user_info = api.check_auth(user, password)
 
+    sanitized_user = user.replace("\n", "\\n").replace("\r", "\\r")
     if not user_info:
-        log.error(f"Login failed for user '{user}'")
+        log.error(f"Login failed for user '{sanitized_user}'")
         return jsonify(False)
 
     s = set_session(user_info)
-    log.info(f"User '{user}' successfully logged in")
+    log.info(f"User '{sanitized_user}' successfully logged in")
     flask.flash("Logged in successfully")
 
     return jsonify(s)
 
 
diff --git a/src/pyload/webui/app/blueprints/app_blueprint.py b/src/pyload/webui/app/blueprints/app_blueprint.py
index 4d5a4ffc29..0a973b97fb 100644
--- a/src/pyload/webui/app/blueprints/app_blueprint.py
+++ b/src/pyload/webui/app/blueprints/app_blueprint.py
@@ -52,16 +52,17 @@ def login():
     if flask.request.method == "POST":
         user = flask.request.form["username"]
         password = flask.request.form["password"]
         user_info = api.check_auth(user, password)
 
+        sanitized_user = user.replace("\n", "\\n").replace("\r", "\\r")
         if not user_info:
-            log.error(f"Login failed for user '{user}'")
+            log.error(f"Login failed for user '{sanitized_user}'")
             return render_template("login.html", next=next, errors=True)
 
         set_session(user_info)
-        log.info(f"User '{user}' successfully logged in")
+        log.info(f"User '{sanitized_user}' successfully logged in")
         flask.flash("Logged in successfully")
 
     if is_authenticated():
         return flask.redirect(next)
 

Vulnerable code:         log.error(f"Login failed for user '{user}'")
    log.info(f"User '{user}' successfully logged in")
            log.error(f"Login failed for user '{user}'")
        log.info(f"User '{user}' successfully logged in")
Fixed code:     sanitized_user = user.replace("\n", "\\n").replace("\r", "\\r")
        log.error(f"Login failed for user '{sanitized_user}'")
    log.info(f"User '{sanitized_user}' successfully logged in")
        sanitized_user = user.replace("\n", "\\n").replace("\r", "\\r")
            log.error(f"Login failed for user '{sanitized_user}'")
        log.info(f"User '{sanitized_user}' successfully logged in")