CVE-2021-4301: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection') (CWE-89)
value: A vulnerability was found in slackero phpwcms up to 1.9.26 and classified as critical. Affected by this issue is some unknown functionality. The manipulation of the argument $phpwcms['db_prepend'] leads to sql injection. The attack may be launched remotely. Upgrading to version 1.9.27 is able to address this issue. The patch is identified as 77dafb6a8cc1015f0777daeb5792f43beef77a9d. It is recommended to upgrade the affected component. VDB-217418 is the identifier assigned to this vulnerability.
CWE description: The product constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component. Without sufficient removal or quoting of SQL syntax in user-controllable inputs, the generated SQL query can cause those inputs to be interpreted as SQL instead of ordinary user data.
CVSS v3 base score: 9.8
Published: 2023-01-07T22:15Z
Repository: https://github.com/slackero/phpwcms
Language: PHP
Files changed: include/inc_lib/dbcon.inc.php, include/inc_lib/revision/revision.php, setup/inc/setup.check.inc.php, setup/inc/step0.inc.php, setup/inc/step1.inc.php, setup/inc/step2.inc.php, setup/inc/step3.inc.php, setup/inc/step4.inc.php, setup/inc/step5.inc.php
Commit date: 2021-08-22 07:49:58 +0200
Commit message: Prevent $phpwcms['db_prepend'] from SQL injection

Diff: diff --git a/include/inc_lib/dbcon.inc.php b/include/inc_lib/dbcon.inc.php
index f4a69f423..7566ad215 100644
--- a/include/inc_lib/dbcon.inc.php
+++ b/include/inc_lib/dbcon.inc.php
@@ -14,15 +14,11 @@
 if (!defined('PHPWCMS_ROOT')) {
     die("You Cannot Access This Script Directly, Have a Nice Day.");
 }
 // ----------------------------------------------------------------
 
-// build the database table prepend part
-define ('DB_PREPEND', empty($GLOBALS['phpwcms']["db_prepend"]) ? '' : $GLOBALS['phpwcms']["db_prepend"].'_');
-
-// Log DB errors
-define ('DB_LOG_ERRORS', empty($GLOBALS['phpwcms']["db_errorlog"]) ? false : true);
+define('DB_LOG_ERRORS', empty($GLOBALS['phpwcms']["db_errorlog"]) ? false : true);
 
 // open the connection to MySQL database
 if(!empty($GLOBALS['phpwcms']["db_pers"]) && substr($GLOBALS['phpwcms']["db_host"], 0, 2) !== 'p:') {
     $GLOBALS['phpwcms']["db_host"] = 'p:'.$GLOBALS['phpwcms']["db_host"];
 }
