CVE-2014-6300 (PHP, published 2014-11-08T11:55Z)
Description: value: Cross-site scripting (XSS) vulnerability in the micro history implementation in phpMyAdmin 4.0.x before 4.0.10.3, 4.1.x before 4.1.14.4, and 4.2.x before 4.2.8.1 allows remote attackers to inject arbitrary web script or HTML, and consequently conduct a cross-site request forgery (CSRF) attack to create a root account, via a crafted URL, related to js/ajax.js.
Severity: MEDIUM (CVSS v3 base score: )
Weakness: CWE-79 \u2014 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
Repository: https://github.com/phpmyadmin/phpmyadmin
Files changed:
ChangeLog
js/ajax.js
js/whitelist.php
libraries/Header.class.php
libraries/Scripts.class.php
Commit message: bug #4530 [security] DOM based XSS that results to a CSRF that creates a ROOT account in certain conditions

Signed-off-by: Marc Delisle <marc@infomarc.info>


Vulnerable code:
        window.location = window.location.hash.substring(
            window.location.hash.indexOf(':') + 1
        );
        // Localised strings
        $params = array('lang' => $GLOBALS['lang']);
        if (isset($GLOBALS['db'])) {
            $params['db'] = $GLOBALS['db'];
        }
                $dynamic_scripts .= "<script type='text/javascript' src='js/"
                    . $value['filename'] . "'></script>";
        return $static_scripts . $dynamic_scripts;
    public function addFile($filename, $conditional_ie = false)
            'conditional_ie' => $conditional_ie

Fixed code:
4.2.8.1 (not yet released)
- bug #4530 [security] DOM based XSS that results to a CSRF that creates a
            ROOT account in certain conditions

        var colon_position = window.location.hash.indexOf(':');
        var questionmark_position = window.location.hash.indexOf('?');
        if (colon_position != -1 && questionmark_position != -1 && colon_position < questionmark_position) {
            var hash_url = window.location.hash.substring(colon_position + 1, questionmark_position);
            if (PMA_gotoWhitelist.indexOf(hash_url) != -1) {
                window.location = window.location.hash.substring(
                    colon_position + 1
                );
            }
        }
<?php
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
 * Exporting of $goto_whitelist from PHP to Javascript
 *
 * @package PhpMyAdmin
 */

chdir('..');

// Send correct type:
header('Content-Type: text/javascript; charset=UTF-8');

// Cache output in client - the nocache query parameter makes sure that this
// file is reloaded when config changes
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 3600) . ' GMT');

// Avoid loading the full common.inc.php because this would add many
// non-js-compatible stuff like DOCTYPE
define('PMA_MINIMUM_COMMON', true);
require_once './libraries/common.inc.php';
// Close session early as we won't write anything there
session_write_close();

echo "var PMA_gotoWhitelist = new Array();\n";
$i = -1;
foreach ($GLOBALS['goto_whitelist'] as $one_whitelist) {
    $i++;
    echo 'PMA_gotoWhitelist[' . $i . ']="' . $one_whitelist . '";' . "\n";
}
?>
        // Localised strings
        $params = array('lang' => $GLOBALS['lang']);
        if (isset($GLOBALS['db'])) {
            $params['db'] = $GLOBALS['db'];
        }
        $this->_scripts->addFile(
            'whitelist.php' . PMA_URL_getCommon($params), false, true
        );
        $first_dynamic_scripts = "";
                if ($value['before_statics'] === true) {
                    $first_dynamic_scripts .= "<script type='text/javascript' src='js/"
                        . $value['filename'] . "'></script>";
                } else {
                    $dynamic_scripts .= "<script type='text/javascript' src='js/"
                        . $value['filename'] . "'></script>";
                }
        return $first_dynamic_scripts . $static_scripts . $dynamic_scripts;
     * @param bool   $before_statics Whether this dynamic script should be
     *                               included before the static ones
    public function addFile($filename, $conditional_ie = false, $before_statics = false)
            'conditional_ie' => $conditional_ie,
            'before_statics' => $before_statics