CVE-2016-5730: Exposure of Sensitive Information to an Unauthorized Actor (CWE-200)
value: phpMyAdmin 4.0.x before 4.0.10.16, 4.4.x before 4.4.15.7, and 4.6.x before 4.6.3 allows remote attackers to obtain sensitive information via vectors involving (1) an array value to FormDisplay.php, (2) incorrect data to validate.php, (3) unexpected data to Validator.php, (4) a missing config directory during setup, or (5) an incorrect OpenID identifier data type, which reveals the full path in an error message.
CWE description: The product exposes sensitive information to an actor that is not explicitly authorized to have access to that information.
CVSS v3 base score: 5.3
Published: 2016-07-03T01:59Z
Repository: https://github.com/phpmyadmin/phpmyadmin
Language: PHP
Files changed: setup/config.php, setup/frames/index.inc.php
Commit date: 2016-06-17 10:54:11 +0200
Commit message: Improve error handling in setup in case config dir is not present

We do not show these options in UI, but the scripts should handle it
gracefully.

Signed-off-by: Michal Čihař <michal@cihar.com>

Diff: diff --git a/setup/config.php b/setup/config.php
index cf1761455c7b1..db9e7c905e4cc 100644
--- a/setup/config.php
+++ b/setup/config.php
@@ -13,10 +13,28 @@
  */
 require './lib/common.inc.php';
 
 require './libraries/config/setup.forms.php';
 
+/**
+ * Loads configuration file path
+ *
+ * Do this in a function to avoid messing up with global $cfg
+ *
+ * @param string $config_file_path
+ *
+ * @return array
+ */
+function loadConfig($config_file_path)
+{
+    $cfg = array();
+    if (file_exists($config_file_path)) {
+        include $config_file_path;
+    }
+    return $cfg;
+}
+
 $form_display = new FormDisplay($GLOBALS['ConfigFile']);
 $form_display->registerForm('_config.php', $forms['_config.php']);
 $form_display->save('_config.php');
 $config_file_path = $GLOBALS['ConfigFile']->getFilePath();
 
@@ -42,24 +60,29 @@
     exit;
 } elseif (PMA_ifSetOr($_POST['submit_save'], '')) {
     //
     // Save generated config file on the server
     //
-    file_put_contents(
+    $result = @file_put_contents(
         $config_file_path,
         ConfigGenerator::getConfigFile($GLOBALS['ConfigFile'])
     );
+    if ($result === false) {
+        $state = 'config_not_saved';
+    } else {
+        $state = 'config_saved';
+    }
     header('HTTP/1.1 303 See Other');
-    header('Location: index.php' . PMA_URL_getCommon() . '&action_done=config_saved');
+    header('Location: index.php' . PMA_URL_getCommon() . '&action_done=' . $state);
     exit;
 } elseif (PMA_ifSetOr($_POST['submit_load'], '')) {
     //
     // Load config file from the server
     //
-    $cfg = array();
-    include $config_file_path;
-    $GLOBALS['ConfigFile']->setConfigData($cfg);
+    $GLOBALS['ConfigFile']->setConfigData(
+        loadConfig($config_file_path)
+    );
     header('HTTP/1.1 303 See Other');
     header('Location: index.php' . PMA_URL_getCommon());
     exit;
 } elseif (PMA_ifSetOr($_POST['submit_delete'], '')) {
     //
diff --git a/setup/frames/index.inc.php b/setup/frames/index.inc.php
index 5310b30ed66de..370bf748a7180 100644
--- a/setup/frames/index.inc.php
+++ b/setup/frames/index.inc.php
@@ -124,10 +124,24 @@
                 . 'directory config to use it.'
             )
         )
     );
     break;
+case 'config_not_saved':
+    /* Use uniqid to display this message every time configuration is saved */
+    PMA_messagesSet(
+        'notice', uniqid('config_not_saved'), __('Configuration not saved!'),
+        PMA_sanitize(
+            __(
+                'Please create web server writable folder [em]config[/em] in '
+                . 'phpMyAdmin top level directory as described in '
+                . '[doc@setup_script]documentation[/doc]. Otherwise you will be '
+                . 'only able to download or display it.'
+            )
+        )
+    );
+    break;
 default:
     break;
 }
 
 echo '<h2>' , __('Overview') , '</h2>';

Vulnerable code:     file_put_contents(
    header('Location: index.php' . PMA_URL_getCommon() . '&action_done=config_saved');
    $cfg = array();
    include $config_file_path;
    $GLOBALS['ConfigFile']->setConfigData($cfg);
Fixed code: /**
 * Loads configuration file path
 *
 * Do this in a function to avoid messing up with global $cfg
 *
 * @param string $config_file_path
 *
 * @return array
 */
function loadConfig($config_file_path)
{
    $cfg = array();
    if (file_exists($config_file_path)) {
        include $config_file_path;
    }
    return $cfg;
}

    $result = @file_put_contents(
    if ($result === false) {
        $state = 'config_not_saved';
    } else {
        $state = 'config_saved';
    }
    header('Location: index.php' . PMA_URL_getCommon() . '&action_done=' . $state);
    $GLOBALS['ConfigFile']->setConfigData(
        loadConfig($config_file_path)
    );
case 'config_not_saved':
    /* Use uniqid to display this message every time configuration is saved */
    PMA_messagesSet(
        'notice', uniqid('config_not_saved'), __('Configuration not saved!'),
        PMA_sanitize(
            __(
                'Please create web server writable folder [em]config[/em] in '
                . 'phpMyAdmin top level directory as described in '
                . '[doc@setup_script]documentation[/doc]. Otherwise you will be '
                . 'only able to download or display it.'
            )
        )
    );
    break;