diff --git a/ChangeLog b/ChangeLog index dfa999da2..3f472e94f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -31,6 +31,10 @@ $HeadURL: https://phpmyadmin.svn.sourceforge.net/svnroot/phpmyadmin/trunk/phpMyA - bug #1811519 [privileges] fixed used collation for accessing mysql.user in server privileges - it should not be possible to move or copy a table to information_schema +2.11.1.2 (not yet released) +- fixed XSS in server_status.php, thanks to Omer Singer, The DigiTrust Group +- fixed some possible XSS with PHP_SELF, PATH_INFO, REQUEST_URI + 2.11.1.1 (2007-10-15) - bug #1810629 [setup] XSS in setup.php, thanks to Omer Singer, The DigiTrust Group diff --git a/libraries/Config.class.php b/libraries/Config.class.php index d9f87016a..9ec622606 100644 --- a/libraries/Config.class.php +++ b/libraries/Config.class.php @@ -557,12 +557,16 @@ class PMA_Config $url = array(); // At first we try to parse REQUEST_URI, it might contain full URL + /** + * REQUEST_URI contains PATH_INFO too, this is not what we want + * script-php/pathinfo/ if (PMA_getenv('REQUEST_URI')) { $url = @parse_url(PMA_getenv('REQUEST_URI')); // produces E_WARNING if it cannot get parsed, e.g. '/foobar:/' if ($url === false) { $url = array('path' => $_SERVER['REQUEST_URI']); } } + */ // If we don't have scheme, we didn't have full URL so we need to // dig deeper @@ -599,13 +603,17 @@ class PMA_Config // And finally the path could be already set from REQUEST_URI if (empty($url['path'])) { + /** + * REQUEST_URI contains PATH_INFO too, this is not what we want + * script-php/pathinfo/ if (PMA_getenv('PATH_INFO')) { $path = parse_url(PMA_getenv('PATH_INFO')); } else { // PHP_SELF in CGI often points to cgi executable, so use it // as last choice - $path = parse_url(PMA_getenv('PHP_SELF')); - } + */ + $path = parse_url($GLOBALS['PMA_PHP_SELF']); + //} $url['path'] = $path['path']; } } @@ -836,27 +844,36 @@ class PMA_Config $url = ''; + /** + * REQUEST_URI contains PATH_INFO too, this is not what we want + * script-php/pathinfo/ if (PMA_getenv('REQUEST_URI')) { $url = PMA_getenv('REQUEST_URI'); } + */ // If we don't have path if (empty($url)) { - if (PMA_getenv('PATH_INFO')) { - $url = PMA_getenv('PATH_INFO'); - } elseif (PMA_getenv('PHP_SELF')) { + //if (PMA_getenv('PATH_INFO')) { + // $url = PMA_getenv('PATH_INFO'); + //} else + if ($GLOBALS['PMA_PHP_SELF']) { // PHP_SELF in CGI often points to cgi executable, so use it // as last choice - $url = PMA_getenv('PHP_SELF'); + $url = $GLOBALS['PMA_PHP_SELF']; } elseif (PMA_getenv('SCRIPT_NAME')) { - $url = PMA_getenv('PHP_SELF'); + $url = $GLOBALS['PMA_PHP_SELF']; } } + /** + * REQUEST_URI contains PATH_INFO too, this is not what we want + * script-php/pathinfo/ $parsed_url = @parse_url($_SERVER['REQUEST_URI']); // produces E_WARNING if it cannot get parsed, e.g. '/foobar:/' if ($parsed_url === false) { + */ $parsed_url = array('path' => $url); - } + //} $cookie_path = substr($parsed_url['path'], 0, strrpos($parsed_url['path'], '/')) . '/'; diff --git a/libraries/common.inc.php b/libraries/common.inc.php index 1e86c7892..dd4a58991 100644 --- a/libraries/common.inc.php +++ b/libraries/common.inc.php @@ -136,6 +136,21 @@ foreach ($GLOBALS as $key => $dummy) { } } +/** + * PATH_INFO could be compromised if set, so remove it from PHP_SELF + * and provide a clean PHP_SELF here + */ +$PMA_PHP_SELF = PMA_getenv('PHP_SELF'); +$_PATH_INFO = PMA_getenv('PATH_INFO'); +if (! empty($_PATH_INFO) && ! empty($PMA_PHP_SELF)) { + $path_info_pos = strrpos($PMA_PHP_SELF, $_PATH_INFO); + if ($path_info_pos + strlen($_PATH_INFO) === strlen($PMA_PHP_SELF)) { + $PMA_PHP_SELF = substr($PMA_PHP_SELF, 0, $path_info_pos); + } +} +$PMA_PHP_SELF = htmlspecialchars($PMA_PHP_SELF); + + /** * just to be sure there was no import (registering) before here * we empty the global space @@ -197,7 +212,7 @@ if (isset($_POST['usesubform'])) { * track this */ if (isset($_POST['redirect']) - && $_POST['redirect'] != basename(PMA_getenv('PHP_SELF'))) { + && $_POST['redirect'] != basename($PMA_PHP_SELF)) { $__redirect = $_POST['redirect']; unset($_POST['redirect']); } diff --git a/libraries/common.lib.php b/libraries/common.lib.php index e739eabab..9a41e763b 100644 --- a/libraries/common.lib.php +++ b/libraries/common.lib.php @@ -1504,6 +1504,7 @@ function PMA_localisedDate($timestamp = -1, $format = '') * returns a tab for tabbed navigation. * If the variables $link and $args ar left empty, an inactive tab is created * + * @uses $GLOBALS['PMA_PHP_SELF'] * @uses $GLOBALS['strEmpty'] * @uses $GLOBALS['strDrop'] * @uses $GLOBALS['active_page'] @@ -1548,7 +1549,7 @@ function PMA_getTab($tab) || PMA_isValid($GLOBALS['active_page'], 'identical', $tab['link'])) { $tab['class'] = 'active'; } elseif (empty($GLOBALS['active_page']) - && basename(PMA_getenv('PHP_SELF')) == $tab['link'] + && basename($GLOBALS['PMA_PHP_SELF']) == $tab['link'] && empty($tab['warning'])) { $tab['class'] = 'active'; } @@ -1844,6 +1845,7 @@ function PMA_flipstring($string, $Separator = "
\n") * @todo use PMA_fatalError() if $die === true? * @uses PMA_getenv() * @uses header_meta_style.inc.php + * @uses $GLOBALS['PMA_PHP_SELF'] * basename * @param array The names of the parameters needed by the calling * script. @@ -1865,7 +1867,7 @@ function PMA_checkParameters($params, $die = true, $request = true) $checked_special = false; } - $reported_script_name = basename(PMA_getenv('PHP_SELF')); + $reported_script_name = basename($GLOBALS['PMA_PHP_SELF']); $found_error = false; $error_message = ''; diff --git a/libraries/display_change_password.lib.php b/libraries/display_change_password.lib.php index 9f39f07d8..bdba76f09 100644 --- a/libraries/display_change_password.lib.php +++ b/libraries/display_change_password.lib.php @@ -12,13 +12,11 @@ $chg_evt_handler = (PMA_USR_BROWSER_AGENT == 'IE' && PMA_USR_BROWSER_VER >= 5) ? 'onpropertychange' : 'onchange'; -$calling_script = PMA_getenv('PHP_SELF'); - // Displays the form ?> -
+ ' . "\n" . '' . "\n"; }?> diff --git a/libraries/grab_globals.lib.php b/libraries/grab_globals.lib.php index 73cc39943..76eefad04 100644 --- a/libraries/grab_globals.lib.php +++ b/libraries/grab_globals.lib.php @@ -104,7 +104,7 @@ if (! empty($_FILES)) { /** * globalize some environment variables */ -$server_vars = array('PHP_SELF', 'HTTP_ACCEPT_LANGUAGE', 'HTTP_AUTHORIZATION'); +$server_vars = array('HTTP_ACCEPT_LANGUAGE', 'HTTP_AUTHORIZATION'); foreach ($server_vars as $current) { // its not important HOW we detect html tags // its more important to prevent XSS diff --git a/server_status.php b/server_status.php index 198f76da3..acb6c2b1b 100644 --- a/server_status.php +++ b/server_status.php @@ -259,11 +259,8 @@ $sections = array( // variable or section name => (name => url) $links = array(); -// because of PMA_NO_VARIABLES_IMPORT, the $PHP_SELF globalized by -// grab_globals is not available here when register_globals = Off -// and in some situations, $_SERVER['PHP_SELF'] is not defined $links['table'][$strFlushTables] - = PMA_getenv('PHP_SELF') . '?flush=TABLES&' . PMA_generate_common_url(); + = $PMA_PHP_SELF . '?flush=TABLES&' . PMA_generate_common_url(); $links['table'][$strShowOpenTables] = 'sql.php?sql_query=' . urlencode('SHOW OPEN TABLES') . '&goto=server_status.php&' . PMA_generate_common_url(); @@ -278,7 +275,7 @@ $links['repl']['MySQL - ' . $strDocu] = $cfg['MySQLManualBase'] . '/replication.html'; $links['qcache'][$strFlushQueryCache] - = PMA_getenv('PHP_SELF') . '?flush=' . urlencode('QUERY CACHE') . '&' . + = $PMA_PHP_SELF . '?flush=' . urlencode('QUERY CACHE') . '&' . PMA_generate_common_url(); $links['qcache']['MySQL - ' . $strDocu] = $cfg['MySQLManualBase'] . '/query-cache.html'; @@ -337,10 +334,10 @@ $hour_factor = 3600 / $server_status['Uptime']; ?>