CVE-2016-7565: Improper Access Control (CWE-284)
value: install/index.php in Exponent CMS 2.3.9 allows remote attackers to execute arbitrary commands via shell metacharacters in the sc array parameter.
CWE description: The product does not restrict or incorrectly restricts access to a resource from an unauthorized actor.
CVSS v3 base score: 9.8
Published: 2017-02-13T18:59Z
Repository: https://github.com/exponentcms/exponent-cms
Language: PHP
Files changed: install/index.php
Commit date: 2016-09-21 21:00:30 -0400
Commit message: security fix to prevent possible hacking by moving security checks earlier in the install code

Diff: diff --git a/install/index.php b/install/index.php
index a638a5151f..0e440ab2d7 100644
--- a/install/index.php
+++ b/install/index.php
@@ -27,11 +27,10 @@ if (version_compare(PHP_VERSION, '5.3.1', 'lt')) {
     die();
 }
 
 ob_start();
 
-
 // Jumpstart to Initialize the installer language before it's set to default
 if (isset($_REQUEST['lang'])) {
     $_REQUEST['sc']['LANGUAGE'] = trim($_REQUEST['lang'], "'");
 }
 if (isset($_REQUEST['sc']['LANGUAGE'])) {
@@ -41,10 +40,31 @@ if (isset($_REQUEST['sc']['LANGUAGE'])) {
 }
 
 include_once('../exponent.php');
 expString::sanitize($_REQUEST);
 
+// Make sure our 'page' is set correctly and prevent running under most circumstances
+if (file_exists("../framework/conf/config.php") && !isset($_REQUEST['page'])) {
+    $_REQUEST['page'] = 'upgrade-1';
+}
+if (!file_exists("../framework/conf/config.php") && !isset($_REQUEST['page'])) {
+    $_REQUEST['page'] = 'welcome';
+}
+$page = $_REQUEST['page'];
+
+// Superadmin must be logged in to do an upgrade
+if (strpos($page, 'upgrade-') !== false && empty($user->isSuperAdmin())) {
+    header('Location: ../index.php');
+    exit();
+}
+
+// Only run installation if not already installed
+if (strpos($page, 'upgrade-') === false && !file_exists(BASE . 'install/not_configured')) {
+    header('Location: ../index.php');
+    exit();
+}
+
 // Switch to a saved profile as requested
 if (isset($_REQUEST['profile'])) {
     expSettings::activateProfile($_REQUEST['profile']);
     expTheme::removeSmartyCache(); //FIXME is this still necessary?
     expSession::clearAllUsersSessionCache();
@@ -55,17 +75,15 @@ if (isset($_REQUEST['profile'])) {
 // Create or update the config settings
 if (isset($_REQUEST['sc'])) {
     if (file_exists("../framework/conf/config.php")) {
         // Update the config
         foreach ($_REQUEST['sc'] as $key => $value) {
-//            $value = expString::sanitize($value);
             expSettings::change($key, $value);
         }
     } else {
         // Initialize /framework/conf/config
         $values = array(
-//            'c'          => expString::sanitize($_REQUEST['sc']),
             'c'          => $_REQUEST['sc'],
             'opts'       => array(),
             'configname' => 'Default',
             'activate'   => 1
         );
@@ -73,10 +91,14 @@ if (isset($_REQUEST['sc'])) {
     }
 }
 
 // Install a sample database as requested
 if (isset($_REQUEST['install_sample'])) {
+    if (!empty($_REQUEST['install_sample']) && (strpos($_REQUEST['install_sample'], '..') !== false || strpos($_REQUEST['install_sample'], '/') !== false)) {
+        header('Location: ../index.php');
+        exit();  // attempt to hack the site
+    }
     $eql = BASE . "themes/" . DISPLAY_THEME_REAL . "/" . $_REQUEST['install_sample'] . ".eql";
     if (!file_exists($eql)) {
         $eql = BASE . "install/samples/" . $_REQUEST['install_sample'] . ".eql";
     }
     if (file_exists($eql)) {
@@ -102,31 +124,10 @@ if (isset($_REQUEST['install_sample'])) {
     } else {
 //        echo gt('Sample content was added to your database.  This content should help you learn how Exponent works, and how to use it for your website.');
     }
 }
 
-// Make sure our 'page' is set correctly
-if (file_exists("../framework/conf/config.php") && !isset($_REQUEST['page'])) {
-    $_REQUEST['page'] = 'upgrade-1';
-}
-if (!file_exists("../framework/conf/config.php") && !isset($_REQUEST['page'])) {
-    $_REQUEST['page'] = 'welcome';
-}
-$page = $_REQUEST['page'];
-
-// Superadmin must be logged in to do an upgrade
-if (strpos($page, 'upgrade-') !== false && empty($user->is_admin)) {
-    header('Location: ../index.php');
-    exit();
-}
-
-// Only run installation if not already installed
-if (strpos($page, 'upgrade-') === false && !file_exists(BASE . 'install/not_configured')) {
-    header('Location: ../index.php');
-    exit();
-}
-
 switch ($page) {
     case 'upgrade-1':
         $masthead = gt("Upgrade");
         $page_text = gt("It appears you've upgraded your Exponent code.") . '<br /><br />' . gt(
                 "Before you begin the upgrade you should"
@@ -269,6 +270,6 @@ switch ($page) {
     </div>
     </body>
     </html>
 <?php
 ob_end_flush();
-?>
\ No newline at end of file
+?>

Vulnerable code: 
//            $value = expString::sanitize($value);
//            'c'          => expString::sanitize($_REQUEST['sc']),
// Make sure our 'page' is set correctly
if (file_exists("../framework/conf/config.php") && !isset($_REQUEST['page'])) {
    $_REQUEST['page'] = 'upgrade-1';
}
if (!file_exists("../framework/conf/config.php") && !isset($_REQUEST['page'])) {
    $_REQUEST['page'] = 'welcome';
}
$page = $_REQUEST['page'];

// Superadmin must be logged in to do an upgrade
if (strpos($page, 'upgrade-') !== false && empty($user->is_admin)) {
    header('Location: ../index.php');
    exit();
}

// Only run installation if not already installed
if (strpos($page, 'upgrade-') === false && !file_exists(BASE . 'install/not_configured')) {
    header('Location: ../index.php');
    exit();
}

?>
Fixed code: // Make sure our 'page' is set correctly and prevent running under most circumstances
if (file_exists("../framework/conf/config.php") && !isset($_REQUEST['page'])) {
    $_REQUEST['page'] = 'upgrade-1';
}
if (!file_exists("../framework/conf/config.php") && !isset($_REQUEST['page'])) {
    $_REQUEST['page'] = 'welcome';
}
$page = $_REQUEST['page'];

// Superadmin must be logged in to do an upgrade
if (strpos($page, 'upgrade-') !== false && empty($user->isSuperAdmin())) {
    header('Location: ../index.php');
    exit();
}

// Only run installation if not already installed
if (strpos($page, 'upgrade-') === false && !file_exists(BASE . 'install/not_configured')) {
    header('Location: ../index.php');
    exit();
}

    if (!empty($_REQUEST['install_sample']) && (strpos($_REQUEST['install_sample'], '..') !== false || strpos($_REQUEST['install_sample'], '/') !== false)) {
        header('Location: ../index.php');
        exit();  // attempt to hack the site
    }
?>