VYPR
High severityNVD Advisory· Published Mar 9, 2020· Updated Aug 4, 2024

CVE-2020-10235

CVE-2020-10235

Description

In Froxlor before 0.10.14, remote attackers with installation routine access achieve arbitrary code execution via unescaped database configuration options passed to exec().

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

In Froxlor before 0.10.14, remote attackers with installation routine access achieve arbitrary code execution via unescaped database configuration options passed to exec().

Vulnerability

Description

CVE-2020-10235 is a command injection vulnerability in Froxlor, a server administration panel. The issue resides in the installation routine, specifically within the _backupExistingDatabase function in install/lib/class.FroxlorInstall.php. Database configuration options, including the MySQL root password, were passed directly to the exec() function without proper escaping, allowing an attacker who can interact with the installer to inject arbitrary OS commands [1][2].

Exploitation

Exploitation requires access to the Froxlor installation routine, which is typically only available during initial setup or after a fresh installation if the configuration file is missing. An attacker with network access to the web installer can supply malicious values for database parameters (e.g., database name, username, or password). When the installer attempts to create a backup, the unescaped password is placed in a shell command built from user input, enabling command injection. The commit addressing this issue shows that escapeshellarg() was added around user-supplied values in the backup command, confirming the vulnerability [2][3].

Impact

Successful exploitation allows a remote attacker to execute arbitrary commands on the underlying server with the privileges of the web server process. This could lead to full compromise of the Froxlor installation, disclosure of sensitive data, or lateral movement within the hosting environment. The vulnerability has a CVSS v3.1 base score of 9.8 (Critical) due to low attack complexity, no privileges required, and no user interaction [1].

Mitigation

The vulnerability is patched in Froxlor version 0.10.14 and later. Users are strongly advised to upgrade immediately. The fix includes escaping database configuration inputs with escapeshellarg() and additional hardening of the userdata configuration file creation process [3]. If immediate upgrade is not possible, restricting access to the installation routine via network controls and ensuring the installer cannot be re-initiated post-setup can reduce exposure.

AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
froxlor/froxlorPackagist
< 0.10.140.10.14

Affected products

2

Patches

2
7e361274c5bf

forgot one escapeshellarg() and enhanced security on userdata.inc.php creation when installing

