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: libraries/config/Validator.php
Commit date: 2016-06-17 10:14:13 +0200
Commit message: Validate input of validator

We can not trust the input here, so we can expect anything and deal with
missing parameters or invalid values.

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

Diff: diff --git a/libraries/config/Validator.php b/libraries/config/Validator.php
index a65ef20ab8113..b7973ce9a7023 100644
--- a/libraries/config/Validator.php
+++ b/libraries/config/Validator.php
@@ -6,10 +6,11 @@
  * @package PhpMyAdmin
  */
 namespace PMA\libraries\config;
 
 use PMA\libraries\DatabaseInterface;
+use PMA\libraries\Util;
 
 /**
  * Validation class for various validation functions
  *
  * Validation function takes two argument: id for which it is called
@@ -278,10 +279,15 @@ public static function validateServer($path, $values)
             'Servers/1/user' => '',
             'Servers/1/SignonSession' => '',
             'Servers/1/SignonURL' => ''
         );
         $error = false;
+        if (empty($values['Servers/1/auth_type'])) {
+            $values['Servers/1/auth_type'] = '';
+            $result['Servers/1/auth_type'] = __('Invalid authentication type!');
+            $error = true;
+        }
         if ($values['Servers/1/auth_type'] == 'config'
             && empty($values['Servers/1/user'])
         ) {
             $result['Servers/1/user'] = __(
                 'Empty username while using [kbd]config[/kbd] authentication method!'
@@ -306,18 +312,18 @@ public static function validateServer($path, $values)
             );
             $error = true;
         }
 
         if (! $error && $values['Servers/1/auth_type'] == 'config') {
-            $password = $values['Servers/1/nopassword'] ? null
-                : $values['Servers/1/password'];
+            $password = !empty($values['Servers/1/nopassword']) && $values['Servers/1/nopassword'] ? null
+                : (empty($values['Servers/1/password']) ? '' : $values['Servers/1/password']);
             $test = static::testDBConnection(
-                $values['Servers/1/connect_type'],
-                $values['Servers/1/host'],
-                $values['Servers/1/port'],
-                $values['Servers/1/socket'],
-                $values['Servers/1/user'],
+                empty($values['Servers/1/connect_type']) ? '' : $values['Servers/1/connect_type'],
+                empty($values['Servers/1/host']) ? '' : $values['Servers/1/host'],
+                empty($values['Servers/1/port']) ? '' : $values['Servers/1/port'],
+                empty($values['Servers/1/socket']) ? '' : $values['Servers/1/socket'],
+                empty($values['Servers/1/user']) ? '' : $values['Servers/1/user'],
                 $password,
                 'Server'
             );
             if ($test !== true) {
                 $result = array_merge($result, $test);
@@ -343,35 +349,38 @@ public static function validatePMAStorage($path, $values)
             'Servers/1/controluser' => '',
             'Servers/1/controlpass' => ''
         );
         $error = false;
 
-        if ($values['Servers/1/pmadb'] == '') {
+        if (empty($values['Servers/1/pmadb'])) {
             return $result;
         }
 
         $result = array();
-        if ($values['Servers/1/controluser'] == '') {
+        if (empty($values['Servers/1/controluser'])) {
             $result['Servers/1/controluser'] = __(
                 'Empty phpMyAdmin control user while using phpMyAdmin configuration '
                 . 'storage!'
             );
             $error = true;
         }
-        if ($values['Servers/1/controlpass'] == '') {
+        if (empty($values['Servers/1/controlpass'])) {
             $result['Servers/1/controlpass'] = __(
                 'Empty phpMyAdmin control user password while using phpMyAdmin '
                 . 'configuration storage!'
             );
             $error = true;
         }
         if (! $error) {
             $test = static::testDBConnection(
-                $values['Servers/1/connect_type'],
-                $values['Servers/1/host'], $values['Servers/1/port'],
-                $values['Servers/1/socket'], $values['Servers/1/controluser'],
-                $values['Servers/1/controlpass'], 'Server_pmadb'
+                empty($values['Servers/1/connect_type']) ? '' : $values['Servers/1/connect_type'],
+                empty($values['Servers/1/host']) ? '' : $values['Servers/1/host'],
+                empty($values['Servers/1/port']) ? '' : $values['Servers/1/port'],
+                empty($values['Servers/1/socket']) ? '' : $values['Servers/1/socket'],
+                empty($values['Servers/1/controluser']) ? '' : $values['Servers/1/controluser'],
+                empty($values['Servers/1/controlpass']) ? '' : $values['Servers/1/controlpass'],
+                'Server_pmadb'
             );
             if ($test !== true) {
                 $result = array_merge($result, $test);
             }
         }
@@ -389,20 +398,20 @@ public static function validatePMAStorage($path, $values)
      */
     public static function validateRegex($path, $values)
     {
         $result = array($path => '');
 
-        if ($values[$path] == '') {
+        if (empty($values[$path])) {
             return $result;
         }
 
         static::testPHPErrorMsg();
 
         $matches = array();
         // in libraries/ListDatabase.php _checkHideDatabase(),
         // a '/' is used as the delimiter for hide_db
-        preg_match('/' . $values[$path] . '/', '', $matches);
+        preg_match('/' . Util::requestString($values[$path]) . '/', '', $matches);
 
         static::testPHPErrorMsg(false);
 
         if (isset($php_errormsg)) {
             $error = preg_replace('/^preg_match\(\): /', '', $php_errormsg);
@@ -426,14 +435,15 @@ public static function validateTrustedProxies($path, $values)
 
         if (empty($values[$path])) {
             return $result;
         }
 
-        if (is_array($values[$path])) {
+        if (is_array($values[$path]) || is_object($values[$path])) {
             // value already processed by FormDisplay::save
             $lines = array();
             foreach ($values[$path] as $ip => $v) {
+                $v = Util::requestString($v);
                 $lines[] = preg_match('/^-\d+$/', $ip)
                     ? $v
                     : $ip . ': ' . $v;
             }
         } else {
@@ -481,18 +491,20 @@ public static function validateNumber(
         $allow_neg,
         $allow_zero,
         $max_value,
         $error_string
     ) {
-        if ($values[$path] === '') {
+        if (empty($values[$path])) {
             return '';
         }
 
-        if (intval($values[$path]) != $values[$path]
-            || (! $allow_neg && $values[$path] < 0)
-            || (! $allow_zero && $values[$path] == 0)
-            || $values[$path] > $max_value
+        $value = Util::requestString($values[$path]);
+
+        if (intval($value) != $value
+            || (! $allow_neg && $value < 0)
+            || (! $allow_zero && $value == 0)
+            || $value > $max_value
         ) {
             return $error_string;
         }
 
         return '';
@@ -574,11 +586,14 @@ public static function validateNonNegativeNumber($path, $values)
      *
      * @return array
      */
     public static function validateByRegex($path, $values, $regex)
     {
-        $result = preg_match($regex, $values[$path]);
+        if (!isset($values[$path])) {
+            return '';
+        }
+        $result = preg_match($regex, Util::requestString($values[$path]));
         return array($path => ($result ? '' : __('Incorrect value!')));
     }
 
     /**
      * Validates upper bound for numeric inputs

Vulnerable code:             $password = $values['Servers/1/nopassword'] ? null
                : $values['Servers/1/password'];
                $values['Servers/1/connect_type'],
                $values['Servers/1/host'],
                $values['Servers/1/port'],
                $values['Servers/1/socket'],
                $values['Servers/1/user'],
        if ($values['Servers/1/pmadb'] == '') {
        if ($values['Servers/1/controluser'] == '') {
        if ($values['Servers/1/controlpass'] == '') {
                $values['Servers/1/connect_type'],
                $values['Servers/1/host'], $values['Servers/1/port'],
                $values['Servers/1/socket'], $values['Servers/1/controluser'],
                $values['Servers/1/controlpass'], 'Server_pmadb'
        if ($values[$path] == '') {
        preg_match('/' . $values[$path] . '/', '', $matches);
        if (is_array($values[$path])) {
        if ($values[$path] === '') {
        if (intval($values[$path]) != $values[$path]
            || (! $allow_neg && $values[$path] < 0)
            || (! $allow_zero && $values[$path] == 0)
            || $values[$path] > $max_value
        $result = preg_match($regex, $values[$path]);
Fixed code: use PMA\libraries\Util;
        if (empty($values['Servers/1/auth_type'])) {
            $values['Servers/1/auth_type'] = '';
            $result['Servers/1/auth_type'] = __('Invalid authentication type!');
            $error = true;
        }
            $password = !empty($values['Servers/1/nopassword']) && $values['Servers/1/nopassword'] ? null
                : (empty($values['Servers/1/password']) ? '' : $values['Servers/1/password']);
                empty($values['Servers/1/connect_type']) ? '' : $values['Servers/1/connect_type'],
                empty($values['Servers/1/host']) ? '' : $values['Servers/1/host'],
                empty($values['Servers/1/port']) ? '' : $values['Servers/1/port'],
                empty($values['Servers/1/socket']) ? '' : $values['Servers/1/socket'],
                empty($values['Servers/1/user']) ? '' : $values['Servers/1/user'],
        if (empty($values['Servers/1/pmadb'])) {
        if (empty($values['Servers/1/controluser'])) {
        if (empty($values['Servers/1/controlpass'])) {
                empty($values['Servers/1/connect_type']) ? '' : $values['Servers/1/connect_type'],
                empty($values['Servers/1/host']) ? '' : $values['Servers/1/host'],
                empty($values['Servers/1/port']) ? '' : $values['Servers/1/port'],
                empty($values['Servers/1/socket']) ? '' : $values['Servers/1/socket'],
                empty($values['Servers/1/controluser']) ? '' : $values['Servers/1/controluser'],
                empty($values['Servers/1/controlpass']) ? '' : $values['Servers/1/controlpass'],
                'Server_pmadb'
        if (empty($values[$path])) {
        preg_match('/' . Util::requestString($values[$path]) . '/', '', $matches);
        if (is_array($values[$path]) || is_object($values[$path])) {
                $v = Util::requestString($v);
        if (empty($values[$path])) {
        $value = Util::requestString($values[$path]);

        if (intval($value) != $value
            || (! $allow_neg && $value < 0)
            || (! $allow_zero && $value == 0)
            || $value > $max_value
        if (!isset($values[$path])) {
            return '';
        }
        $result = preg_match($regex, Util::requestString($values[$path]));