@@ -35,23 +31,28 @@ if($is_mysql_error === false) {
 
     // set DB to compatible mode
     // for compatibility issues try to check for MySQL version and charset
     $GLOBALS['phpwcms']['db_version'] = _dbInitialize();
     define('PHPWCMS_DB_VERSION', $GLOBALS['phpwcms']['db_version']);
+    define('DB_PREPEND', empty($GLOBALS['phpwcms']["db_prepend"]) ? '' : mysqli_real_escape_string($GLOBALS['db'], $GLOBALS['phpwcms']["db_prepend"]) . '_');
 
 } elseif($is_mysql_error !== 'dbdown.php') {
 
     headerRedirect(PHPWCMS_URL.'dbdown.php', 503, false); // keep session
 
 } else {
 
     define('PHPWCMS_DB_VERSION', $GLOBALS['phpwcms']['db_version']);
+    define('DB_PREPEND', empty($GLOBALS['phpwcms']["db_prepend"]) ? '' : aporeplace($GLOBALS['phpwcms']["db_prepend"]) . '_');
 
 }
 
 // deprecated function for escaping db items
 function aporeplace($value='') {
+    if (!$GLOBALS['db']) {
+        return str_replace(array("\\", "\x00", "\n", "\r", "'",  '"', "\x1a"), array("\\\\", "\\0", "\\n", "\\r", "\'", '\"', "\\Z"), $value);
+    }
     return mysqli_real_escape_string($GLOBALS['db'], $value);
 }
 
 function _dbSelect($db_table='') {
 
diff --git a/include/inc_lib/revision/revision.php b/include/inc_lib/revision/revision.php
index 298101b2e..4e7bd0d4b 100644
--- a/include/inc_lib/revision/revision.php
+++ b/include/inc_lib/revision/revision.php
@@ -8,7 +8,7 @@
  * @link http://www.phpwcms.org
  *
  **/
 
 define('PHPWCMS_VERSION', '1.9.27-dev');
-define('PHPWCMS_RELEASE_DATE', '2021/08/19');
+define('PHPWCMS_RELEASE_DATE', '2021/08/22');
 define('PHPWCMS_REVISION', '552');
diff --git a/setup/inc/setup.check.inc.php b/setup/inc/setup.check.inc.php
index 5a3d89a08..eab89255e 100644
--- a/setup/inc/setup.check.inc.php
+++ b/setup/inc/setup.check.inc.php
@@ -1,6 +1,19 @@
 <?php
+/**
+ * phpwcms content management system
+ *
+ * @author Oliver Georgi <og@phpwcms.org>
+ * @copyright Copyright (c) 2002-2021, Oliver Georgi
+ * @license http://opensource.org/licenses/GPL-2.0 GNU GPL-2
+ * @link http://www.phpwcms.org
+ *
+ **/
+
+if (!defined('PHP8')) {
+    die("You Cannot Access This Script Directly, Have a Nice Day.");
+}
 
 if(!empty($step)) {
 
     if ($step == 1 && $do) {
 
@@ -83,11 +96,11 @@ if(!empty($step)) {
 
                     }
 
                     mysqli_free_result($result);
 
-                    if($result = mysqli_query($db, 'SELECT * FROM '. ($phpwcms["db_prepend"] ? $phpwcms["db_prepend"].'_' : '').'phpwcms_user')) {
+                    if($result = mysqli_query($db, 'SELECT * FROM '. ($phpwcms["db_prepend"] ? mysqli_real_escape_string($db, $phpwcms["db_prepend"]) . '_' : '') . 'phpwcms_user')) {
 
                         $_db_prepend_error = true;
                         mysqli_free_result($result);
 
                     }
@@ -126,11 +139,11 @@ if(!empty($step)) {
 
                         } else {
 
                             // now read and display sql queries
 
-                            $_db_prepend = ($phpwcms["db_prepend"] ? $phpwcms["db_prepend"].'_' : '');
+                            $_db_prepend = $phpwcms["db_prepend"] ? mysqli_real_escape_string($db, $phpwcms["db_prepend"]) . '_' : '';
 
                             $sql_data = read_textfile($DOCROOT . '/setup/default_sql/phpwcms_init.sql');
                             $sql_data = $sql_data . read_textfile($DOCROOT . '/setup/default_sql/phpwcms_inserts.sql');
                             $sql_data = preg_replace("/(#|--).*.\n/", '', $sql_data );
                             $sql_data = preg_replace('/ `phpwcms/', ' `'.$_db_prepend.'phpwcms', $sql_data );
@@ -217,12 +230,12 @@ if(!empty($step)) {
             if(mysqli_connect_error()) {
                 $err = 1;
             } else {
                 mysqli_query($db, "SET SQL_MODE=NO_AUTO_VALUE_ON_ZERO,NO_ENGINE_SUBSTITUTION");
                 mysqli_query($db, "SET NAMES '".mysqli_real_escape_string($db, $phpwcms["charset"])."'");
-                $phpwcms["db_prepend"] = ($phpwcms["db_prepend"]) ? $phpwcms["db_prepend"]."_" : "";
-                $sql =  "INSERT INTO ".$phpwcms["db_prepend"]."phpwcms_user (usr_login, usr_pass, usr_email, ".
+                $_db_prepend = $phpwcms["db_prepend"] ? mysqli_real_escape_string($db, $phpwcms["db_prepend"]) . "_" : "";
+                $sql =  "INSERT INTO " . $_db_prepend . "phpwcms_user (usr_login, usr_pass, usr_email, ".
                         "usr_admin, usr_aktiv, usr_name, usr_fe, usr_wysiwyg ) VALUES ('".
                         mysqli_real_escape_string($db, $phpwcms["admin_user"])."', '".
                         mysqli_real_escape_string($db, md5($phpwcms["admin_pass"]))."', '".
                         mysqli_real_escape_string($db, $phpwcms["admin_email"])."', 1, 1, '".
                         mysqli_real_escape_string($db, $phpwcms['SMTP_FROM_NAME'])."', 2, 2)";
diff --git a/setup/inc/step0.inc.php b/setup/inc/step0.inc.php
index 728fabbf3..c2c9107cd 100644
--- a/setup/inc/step0.inc.php
+++ b/setup/inc/step0.inc.php
@@ -7,10 +7,14 @@
  * @license http://opensource.org/licenses/GPL-2.0 GNU GPL-2
  * @link http://www.phpwcms.org
  *
  **/
 
+if (!defined('PHP8')) {
+    die("You Cannot Access This Script Directly, Have a Nice Day.");
+}
+
 $_SESSION['admin_set'] = false;
 $setup_recommend = true;
 
 ?>
     <h1><span class="number">1.</span> Thanks! You have agreed to the GPL.</h1>
diff --git a/setup/inc/step1.inc.php b/setup/inc/step1.inc.php
index 327864430..7b2ffd9ea 100644
--- a/setup/inc/step1.inc.php
+++ b/setup/inc/step1.inc.php
@@ -7,10 +7,14 @@
  * @license http://opensource.org/licenses/GPL-2.0 GNU GPL-2
  * @link http://www.phpwcms.org
  *
  **/
 
+if (!defined('PHP8')) {
+    die("You Cannot Access This Script Directly, Have a Nice Day.");
+}
+
 ?>
 <h1><span class="number">3.</span> MySQL database settings </h1>
 <?php
 if(isset($_POST["dbsavesubmit"]) && $err) {
     echo errorWarning('Please proof your database settings!');
@@ -140,18 +144,18 @@ if(!empty($db_init)) {
         $db_sql                 = false;
 
     } elseif(isset($db_create_err) || !empty($db_no_create)) {
 
         // OK fine - initial tables were created without error
-        $_db_prepend = ($phpwcms["db_prepend"] ? $phpwcms["db_prepend"].'_' : '');
+        $_db_prepend = $phpwcms["db_prepend"] ? mysqli_real_escape_string($db, $phpwcms["db_prepend"]) . '_' : '';
         $check = _dbQuery("SHOW TABLES LIKE '".$_db_prepend."phpwcms_%'");
 
         if($check && count($check)) {
 
-            $sql_data               = false;
-            $db_sql                 = false;
-            $db_fine                = true;
+            $sql_data   = false;
+            $db_sql     = false;
+            $db_fine    = true;
 
 ?>
       <tr>
         <td align="right" class="v10">&nbsp;</td>
         <td colspan="2"><img src="../img/famfamfam/icon_accept.gif" alt="Juchu" class="icon1" /><strong>Fine!</strong> All initial phpwcms tables were created or still exists.<input type="hidden" name="db_sql_hidden" value="1" /></td>
@@ -303,11 +307,11 @@ if(!empty($_SESSION['admin_set'])) {
     </tr>
 <?php
 
     } else {
 
-        $_db_prepend = ($phpwcms["db_prepend"] ? $phpwcms["db_prepend"].'_' : '');
+        $_db_prepend = $phpwcms["db_prepend"] ? mysqli_real_escape_string($db, $phpwcms["db_prepend"]) . '_' : '';
 
         //show Info that admin info was saved
         //and also if stored in database
 
         $user_check = _dbQuery('SELECT * FROM '.$_db_prepend."phpwcms_user WHERE usr_login='".mysqli_real_escape_string($db, $phpwcms['admin_user'])."'");
diff --git a/setup/inc/step2.inc.php b/setup/inc/step2.inc.php
index df740a0bf..4c7d439ea 100644
--- a/setup/inc/step2.inc.php
+++ b/setup/inc/step2.inc.php
@@ -7,10 +7,14 @@
  * @license http://opensource.org/licenses/GPL-2.0 GNU GPL-2
  * @link http://www.phpwcms.org
  *
  **/
 
+if (!defined('PHP8')) {
+    die("You Cannot Access This Script Directly, Have a Nice Day.");
+}
+
 if ($err) {
     echo '<p class="error"><b>Check your admin user name and password!</b></p>';
 }
 
 ?>
diff --git a/setup/inc/step3.inc.php b/setup/inc/step3.inc.php
index 5ee82d8a6..a51729375 100644
--- a/setup/inc/step3.inc.php
+++ b/setup/inc/step3.inc.php
@@ -7,10 +7,14 @@
  * @license http://opensource.org/licenses/GPL-2.0 GNU GPL-2
  * @link http://www.phpwcms.org
  *
  **/
 
+if (!defined('PHP8')) {
+    die("You Cannot Access This Script Directly, Have a Nice Day.");
+}
+
 ?>
 <p class="title">phpwcms path settings </p>
 <p>Please check that any path value does NOT begin or end with a slash. I recommend
   to use the default values. It's the best way for 1st time
   usage.</p>
diff --git a/setup/inc/step4.inc.php b/setup/inc/step4.inc.php
index a3295debf..adf9cbabe 100644
--- a/setup/inc/step4.inc.php
+++ b/setup/inc/step4.inc.php
@@ -7,10 +7,14 @@
  * @license http://opensource.org/licenses/GPL-2.0 GNU GPL-2
  * @link http://www.phpwcms.org
  *
  **/
 
+if (!defined('PHP8')) {
+    die("You Cannot Access This Script Directly, Have a Nice Day.");
+}
+
 ?><p class="title">phpwcms content values</p>
 <form action="setup.php?step=4" method="post"><table border="0" cellpadding="0" cellspacing="0" summary="">
           <tr>
             <td align="right" class="v10">&nbsp;</td>
             <td colspan="2" class="chatlist">this is the max size of files can
diff --git a/setup/inc/step5.inc.php b/setup/inc/step5.inc.php
index aaa9adceb..e1748d49a 100644
--- a/setup/inc/step5.inc.php
+++ b/setup/inc/step5.inc.php
@@ -7,10 +7,13 @@
  * @license http://opensource.org/licenses/GPL-2.0 GNU GPL-2
  * @link http://www.phpwcms.org
  *
  **/
 
+if (!defined('PHP8')) {
+    die("You Cannot Access This Script Directly, Have a Nice Day.");
+}
 
 $_SERVER['DOCUMENT_ROOT'] = $phpwcms['DOC_ROOT'];
 $phpwcms["root"] = !empty($phpwcms["root"]) ? "/".$phpwcms["root"] : "";
 
 ?>

Vulnerable code: // build the database table prepend part
define ('DB_PREPEND', empty($GLOBALS['phpwcms']["db_prepend"]) ? '' : $GLOBALS['phpwcms']["db_prepend"].'_');

// Log DB errors
define ('DB_LOG_ERRORS', empty($GLOBALS['phpwcms']["db_errorlog"]) ? false : true);
define('PHPWCMS_RELEASE_DATE', '2021/08/19');
                    if($result = mysqli_query($db, 'SELECT * FROM '. ($phpwcms["db_prepend"] ? $phpwcms["db_prepend"].'_' : '').'phpwcms_user')) {
                            $_db_prepend = ($phpwcms["db_prepend"] ? $phpwcms["db_prepend"].'_' : '');
                $phpwcms["db_prepend"] = ($phpwcms["db_prepend"]) ? $phpwcms["db_prepend"]."_" : "";
                $sql =  "INSERT INTO ".$phpwcms["db_prepend"]."phpwcms_user (usr_login, usr_pass, usr_email, ".
        $_db_prepend = ($phpwcms["db_prepend"] ? $phpwcms["db_prepend"].'_' : '');
            $sql_data               = false;
            $db_sql                 = false;
            $db_fine                = true;
        $_db_prepend = ($phpwcms["db_prepend"] ? $phpwcms["db_prepend"].'_' : '');
Fixed code: define('DB_LOG_ERRORS', empty($GLOBALS['phpwcms']["db_errorlog"]) ? false : true);
    define('DB_PREPEND', empty($GLOBALS['phpwcms']["db_prepend"]) ? '' : mysqli_real_escape_string($GLOBALS['db'], $GLOBALS['phpwcms']["db_prepend"]) . '_');
    define('DB_PREPEND', empty($GLOBALS['phpwcms']["db_prepend"]) ? '' : aporeplace($GLOBALS['phpwcms']["db_prepend"]) . '_');
    if (!$GLOBALS['db']) {
        return str_replace(array("\\", "\x00", "\n", "\r", "'",  '"', "\x1a"), array("\\\\", "\\0", "\\n", "\\r", "\'", '\"', "\\Z"), $value);
    }
define('PHPWCMS_RELEASE_DATE', '2021/08/22');
/**
 * phpwcms content management system
 *
 * @author Oliver Georgi <og@phpwcms.org>
 * @copyright Copyright (c) 2002-2021, Oliver Georgi
 * @license http://opensource.org/licenses/GPL-2.0 GNU GPL-2
 * @link http://www.phpwcms.org
 *
 **/

if (!defined('PHP8')) {
    die("You Cannot Access This Script Directly, Have a Nice Day.");
}
                    if($result = mysqli_query($db, 'SELECT * FROM '. ($phpwcms["db_prepend"] ? mysqli_real_escape_string($db, $phpwcms["db_prepend"]) . '_' : '') . 'phpwcms_user')) {
                            $_db_prepend = $phpwcms["db_prepend"] ? mysqli_real_escape_string($db, $phpwcms["db_prepend"]) . '_' : '';
                $_db_prepend = $phpwcms["db_prepend"] ? mysqli_real_escape_string($db, $phpwcms["db_prepend"]) . "_" : "";
                $sql =  "INSERT INTO " . $_db_prepend . "phpwcms_user (usr_login, usr_pass, usr_email, ".
if (!defined('PHP8')) {
    die("You Cannot Access This Script Directly, Have a Nice Day.");
}

if (!defined('PHP8')) {
    die("You Cannot Access This Script Directly, Have a Nice Day.");
}

        $_db_prepend = $phpwcms["db_prepend"] ? mysqli_real_escape_string($db, $phpwcms["db_prepend"]) . '_' : '';
            $sql_data   = false;
            $db_sql     = false;
            $db_fine    = true;
        $_db_prepend = $phpwcms["db_prepend"] ? mysqli_real_escape_string($db, $phpwcms["db_prepend"]) . '_' : '';
if (!defined('PHP8')) {
    die("You Cannot Access This Script Directly, Have a Nice Day.");
}

if (!defined('PHP8')) {
    die("You Cannot Access This Script Directly, Have a Nice Day.");
}

if (!defined('PHP8')) {
    die("You Cannot Access This Script Directly, Have a Nice Day.");
}

if (!defined('PHP8')) {
    die("You Cannot Access This Script Directly, Have a Nice Day.");
}