CVE-2014-8336: Improper Input Validation (CWE-20)
value: The "Sql Run Query" panel in WP-DBManager (aka Database Manager) plugin before 2.7.2 for WordPress allows remote attackers to read arbitrary files by leveraging failure to sufficiently limit queries, as demonstrated by use of LOAD_FILE in an INSERT statement.
CWE description: The product receives input or data, but it does
        not validate or incorrectly validates that the input has the
        properties that are required to process the data safely and
        correctly.
CVSS v3 base score: 6.5
Published: 2018-01-05T16:29Z
Repository: https://github.com/lesterchan/wp-dbmanager
Language: PHP
Files changed: README.md, database-backup.php, database-manage.php, database-run.php, wp-dbmanager.php
Commit date: 2014-10-16 12:08:01 +0800
Commit message: Uses escapeshellcmd() and do not allow LOAD_FILE inside queries

Diff: diff --git a/README.md b/README.md
index 0e7f4fc..86469f3 100644
--- a/README.md
+++ b/README.md
@@ -32,12 +32,14 @@ Allows you to optimize database, repair database, backup database, restore datab
 * If this is a concern to you, I recommend another database backup plugin called [WP-DB-Backup](https://wordpress.org/plugins/wp-db-backup/)
 * To know about the difference between WP-DBManager and WP-DB-backup, checkout __What is the difference between WP-DBManager and WP-DB-Backup?__ in the [FAQ section](https://wordpress.org/plugins/wp-dbmanager/faq/).
 
 ## Changelog
 ### Version 2.72
-* FIXED: Use dbmanager_is_valid_path() to check for mysql and mysqldump path. Fixes arbitrary command injection using backup path. Props Larry W. Cashdollari.
-* FIXED: Use realpath() to check for backup path. Fixes arbitrary command injection using backup path. Props Larry W. Cashdollari.
+* FIXED: Uses escapeshellcmd() to escape shell commands
+* FIXED: Do not allow LOAD_FILE to be run
+* FIXED: Uses dbmanager_is_valid_path() to check for mysql and mysqldump path. Fixes arbitrary command injection using backup path. Props Larry W. Cashdollari.
+* FIXED: Uses realpath() to check for backup path. Fixes arbitrary command injection using backup path. Props Larry W. Cashdollari.
 
 ### Version 2.71
 * NEW: Bump to 4.0
 
 ### Version 2.70
diff --git a/database-backup.php b/database-backup.php
index 115cf6a..23deb8c 100644
--- a/database-backup.php
+++ b/database-backup.php
@@ -40,15 +40,15 @@ if(!empty($_POST['do'])) {
 			}
 			$gzip = intval($_POST['gzip']);
 			if($gzip == 1) {
 				$backup['filename'] = $backup['date'].'_-_'.DB_NAME.'.sql.gz';
 				$backup['filepath'] = $backup['path'].'/'.$backup['filename'];
-				$backup['command'] = $brace.$backup['mysqldumppath'].$brace.' --force --host="'.$backup['host'].'" --user="'.DB_USER.'" --password="'.$backup['password'].'"'.$backup['port'].$backup['sock'].$backup['charset'].' --add-drop-table --skip-lock-tables '.DB_NAME.' | gzip > '.$brace.$backup['filepath'].$brace;
+				$backup['command'] = escapeshellcmd( $brace.$backup['mysqldumppath'].$brace.' --force --host="'.$backup['host'].'" --user="'.DB_USER.'" --password="'.$backup['password'].'"'.$backup['port'].$backup['sock'].$backup['charset'].' --add-drop-table --skip-lock-tables '.DB_NAME ).' | gzip > '.escapeshellcmd( $brace.$backup['filepath'].$brace );
 			} else {
 				$backup['filename'] = $backup['date'].'_-_'.DB_NAME.'.sql';
 				$backup['filepath'] = $backup['path'].'/'.$backup['filename'];
-				$backup['command'] = $brace.$backup['mysqldumppath'].$brace.' --force --host="'.$backup['host'].'" --user="'.DB_USER.'" --password="'.$backup['password'].'"'.$backup['port'].$backup['sock'].$backup['charset'].' --add-drop-table --skip-lock-tables '.DB_NAME.' > '.$brace.$backup['filepath'].$brace;
+				$backup['command'] = escapeshellcmd( $brace.$backup['mysqldumppath'].$brace.' --force --host="'.$backup['host'].'" --user="'.DB_USER.'" --password="'.$backup['password'].'"'.$backup['port'].$backup['sock'].$backup['charset'].' --add-drop-table --skip-lock-tables '.DB_NAME ).' > '.escapeshellcmd( $brace.$backup['filepath'].$brace );
 			}
 			$error = execute_backup($backup['command']);
 			if(!is_writable($backup['path'])) {
 				$text = '<p style="color: red;">'.sprintf(__('Database Failed To Backup On \'%s\'. Backup Folder Not Writable.', 'wp-dbmanager'), $current_date).'</p>';
 			} elseif(filesize($backup['filepath']) == 0) {
diff --git a/database-manage.php b/database-manage.php
index 14d08e7..a31dca2 100644
--- a/database-manage.php
+++ b/database-manage.php
@@ -42,13 +42,13 @@ if( !empty( $_POST['do'] ) ) {
 					} else {
 						$backup['sock'] = ' --socket="'.$db_host[1].'"';
 					}
 				}
 				if(stristr($database_file, '.gz')) {
-					$backup['command'] = 'gunzip < '.$brace.$backup['path'].'/'.$database_file.$brace.' | '.$brace.$backup['mysqlpath'].$brace.' --host="'.$backup['host'].'" --user="'.DB_USER.'" --password="'.$backup['password'].'"'.$backup['port'].$backup['sock'].$backup['charset'].' '.DB_NAME;
+					$backup['command'] = 'gunzip < '.escapeshellcmd( $brace.$backup['path'].'/'.$database_file.$brace ).' | '.escapeshellcmd( $brace.$backup['mysqlpath'].$brace.' --host="'.$backup['host'].'" --user="'.DB_USER.'" --password="'.$backup['password'].'"'.$backup['port'].$backup['sock'].$backup['charset'].' '.DB_NAME );
 				} else {
-					$backup['command'] = $brace.$backup['mysqlpath'].$brace.' --host="'.$backup['host'].'" --user="'.DB_USER.'" --password="'.$backup['password'].'"'.$backup['port'].$backup['sock'].$backup['charset'].' '.DB_NAME.' < '.$brace.$backup['path'].'/'.$database_file.$brace;
+					$backup['command'] = escapeshellcmd( $brace.$backup['mysqlpath'].$brace.' --host="'.$backup['host'].'" --user="'.DB_USER.'" --password="'.$backup['password'].'"'.$backup['port'].$backup['sock'].$backup['charset'].' '.DB_NAME ).' < '.escapeshellcmd( $brace.$backup['path'].'/'.$database_file.$brace );
 				}
 				if( realpath( $backup['path'] ) === false ) {
 					$text = '<p style="color: red;">' . sprintf(__('%s is not a valid backup path', 'wp-dbmanager'), stripslashes( $backup['path'] ) ) . '</p>';
 				} else if( dbmanager_is_valid_path( $backup['mysqlpath'] ) === 0 ) {
 					$text = '<p style="color: red;">' . sprintf(__('%s is not a valid mysql path', 'wp-dbmanager'), stripslashes( $backup['mysqlpath'] ) ) . '</p>';
diff --git a/database-run.php b/database-run.php
index 11a0557..7802532 100644
--- a/database-run.php
+++ b/database-run.php
@@ -35,23 +35,26 @@ if(!empty($_POST['do'])) {
 					if(!empty($sql_query2)) {
 						$sql_queries[] = $sql_query2;
 					}
 				}
 				if($sql_queries) {
-					foreach($sql_queries as $sql_query) {
-						if (preg_match("/^\\s*(insert|update|replace|delete|create|alter) /i",$sql_query)) {
-							$run_query = $wpdb->query($sql_query);
-							if(!$run_query) {
+					foreach( $sql_queries as $sql_query ) {
+						if ( preg_match( "/LOAD_FILE/i", $sql_query ) ) {
+							$text .= "<p style=\"color: red;\">$sql_query</p>";
+							$totalquerycount++;
+						} elseif( preg_match( "/^\\s*(select|drop|show|grant) /i", $sql_query ) ) {
+							$text .= "<p style=\"color: red;\">$sql_query</p>";
+							$totalquerycount++;
+						} else if ( preg_match( "/^\\s*(insert|update|replace|delete|create|alter) /i", $sql_query ) ) {
+							$run_query = $wpdb->query( $sql_query );
+							if( ! $run_query ) {
 								$text .= "<p style=\"color: red;\">$sql_query</p>";
 							} else {
 								$successquery++;
 								$text .= "<p style=\"color: green;\">$sql_query</p>";
 							}
 							$totalquerycount++;
-						} elseif (preg_match("/^\\s*(select|drop|show|grant) /i",$sql_query)) {
-							$text .= "<p style=\"color: red;\">$sql_query</p>";
-							$totalquerycount++;
 						}
 					}
 					$text .= '<p style="color: blue;">'.number_format_i18n($successquery).'/'.number_format_i18n($totalquerycount).' '.__('Query(s) Executed Successfully', 'wp-dbmanager').'</p>';
 				} else {
 					$text = '<p style="color: red;">'.__('Empty Query', 'wp-dbmanager').'</p>';
diff --git a/wp-dbmanager.php b/wp-dbmanager.php
index f006082..96f7392 100644
--- a/wp-dbmanager.php
+++ b/wp-dbmanager.php
@@ -58,11 +58,10 @@ function dbmanager_menu() {
 add_filter('cron_schedules', 'cron_dbmanager_reccurences');
 add_action('dbmanager_cron_backup', 'cron_dbmanager_backup');
 add_action('dbmanager_cron_optimize', 'cron_dbmanager_optimize');
 add_action('dbmanager_cron_repair', 'cron_dbmanager_repair');
 function cron_dbmanager_backup() {
-	global $wpdb;
 	$backup_options = get_option('dbmanager_options');
 	$backup_email = stripslashes($backup_options['backup_email']);
 	if(intval($backup_options['backup_period']) > 0) {
 		$backup = array();
 		$backup['date'] = current_time('timestamp');
@@ -85,18 +84,18 @@ function cron_dbmanager_backup() {
 		$backup['command'] = '';
 		$brace = (substr(PHP_OS, 0, 3) == 'WIN') ? '"' : '';
 		if(intval($backup_options['backup_gzip']) == 1) {
 			$backup['filename'] = $backup['date'].'_-_'.DB_NAME.'.sql.gz';
 			$backup['filepath'] = $backup['path'].'/'.$backup['filename'];
-			$backup['command'] = $brace.$backup['mysqldumppath'].$brace.' --force --host="'.$backup['host'].'" --user="'.DB_USER.'" --password="'.$backup['password'].'"'.$backup['port'].$backup['sock'].' --add-drop-table --skip-lock-tables '.DB_NAME.' | gzip > '.$brace.$backup['filepath'].$brace;
+			$backup['command'] = escapeshellcmd( $brace.$backup['mysqldumppath'].$brace.' --force --host="'.$backup['host'].'" --user="'.DB_USER.'" --password="'.$backup['password'].'"'.$backup['port'].$backup['sock'].' --add-drop-table --skip-lock-tables '.DB_NAME ). ' | gzip > '.escapeshellcmd( $brace.$backup['filepath'].$brace );
 		} else {
 			$backup['filename'] = $backup['date'].'_-_'.DB_NAME.'.sql';
 			$backup['filepath'] = $backup['path'].'/'.$backup['filename'];
-			$backup['command'] = $brace.$backup['mysqldumppath'].$brace.' --force --host="'.$backup['host'].'" --user="'.DB_USER.'" --password="'.$backup['password'].'"'.$backup['port'].$backup['sock'].' --add-drop-table --skip-lock-tables '.DB_NAME.' > '.$brace.$backup['filepath'].$brace;
+			$backup['command'] = escapeshellcmd( $brace.$backup['mysqldumppath'].$brace.' --force --host="'.$backup['host'].'" --user="'.DB_USER.'" --password="'.$backup['password'].'"'.$backup['port'].$backup['sock'].' --add-drop-table --skip-lock-tables '.DB_NAME ). ' > '.escapeshellcmd( $brace.$backup['filepath'].$brace );
 		}
 		execute_backup($backup['command']);
-		if( !empty( $backup_email ) )
+		if( ! empty( $backup_email ) )
 		{
 			dbmanager_email_backup( $backup_email, $backup['filepath'] );
 		}
 	}
 	return;
@@ -215,20 +214,20 @@ function execute_backup($command) {
 		return sprintf( __( '%s is not a valid mysqldump path', 'wp-dbmanager' ), stripslashes( $backup_options['mysqldumppath'] ) );
 	} else if( dbmanager_is_valid_path( $backup_options['mysqlpath'] ) === 0 ) {
 		return sprintf( __( '%s is not a valid mysql path', 'wp-dbmanager' ), stripslashes( $backup_options['mysqlpath'] ) );
 	}
 
-	if(substr(PHP_OS, 0, 3) == 'WIN') {
+	if( substr( PHP_OS, 0, 3 ) === 'WIN' ) {
 		$writable_dir = $backup_options['path'];
 		$tmpnam = $writable_dir.'/wp-dbmanager.bat';
-		$fp = fopen($tmpnam, 'w');
-		fwrite($fp, $command);
-		fclose($fp);
-		system($tmpnam.' > NUL', $error);
-		unlink($tmpnam);
+		$fp = fopen( $tmpnam, 'w' );
+		fwrite ($fp, $command );
+		fclose( $fp );
+		system( $tmpnam.' > NUL', $error );
+		unlink( $tmpnam );
 	} else {
-		passthru($command, $error);
+		passthru( $command, $error );
 	}
 	return $error;
 }
 
 ### Function: Check for valid file path

Vulnerable code: * FIXED: Use dbmanager_is_valid_path() to check for mysql and mysqldump path. Fixes arbitrary command injection using backup path. Props Larry W. Cashdollari.
* FIXED: Use realpath() to check for backup path. Fixes arbitrary command injection using backup path. Props Larry W. Cashdollari.
				$backup['command'] = $brace.$backup['mysqldumppath'].$brace.' --force --host="'.$backup['host'].'" --user="'.DB_USER.'" --password="'.$backup['password'].'"'.$backup['port'].$backup['sock'].$backup['charset'].' --add-drop-table --skip-lock-tables '.DB_NAME.' | gzip > '.$brace.$backup['filepath'].$brace;
				$backup['command'] = $brace.$backup['mysqldumppath'].$brace.' --force --host="'.$backup['host'].'" --user="'.DB_USER.'" --password="'.$backup['password'].'"'.$backup['port'].$backup['sock'].$backup['charset'].' --add-drop-table --skip-lock-tables '.DB_NAME.' > '.$brace.$backup['filepath'].$brace;
					$backup['command'] = 'gunzip < '.$brace.$backup['path'].'/'.$database_file.$brace.' | '.$brace.$backup['mysqlpath'].$brace.' --host="'.$backup['host'].'" --user="'.DB_USER.'" --password="'.$backup['password'].'"'.$backup['port'].$backup['sock'].$backup['charset'].' '.DB_NAME;
					$backup['command'] = $brace.$backup['mysqlpath'].$brace.' --host="'.$backup['host'].'" --user="'.DB_USER.'" --password="'.$backup['password'].'"'.$backup['port'].$backup['sock'].$backup['charset'].' '.DB_NAME.' < '.$brace.$backup['path'].'/'.$database_file.$brace;
					foreach($sql_queries as $sql_query) {
						if (preg_match("/^\\s*(insert|update|replace|delete|create|alter) /i",$sql_query)) {
							$run_query = $wpdb->query($sql_query);
							if(!$run_query) {
						} elseif (preg_match("/^\\s*(select|drop|show|grant) /i",$sql_query)) {
							$text .= "<p style=\"color: red;\">$sql_query</p>";
							$totalquerycount++;
	global $wpdb;
			$backup['command'] = $brace.$backup['mysqldumppath'].$brace.' --force --host="'.$backup['host'].'" --user="'.DB_USER.'" --password="'.$backup['password'].'"'.$backup['port'].$backup['sock'].' --add-drop-table --skip-lock-tables '.DB_NAME.' | gzip > '.$brace.$backup['filepath'].$brace;
			$backup['command'] = $brace.$backup['mysqldumppath'].$brace.' --force --host="'.$backup['host'].'" --user="'.DB_USER.'" --password="'.$backup['password'].'"'.$backup['port'].$backup['sock'].' --add-drop-table --skip-lock-tables '.DB_NAME.' > '.$brace.$backup['filepath'].$brace;
		if( !empty( $backup_email ) )
	if(substr(PHP_OS, 0, 3) == 'WIN') {
		$fp = fopen($tmpnam, 'w');
		fwrite($fp, $command);
		fclose($fp);
		system($tmpnam.' > NUL', $error);
		unlink($tmpnam);
		passthru($command, $error);
Fixed code: * FIXED: Uses escapeshellcmd() to escape shell commands
* FIXED: Do not allow LOAD_FILE to be run
* FIXED: Uses dbmanager_is_valid_path() to check for mysql and mysqldump path. Fixes arbitrary command injection using backup path. Props Larry W. Cashdollari.
* FIXED: Uses realpath() to check for backup path. Fixes arbitrary command injection using backup path. Props Larry W. Cashdollari.
				$backup['command'] = escapeshellcmd( $brace.$backup['mysqldumppath'].$brace.' --force --host="'.$backup['host'].'" --user="'.DB_USER.'" --password="'.$backup['password'].'"'.$backup['port'].$backup['sock'].$backup['charset'].' --add-drop-table --skip-lock-tables '.DB_NAME ).' | gzip > '.escapeshellcmd( $brace.$backup['filepath'].$brace );
				$backup['command'] = escapeshellcmd( $brace.$backup['mysqldumppath'].$brace.' --force --host="'.$backup['host'].'" --user="'.DB_USER.'" --password="'.$backup['password'].'"'.$backup['port'].$backup['sock'].$backup['charset'].' --add-drop-table --skip-lock-tables '.DB_NAME ).' > '.escapeshellcmd( $brace.$backup['filepath'].$brace );
					$backup['command'] = 'gunzip < '.escapeshellcmd( $brace.$backup['path'].'/'.$database_file.$brace ).' | '.escapeshellcmd( $brace.$backup['mysqlpath'].$brace.' --host="'.$backup['host'].'" --user="'.DB_USER.'" --password="'.$backup['password'].'"'.$backup['port'].$backup['sock'].$backup['charset'].' '.DB_NAME );
					$backup['command'] = escapeshellcmd( $brace.$backup['mysqlpath'].$brace.' --host="'.$backup['host'].'" --user="'.DB_USER.'" --password="'.$backup['password'].'"'.$backup['port'].$backup['sock'].$backup['charset'].' '.DB_NAME ).' < '.escapeshellcmd( $brace.$backup['path'].'/'.$database_file.$brace );
					foreach( $sql_queries as $sql_query ) {
						if ( preg_match( "/LOAD_FILE/i", $sql_query ) ) {
							$text .= "<p style=\"color: red;\">$sql_query</p>";
							$totalquerycount++;
						} elseif( preg_match( "/^\\s*(select|drop|show|grant) /i", $sql_query ) ) {
							$text .= "<p style=\"color: red;\">$sql_query</p>";
							$totalquerycount++;
						} else if ( preg_match( "/^\\s*(insert|update|replace|delete|create|alter) /i", $sql_query ) ) {
							$run_query = $wpdb->query( $sql_query );
							if( ! $run_query ) {
			$backup['command'] = escapeshellcmd( $brace.$backup['mysqldumppath'].$brace.' --force --host="'.$backup['host'].'" --user="'.DB_USER.'" --password="'.$backup['password'].'"'.$backup['port'].$backup['sock'].' --add-drop-table --skip-lock-tables '.DB_NAME ). ' | gzip > '.escapeshellcmd( $brace.$backup['filepath'].$brace );
			$backup['command'] = escapeshellcmd( $brace.$backup['mysqldumppath'].$brace.' --force --host="'.$backup['host'].'" --user="'.DB_USER.'" --password="'.$backup['password'].'"'.$backup['port'].$backup['sock'].' --add-drop-table --skip-lock-tables '.DB_NAME ). ' > '.escapeshellcmd( $brace.$backup['filepath'].$brace );
		if( ! empty( $backup_email ) )
	if( substr( PHP_OS, 0, 3 ) === 'WIN' ) {
		$fp = fopen( $tmpnam, 'w' );
		fwrite ($fp, $command );
		fclose( $fp );
		system( $tmpnam.' > NUL', $error );
		unlink( $tmpnam );
		passthru( $command, $error );