diff --git a/ChangeLog b/ChangeLog index 3a1d00b14..0188759b9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -119,6 +119,9 @@ $Id$ - bug #3044189 [doc] Cleared documentation for hide_db. - bug #3042495 [core] Move PMA_sendHeaderLocation to core.lib.php. +3.3.5.1 (2010-10-20) +- [core] Fixed various XSS issues, see PMASA-2010-5 for more details. + 3.3.5.0 (2010-07-26) - patch #2932113 [information_schema] Slow export when having lots of databases, thanks to Stéphane Pontier - shadow_walker diff --git a/db_search.php b/db_search.php index 0b68ba3d4..854cba8a0 100644 --- a/db_search.php +++ b/db_search.php @@ -336,7 +336,7 @@ $alter_select = + value="" /> diff --git a/db_sql.php b/db_sql.php index 986fb3417..50db7bda0 100644 --- a/db_sql.php +++ b/db_sql.php @@ -36,7 +36,7 @@ if ($num_tables == 0 && empty($db_query_force)) { /** * Query box, bookmark, insert data from textfile */ -PMA_sqlQueryForm(true, false, isset($_REQUEST['delimiter']) ? $_REQUEST['delimiter'] : ';'); +PMA_sqlQueryForm(true, false, isset($_REQUEST['delimiter']) ? htmlspecialchars($_REQUEST['delimiter']) : ';'); /** * Displays the footer diff --git a/error.php b/error.php index 117d070a2..b1d47e245 100644 --- a/error.php +++ b/error.php @@ -75,10 +75,14 @@ header('Content-Type: text/html; charset=' . $charset);

phpMyAdmin -

