CVE-2024-34070: Insufficient Information (NVD-CWE-noinfo)
value: Froxlor is open source server administration software. Prior to 2.1.9, a Stored Blind Cross-Site Scripting (XSS) vulnerability was identified in the Failed Login Attempts Logging Feature of the Froxlor Application. An unauthenticated User can inject malicious scripts in the loginname parameter on the Login attempt, which will then be executed when viewed by the Administrator in the System Logs.  By exploiting this vulnerability, the attacker can perform various malicious actions such as forcing the Administrator to execute actions without their knowledge or consent. For instance, the attacker can force the Administrator to add a new administrator controlled by the attacker, thereby giving the attacker full control over the application. This vulnerability is fixed in 2.1.9.

CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
Published: 2024-05-14T15:38Z
Repository: https://github.com/froxlor/Froxlor
Language: PHP
Files changed: index.php, lib/Froxlor/Api/Commands/SysLog.php, lib/Froxlor/FroxlorLogger.php
Commit date: 2024-05-03 07:56:40 +0200
Commit message: Merge pull request from GHSA-x525-54hf-xr53

* do not log unvalidated user-input to mysql-log (if enabled)

Signed-off-by: Michael Kaufmann <d00p@froxlor.org>

* clean log-text to only allow a subset of special characters

Signed-off-by: Michael Kaufmann <d00p@froxlor.org>

* clean log-text when selecting from database to avoid possible previously added malicious entries

Signed-off-by: Michael Kaufmann <d00p@froxlor.org>

---------

Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
Diff: diff --git a/index.php b/index.php
index 5cccab8f..d7754ffa 100644
--- a/index.php
+++ b/index.php
@@ -246,11 +246,11 @@ if ($action == '2fa_entercode') {
 			} else {
 				// Log failed login
 				$rstlog = FroxlorLogger::getInstanceOf([
 					'loginname' => $_SERVER['REMOTE_ADDR']
 				]);
-				$rstlog->logAction(FroxlorLogger::LOGIN_ACTION, LOG_WARNING, "Unknown user '" . $loginname . "' tried to login.");
+				$rstlog->logAction(FroxlorLogger::LOGIN_ACTION, LOG_WARNING, "Unknown user tried to login.");
 
 				Response::redirectTo('index.php', [
 					'showmessage' => '2'
 				]);
 				exit();
@@ -303,11 +303,11 @@ if ($action == '2fa_entercode') {
 
 			// Log failed login
 			$rstlog = FroxlorLogger::getInstanceOf([
 				'loginname' => $_SERVER['REMOTE_ADDR']
 			]);
-			$rstlog->logAction(FroxlorLogger::LOGIN_ACTION, LOG_WARNING, "User '" . $loginname . "' tried to login with wrong password.");
+			$rstlog->logAction(FroxlorLogger::LOGIN_ACTION, LOG_WARNING, "User tried to login with wrong password.");
 
 			unset($userinfo);
 			Response::redirectTo('index.php', [
 				'showmessage' => '2'
 			]);
@@ -622,11 +622,11 @@ if ($action == 'forgotpwd') {
 							exit();
 						} else {
 							$rstlog = FroxlorLogger::getInstanceOf([
 								'loginname' => 'password_reset'
 							]);
-							$rstlog->logAction(FroxlorLogger::USR_ACTION, LOG_WARNING, "User '" . $loginname . "' requested to set a new password, but was not found in database!");
+							$rstlog->logAction(FroxlorLogger::USR_ACTION, LOG_WARNING, "Unknown user requested to set a new password, but was not found in database!");
 							$message = lng('login.usernotfound');
 						}
 
 						unset($user);
 					}
diff --git a/lib/Froxlor/Api/Commands/SysLog.php b/lib/Froxlor/Api/Commands/SysLog.php
index 9236d577..2df7d1a1 100644
--- a/lib/Froxlor/Api/Commands/SysLog.php
+++ b/lib/Froxlor/Api/Commands/SysLog.php
@@ -88,10 +88,12 @@ class SysLog extends ApiCommand implements ResourceEntity
 			WHERE `user` = :loginname AND `action` <> 99 " . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
 			$query_fields['loginname'] = $this->getUserDetail('loginname');
 		}
 		Database::pexecute($result_stmt, $query_fields, true, true);
 		while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
+			// clean log-text
+			$row['text'] = preg_replace("/[^\w @#\"':.()\[\]+\-_\/\\\!]/i", "_", $row['text']);
 			$result[] = $row;
 		}
 		$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] list log-entries");
 		return $this->response([
 			'count' => count($result),
diff --git a/lib/Froxlor/FroxlorLogger.php b/lib/Froxlor/FroxlorLogger.php
index 2ca02aeb..6eeadf7f 100644
--- a/lib/Froxlor/FroxlorLogger.php
+++ b/lib/Froxlor/FroxlorLogger.php
@@ -173,10 +173,13 @@ class FroxlorLogger
 
 		if (empty(self::$ml)) {
 			$this->initMonolog();
 		}
 
+		// clean log-text
+		$text = preg_replace("/[^\w @#\"':.()\[\]+\-_\/\\\!]/i", "_", $text);
+
 		if (self::$crondebug_flag || ($action == FroxlorLogger::CRON_ACTION && $type <= LOG_WARNING)) {
 			echo "[" . $this->getLogLevelDesc($type) . "] " . $text . PHP_EOL;
 		}
 
 		// warnings, errors and critical messages WILL be logged

Vulnerable code: 				$rstlog->logAction(FroxlorLogger::LOGIN_ACTION, LOG_WARNING, "Unknown user '" . $loginname . "' tried to login.");
			$rstlog->logAction(FroxlorLogger::LOGIN_ACTION, LOG_WARNING, "User '" . $loginname . "' tried to login with wrong password.");
							$rstlog->logAction(FroxlorLogger::USR_ACTION, LOG_WARNING, "User '" . $loginname . "' requested to set a new password, but was not found in database!");
Fixed code: 				$rstlog->logAction(FroxlorLogger::LOGIN_ACTION, LOG_WARNING, "Unknown user tried to login.");
			$rstlog->logAction(FroxlorLogger::LOGIN_ACTION, LOG_WARNING, "User tried to login with wrong password.");
							$rstlog->logAction(FroxlorLogger::USR_ACTION, LOG_WARNING, "Unknown user requested to set a new password, but was not found in database!");
			// clean log-text
			$row['text'] = preg_replace("/[^\w @#\"':.()\[\]+\-_\/\\\!]/i", "_", $row['text']);
		// clean log-text
		$text = preg_replace("/[^\w @#\"':.()\[\]+\-_\/\\\!]/i", "_", $text);