From 33b39f9f1dd9a4d27856530e5ac004e23b30e8ac Mon Sep 17 00:00:00 2001 From: Marc Delisle Date: Sat, 13 Sep 2014 09:57:22 -0400 Subject: [PATCH] bug #4530 [security] DOM based XSS that results to a CSRF that creates a ROOT account in certain conditions Signed-off-by: Marc Delisle --- ChangeLog | 4 ++++ js/ajax.js | 13 ++++++++++--- js/whitelist.php | 31 +++++++++++++++++++++++++++++++ libraries/Header.class.php | 13 ++++++++----- libraries/Scripts.class.php | 19 ++++++++++++++----- 5 files changed, 67 insertions(+), 13 deletions(-) create mode 100644 js/whitelist.php diff --git a/ChangeLog b/ChangeLog index 208a836236..08c97b8ac9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,10 @@ phpMyAdmin - ChangeLog ====================== +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 + 4.2.8.0 (2014-08-31) - bug #4516 Odd export behavior - bug #4519 Uncaught TypeError: Cannot read property 'success' of null diff --git a/js/ajax.js b/js/ajax.js index 08b3221af4..8de190e117 100644 --- a/js/ajax.js +++ b/js/ajax.js @@ -783,9 +783,16 @@ AJAX.setUrlHash = (function (jQuery, window) { if (window.location.hash.substring(0, 8) == '#PMAURL-') { // We have a valid hash, let's redirect the user // to the page that it's pointing to - window.location = window.location.hash.substring( - window.location.hash.indexOf(':') + 1 - ); + 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 + ); + } + } } else { // We don't have a valid hash, so we'll set it up // when the page finishes loading diff --git a/js/whitelist.php b/js/whitelist.php new file mode 100644 index 0000000000..0f64f5ce32 --- /dev/null +++ b/js/whitelist.php @@ -0,0 +1,31 @@ + diff --git a/libraries/Header.class.php b/libraries/Header.class.php index bc1e4a6f13..c54f8a03d9 100644 --- a/libraries/Header.class.php +++ b/libraries/Header.class.php @@ -144,7 +144,15 @@ class PMA_Header */ private function _addDefaultScripts() { + // Localised strings + $params = array('lang' => $GLOBALS['lang']); + if (isset($GLOBALS['db'])) { + $params['db'] = $GLOBALS['db']; + } $this->_scripts->addFile('jquery/jquery-1.8.3.min.js'); + $this->_scripts->addFile( + 'whitelist.php' . PMA_URL_getCommon($params), false, true + ); $this->_scripts->addFile('ajax.js'); $this->_scripts->addFile('keyhandler.js'); $this->_scripts->addFile('jquery/jquery-ui-1.9.2.custom.min.js'); @@ -171,11 +179,6 @@ class PMA_Header // Here would not be a good place to add CodeMirror because // the user preferences have not been merged at this point - // Localised strings - $params = array('lang' => $GLOBALS['lang']); - if (isset($GLOBALS['db'])) { - $params['db'] = $GLOBALS['db']; - } $this->_scripts->addFile('messages.php' . PMA_URL_getCommon($params)); // Append the theme id to this url to invalidate // the cache on a theme change. Though this might be diff --git a/libraries/Scripts.class.php b/libraries/Scripts.class.php index 7df3858796..7c5e1d1d50 100644 --- a/libraries/Scripts.class.php +++ b/libraries/Scripts.class.php @@ -50,12 +50,18 @@ class PMA_Scripts */ private function _includeFiles($files) { + $first_dynamic_scripts = ""; $dynamic_scripts = ""; $scripts = array(); foreach ($files as $value) { if (strpos($value['filename'], "?") !== false) { - $dynamic_scripts .= ""; + if ($value['before_statics'] === true) { + $first_dynamic_scripts .= ""; + } else { + $dynamic_scripts .= ""; + } continue; } $include = true; @@ -83,7 +89,7 @@ class PMA_Scripts '', htmlspecialchars($url) ); - return $static_scripts . $dynamic_scripts; + return $first_dynamic_scripts . $static_scripts . $dynamic_scripts; } /** @@ -105,10 +111,12 @@ class PMA_Scripts * @param string $filename The name of the file to include * @param bool $conditional_ie Whether to wrap the script tag in * conditional comments for IE + * @param bool $before_statics Whether this dynamic script should be + * included before the static ones * * @return void */ - public function addFile($filename, $conditional_ie = false) + public function addFile($filename, $conditional_ie = false, $before_statics = false) { $hash = md5($filename); if (!empty($this->_files[$hash])) { @@ -119,7 +127,8 @@ class PMA_Scripts $this->_files[$hash] = array( 'has_onload' => $has_onload, 'filename' => $filename, - 'conditional_ie' => $conditional_ie + 'conditional_ie' => $conditional_ie, + 'before_statics' => $before_statics ); }