diff --git a/libraries/common.lib.php b/libraries/common.lib.php index a1c3c7bb4..4b1d8d925 100644 --- a/libraries/common.lib.php +++ b/libraries/common.lib.php @@ -566,7 +566,7 @@ function PMA_mysqlDie($error_message = '', $the_query = '', $formatted_sql = ''; } else { if (strlen($the_query) > $GLOBALS['cfg']['MaxCharactersInDisplayedSQL']) { - $formatted_sql = substr($the_query, 0, $GLOBALS['cfg']['MaxCharactersInDisplayedSQL']) . '[...]'; + $formatted_sql = htmlspecialchars(substr($the_query, 0, $GLOBALS['cfg']['MaxCharactersInDisplayedSQL'])) . '[...]'; } else { $formatted_sql = PMA_formatSql(PMA_SQP_parse($the_query), $the_query); } diff --git a/libraries/core.lib.php b/libraries/core.lib.php index 2355651a7..8bfc035c7 100644 --- a/libraries/core.lib.php +++ b/libraries/core.lib.php @@ -525,22 +525,23 @@ function PMA_getenv($var_name) { function PMA_sendHeaderLocation($uri) { if (PMA_IS_IIS && strlen($uri) > 600) { + require_once './libraries/js_escape.lib.php'; echo '- - -' . "\n"; echo '' . "\n"; echo '' . "\n"; echo '' . "\n"; - echo '' . "\n"; + echo '' . "\n"; echo '' . "\n"; echo '' . "\n"; echo '' . "\n"; echo '' . "\n"; diff --git a/libraries/database_interface.lib.php b/libraries/database_interface.lib.php index 8eba11181..c1a97b437 100644 --- a/libraries/database_interface.lib.php +++ b/libraries/database_interface.lib.php @@ -195,6 +195,10 @@ function PMA_usort_comparison_callback($a, $b) } else { $sorter = 'strcasecmp'; } + /* No sorting when key is not present */ + if (!isset($a[$GLOBALS['callback_sort_by']]) || ! isset($b[$GLOBALS['callback_sort_by']])) { + return 0; + } // produces f.e.: // return -1 * strnatcasecmp($a["SCHEMA_TABLES"], $b["SCHEMA_TABLES"]) return ($GLOBALS['callback_sort_order'] == 'ASC' ? 1 : -1) * $sorter($a[$GLOBALS['callback_sort_by']], $b[$GLOBALS['callback_sort_by']]); diff --git a/libraries/db_info.inc.php b/libraries/db_info.inc.php index 969af04e3..c51b2470f 100644 --- a/libraries/db_info.inc.php +++ b/libraries/db_info.inc.php @@ -211,7 +211,8 @@ if (! isset($sot_ready)) { ); // Make sure the sort type is implemented - if ($sort = $sortable_name_mappings[$_REQUEST['sort']]) { + if (isset($sortable_name_mappings[$_REQUEST['sort']])) { + $sort = $sortable_name_mappings[$_REQUEST['sort']]; if ($_REQUEST['sort_order'] == 'DESC') { $sort_order = 'DESC'; } diff --git a/libraries/dbi/mysql.dbi.lib.php b/libraries/dbi/mysql.dbi.lib.php index fdd83f8aa..5af59bd2f 100644 --- a/libraries/dbi/mysql.dbi.lib.php +++ b/libraries/dbi/mysql.dbi.lib.php @@ -344,6 +344,8 @@ function PMA_DBI_getError($link = null) $error_message = PMA_DBI_convert_message($error_message); } + $error_message = htmlspecialchars($error_message); + // Some errors messages cannot be obtained by mysql_error() if ($error_number == 2002) { $error = '#' . ((string) $error_number) . ' - ' . __('The server is not responding') . ' ' . __('(or the local MySQL server\'s socket is not correctly configured)'); diff --git a/libraries/dbi/mysqli.dbi.lib.php b/libraries/dbi/mysqli.dbi.lib.php index b5915df83..9e836eb03 100644 --- a/libraries/dbi/mysqli.dbi.lib.php +++ b/libraries/dbi/mysqli.dbi.lib.php @@ -400,6 +400,8 @@ function PMA_DBI_getError($link = null) $error_message = PMA_DBI_convert_message($error_message); } + $error_message = htmlspecialchars($error_message); + if ($error_number == 2002) { $error = '#' . ((string) $error_number) . ' - ' . __('The server is not responding') . ' ' . __('(or the local MySQL server\'s socket is not correctly configured)'); } else { diff --git a/libraries/sanitizing.lib.php b/libraries/sanitizing.lib.php index c9b79a747..eb8696d95 100644 --- a/libraries/sanitizing.lib.php +++ b/libraries/sanitizing.lib.php @@ -8,17 +8,26 @@ /** * Sanitizes $message, taking into account our special codes - * for formatting + * for formatting. + * + * If you want to include result in element attribute, you should escape it. + * + * Examples: + * + *

+ * + * bar * * @uses preg_replace() * @uses strtr() * @param string the message + * @param boolean whether to escape html in result * * @return string the sanitized message * * @access public */ -function PMA_sanitize($message) +function PMA_sanitize($message, $escape = false) { $replace_pairs = array( '<' => '<', @@ -66,6 +75,10 @@ function PMA_sanitize($message) $message = preg_replace($pattern, '', $message); } + if ($escape) { + $message = htmlspecialchars($message); + } + return $message; } ?> diff --git a/libraries/sqlparser.lib.php b/libraries/sqlparser.lib.php index 5509db1c9..3e74ca737 100644 --- a/libraries/sqlparser.lib.php +++ b/libraries/sqlparser.lib.php @@ -2574,7 +2574,7 @@ if (! defined('PMA_MINIMUM_COMMON')) { } $after .= "\n"; */ - $str .= $before . ($mode=='color' ? PMA_SQP_formatHTML_colorize($arr[$i]) : $arr[$i]['data']). $after; + $str .= $before . ($mode=='color' ? PMA_SQP_formatHTML_colorize($arr[$i]) : htmlspecialchars($arr[$i]['data'])). $after; } // end for /* End possibly unclosed documentation link */ if ($close_docu_link) { diff --git a/server_databases.php b/server_databases.php index 7aeee672c..d054acaf6 100644 --- a/server_databases.php +++ b/server_databases.php @@ -19,7 +19,21 @@ require './libraries/replication.inc.php'; if (empty($_REQUEST['sort_by'])) { $sort_by = 'SCHEMA_NAME'; } else { - $sort_by = PMA_sanitize($_REQUEST['sort_by']); + $sort_by_whitelist = array( + 'SCHEMA_NAME', + 'DEFAULT_COLLATION_NAME', + 'SCHEMA_TABLES', + 'SCHEMA_TABLE_ROWS', + 'SCHEMA_DATA_LENGTH', + 'SCHEMA_INDEX_LENGTH', + 'SCHEMA_LENGTH', + 'SCHEMA_DATA_FREE' + ); + if (in_array($_REQUEST['sort_by'], $sort_by_whitelist)) { + $sort_by = $_REQUEST['sort_by']; + } else { + $sort_by = 'SCHEMA_NAME'; + } } if (isset($_REQUEST['sort_order']) @@ -339,11 +353,11 @@ if ($databases_count > 0) { unset($column_order, $stat_name, $stat, $databases, $table_columns); if ($is_superuser || $cfg['AllowUserDropDatabase']) { - $common_url_query = PMA_generate_common_url() . '&sort_by=' . $sort_by . '&sort_order=' . $sort_order . '&dbstats=' . $dbstats; + $common_url_query = PMA_generate_common_url(array('sort_by' => $sort_by, 'sort_order' => $sort_order, 'dbstats' => $dbstats)); echo '' . __('With selected:') . '' . "\n" - . '' . "\n" + . '' . "\n" . ' ' . __('Check All') . ' / ' . "\n" - . '' . "\n" + . '' . "\n" . ' ' . __('Uncheck All') . '' . "\n" . '' . __('With selected:') . '' . "\n"; PMA_buttonOrImage('drop_selected_dbs', 'mult_submit', 'drop_selected_dbs', __('Drop'), 'b_deltbl.png'); diff --git a/server_privileges.php b/server_privileges.php index cd5afe75a..33483d2fb 100644 --- a/server_privileges.php +++ b/server_privileges.php @@ -1182,7 +1182,7 @@ if (!empty($update_privs)) { } $sql_query = $sql_query0 . ' ' . $sql_query1 . ' ' . $sql_query2; $message = PMA_Message::success(__('You have updated the privileges for %s.')); - $message->addParam('\'' . $username . '\'@\'' . $hostname . '\''); + $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\''); } @@ -1206,7 +1206,7 @@ if (isset($_REQUEST['revokeall'])) { } $sql_query = $sql_query0 . ' ' . $sql_query1; $message = PMA_Message::success(__('You have revoked the privileges for %s')); - $message->addParam('\'' . $username . '\'@\'' . $hostname . '\''); + $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\''); if (! isset($tablename)) { unset($dbname); } else { @@ -1242,7 +1242,7 @@ if (isset($_REQUEST['change_pw'])) { PMA_DBI_try_query($local_query) or PMA_mysqlDie(PMA_DBI_getError(), $sql_query, FALSE, $err_url); $message = PMA_Message::success(__('The password for %s was changed successfully.')); - $message->addParam('\'' . $username . '\'@\'' . $hostname . '\''); + $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\''); } } @@ -1647,8 +1647,8 @@ if (empty($_REQUEST['adduser']) && (! isset($checkprivs) || ! strlen($checkprivs if (isset($dbname)) { echo ' \'' + . $GLOBALS['url_query'] . '&username=' . htmlspecialchars(urlencode($username)) + . '&hostname=' . htmlspecialchars(urlencode($hostname)) . '&dbname=&tablename=">\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'' . "\n"; $url_dbname = urlencode(str_replace(array('\_', '\%'), array('_', '%'), $dbname)); @@ -1656,8 +1656,8 @@ if (empty($_REQUEST['adduser']) && (! isset($checkprivs) || ! strlen($checkprivs echo ' - ' . ($dbname_is_wildcard ? __('Databases') : __('Database') ); if (isset($tablename)) { echo ' ' . htmlspecialchars($dbname) . ''; + . '&username=' . htmlspecialchars(urlencode($username)) . '&hostname=' . htmlspecialchars(urlencode($hostname)) + . '&dbname=' . htmlspecialchars($url_dbname) . '&tablename=">' . htmlspecialchars($dbname) . ''; echo ' - ' . __('Table') . ' ' . htmlspecialchars($tablename) . ''; } else { echo ' ' . htmlspecialchars($dbname) . ''; @@ -1891,16 +1891,16 @@ if (empty($_REQUEST['adduser']) && (! isset($checkprivs) || ! strlen($checkprivs } echo '' . "\n" . ' '; - printf($link_edit, urlencode($username), - urlencode($hostname), - urlencode((! isset($dbname)) ? $row['Db'] : $dbname), + printf($link_edit, htmlspecialchars(urlencode($username)), + urlencode(htmlspecialchars($hostname)), + urlencode((! isset($dbname)) ? $row['Db'] : htmlspecialchars($dbname)), urlencode((! isset($dbname)) ? '' : $row['Table_name'])); echo '' . "\n" . ' '; if (! empty($row['can_delete']) || isset($row['Table_name']) && strlen($row['Table_name'])) { - printf($link_revoke, urlencode($username), - urlencode($hostname), - urlencode((! isset($dbname)) ? $row['Db'] : $dbname), + printf($link_revoke, htmlspecialchars(urlencode($username)), + urlencode(htmlspecialchars($hostname)), + urlencode((! isset($dbname)) ? $row['Db'] : htmlspecialchars($dbname)), urlencode((! isset($dbname)) ? '' : $row['Table_name'])); } echo '' . "\n" @@ -1980,7 +1980,7 @@ if (empty($_REQUEST['adduser']) && (! isset($checkprivs) || ! strlen($checkprivs if (isset($tablename)) { echo ' [ ' . __('Table') . ' ' . htmlspecialchars($tablename) . ': ' . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabTable']) . " ]\n"; @@ -2207,7 +2207,7 @@ if (empty($_REQUEST['adduser']) && (! isset($checkprivs) || ! strlen($checkprivs // Offer to create a new user for the current database echo '
' . "\n" - . ' ' . "\n" + . ' ' . "\n" . PMA_getIcon('b_usradd.png') . ' ' . __('Add a new User') . '' . "\n" . '
' . "\n"; diff --git a/sql.php b/sql.php index a98b9d480..a3ae0cfe1 100644 --- a/sql.php +++ b/sql.php @@ -173,14 +173,14 @@ if ($do_confirm) { .PMA_generate_common_hidden_inputs($db, $table); ?> - + - - - - - - + + + + + + ' . "\n" .' ' . __('Do you really want to ') . '' diff --git a/tbl_sql.php b/tbl_sql.php index e72dce3c9..aa0af4d00 100644 --- a/tbl_sql.php +++ b/tbl_sql.php @@ -37,7 +37,7 @@ require_once './libraries/tbl_links.inc.php'; /** * Query box, bookmark, insert data from textfile */ -PMA_sqlQueryForm(true, false, isset($_REQUEST['delimiter']) ? $_REQUEST['delimiter'] : ';'); +PMA_sqlQueryForm(true, false, isset($_REQUEST['delimiter']) ? htmlspecialchars($_REQUEST['delimiter']) : ';'); /** * Displays the footer