https://github.com/froxlor/froxlorMichael KaufmannMar 6, 2020via ghsa
1 file changed · +8 8
  • install/lib/class.FroxlorInstall.php+8 8 modified
    @@ -333,18 +333,18 @@ private function _createUserdataConf()
     
     		// test if we can store the userdata.inc.php in ../lib
     		$userdata_file = dirname(dirname(dirname(__FILE__))) . '/lib/userdata.inc.php';
    -		if ($fp = @fopen($userdata_file, 'w')) {
    -			$result = @fputs($fp, $userdata, strlen($userdata));
    +		if (@touch($userdata_file) && @chmod($userdata_file, 0400) && @is_writable($userdata_file)) {
    +			$fp = @fopen($userdata_file, 'w');
    +			@fputs($fp, $userdata, strlen($userdata));
     			@fclose($fp);
     			$content .= $this->_status_message('green', 'OK');
    -			chmod($userdata_file, 0440);
     		} else {
     			// try creating it in a temporary file
    -			$temp_file = tempnam(sys_get_temp_dir(), 'fx');
    -			if (touch($temp_file)) {
    +			$temp_file = @tempnam(sys_get_temp_dir(), 'fx');
    +			if ($temp_file) {
     				chmod($temp_file, 0400);
     				$fp = @fopen($temp_file, 'w');
    -				$result = @fputs($fp, $userdata, strlen($userdata));
    +				@fputs($fp, $userdata, strlen($userdata));
     				@fclose($fp);
     				$content .= $this->_status_message('orange', sprintf($this->_lng['install']['creating_configfile_temp'], $temp_file));
     			} else {
    @@ -568,7 +568,7 @@ private function _importDatabaseData()
     			for ($i = 0; $i < sizeof($sql_query); $i ++) {
     				if (trim($sql_query[$i]) != '') {
     					try {
    -						$result = $db->query($sql_query[$i]);
    +						$db->query($sql_query[$i]);
     					} catch (\PDOException $e) {
     						$content .= $this->_status_message('red', $e->getMessage());
     						$fatal_fail = true;
    @@ -735,7 +735,7 @@ private function _backupExistingDatabase(&$db_root)
     			}
     
     			if ($do_backup) {
    -				$command = $mysql_dump . " " . escapeshellarg($this->_data['mysql_database']) . " -u " . escapeshellarg($this->_data['mysql_root_user']) . " --password='" . $this->_data['mysql_root_pass'] . "' --result-file=" . $filename;
    +				$command = $mysql_dump . " " . escapeshellarg($this->_data['mysql_database']) . " -u " . escapeshellarg($this->_data['mysql_root_user']) . " --password='" . escapeshellarg($this->_data['mysql_root_pass']) . "' --result-file=" . $filename;
     				$output = exec($command);
     				if (stristr($output, "error")) {
     					$content .= $this->_status_message('red', $this->_lng['install']['backup_failed']);
    
62ce21c9ec39

secure shell-execution of mysqldump on installation if given database-name exists

https://github.com/froxlor/froxlorMichael KaufmannMar 4, 2020via ghsa
1 file changed · +1 1
  • install/lib/class.FroxlorInstall.php+1 1 modified
    @@ -735,7 +735,7 @@ private function _backupExistingDatabase(&$db_root)
     			}
     
     			if ($do_backup) {
    -				$command = $mysql_dump . " " . $this->_data['mysql_database'] . " -u " . $this->_data['mysql_root_user'] . " --password='" . $this->_data['mysql_root_pass'] . "' --result-file=" . $filename;
    +				$command = $mysql_dump . " " . escapeshellarg($this->_data['mysql_database']) . " -u " . escapeshellarg($this->_data['mysql_root_user']) . " --password='" . $this->_data['mysql_root_pass'] . "' --result-file=" . $filename;
     				$output = exec($command);
     				if (stristr($output, "error")) {
     					$content .= $this->_status_message('red', $this->_lng['install']['backup_failed']);
    

Vulnerability mechanics

Root cause

"Missing `escapeshellarg()` on the `mysql_root_pass` (and initially `mysql_database` and `mysql_root_user`) in `_backupExistingDatabase` allows OS command injection via the database configuration form."

Attack vector

An attacker who can reach the Froxlor installation routine (e.g., on a freshly deployed or not-yet-locked-down instance) supplies crafted values for database configuration fields such as `mysql_root_pass`, `mysql_root_user`, or `mysql_database`. These values are passed unescaped into a shell command executed via `exec()` in `_backupExistingDatabase` [CWE-78]. By injecting shell metacharacters (e.g., backticks, `$()`, or `;`) into the password field, the attacker can execute arbitrary OS commands under the privileges of the web server process. The attack requires network access to the installer and does not require prior authentication [ref_id=1].

Affected code

The vulnerability resides in the `_backupExistingDatabase` method within `install/lib/class.FroxlorInstall.php`. In the pre-patch version, the `mysql_root_pass` value from the installation form was interpolated directly into a shell command string without escaping, while `mysql_database` and `mysql_root_user` were also unescaped in the earlier commit [patch_id=1703319]. The `_createUserdataConf` method also had related hardening for file permissions [patch_id=1703320].

What the fix does

Patch [patch_id=1703319] wraps `$this->_data['mysql_database']` and `$this->_data['mysql_root_user']` with `escapeshellarg()`, which was already applied to the database name but missing for the user. Patch [patch_id=1703320] additionally wraps `$this->_data['mysql_root_pass']` with `escapeshellarg()` inside the `--password='...'` argument, closing the injection vector. The same commit also hardens `_createUserdataConf` by using `touch()` + `chmod(0400)` before writing the config file and removing the unused `$result` variable, reducing the risk of information disclosure or file-based attacks [CWE-20].

Preconditions

  • networkAttacker must have network access to the Froxlor installation routine (e.g., the /froxlor installer is reachable)
  • configThe Froxlor instance must be running a version before 0.10.14
  • authNo authentication is required; the installation routine is publicly accessible

Generated on May 23, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.