diff --git a/ChangeLog b/ChangeLog
index f53c063a0..81670e91e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -19,6 +19,9 @@ $HeadURL: https://phpmyadmin.svn.sourceforge.net/svnroot/phpmyadmin/trunk/phpMyA
- 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 751675db5..455aa61a1 100644
--- a/db_search.php
+++ b/db_search.php
@@ -355,7 +355,7 @@ $alter_select =
|
|
+ value="" />
diff --git a/db_sql.php b/db_sql.php
index 2ac198bda..420561e81 100644
--- a/db_sql.php
+++ b/db_sql.php
@@ -37,7 +37,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 674d08e0f..7e86ffb95 100644
--- a/error.php
+++ b/error.php
@@ -76,10 +76,14 @@ header('Content-Type: text/html; charset=' . $charset);
phpMyAdmin -
diff --git a/libraries/common.lib.php b/libraries/common.lib.php
index 1a62769f4..d5b38cc58 100644
--- a/libraries/common.lib.php
+++ b/libraries/common.lib.php
@@ -575,7 +575,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 3e6cc00ca..f7f9da4d7 100644
--- a/libraries/core.lib.php
+++ b/libraries/core.lib.php
@@ -614,22 +614,23 @@ function PMA_setCookie($cookie, $value, $default = null, $validity = null, $http
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 501c34d0c..300a92554 100644
--- a/libraries/database_interface.lib.php
+++ b/libraries/database_interface.lib.php
@@ -205,6 +205,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 4f59baa47..1e5b401ad 100644
--- a/libraries/db_info.inc.php
+++ b/libraries/db_info.inc.php
@@ -213,7 +213,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 275458832..4750ee225 100644
--- a/libraries/dbi/mysql.dbi.lib.php
+++ b/libraries/dbi/mysql.dbi.lib.php
@@ -348,6 +348,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) . ' - ' . $GLOBALS['strServerNotResponding'] . ' ' . $GLOBALS['strSocketProblem'];
diff --git a/libraries/dbi/mysqli.dbi.lib.php b/libraries/dbi/mysqli.dbi.lib.php
index f3bcf268c..9672385df 100644
--- a/libraries/dbi/mysqli.dbi.lib.php
+++ b/libraries/dbi/mysqli.dbi.lib.php
@@ -405,6 +405,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) . ' - ' . $GLOBALS['strServerNotResponding'] . ' ' . $GLOBALS['strSocketProblem'];
} else {
diff --git a/libraries/sanitizing.lib.php b/libraries/sanitizing.lib.php
index 2b54bf197..d17fc50dd 100644
--- a/libraries/sanitizing.lib.php
+++ b/libraries/sanitizing.lib.php
@@ -9,17 +9,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(
'<' => '<',
@@ -67,6 +76,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 53f239a97..f844e2301 100644
--- a/libraries/sqlparser.lib.php
+++ b/libraries/sqlparser.lib.php
@@ -2456,7 +2456,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
if ($mode=='color') {
$str .= '';
diff --git a/server_databases.php b/server_databases.php
index 47037cc66..5e6d0ecc4 100644
--- a/server_databases.php
+++ b/server_databases.php
@@ -22,7 +22,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'])
@@ -342,11 +356,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 '
' . "\n"
- . '' . "\n"
+ . '' . "\n"
. ' ' . $strCheckAll . ' / ' . "\n"
- . '' . "\n"
+ . '' . "\n"
. ' ' . $strUncheckAll . '' . "\n"
. '' . $strWithChecked . '' . "\n";
PMA_buttonOrImage('drop_selected_dbs', 'mult_submit', 'drop_selected_dbs', $strDrop, 'b_deltbl.png');
diff --git a/server_privileges.php b/server_privileges.php
index 3f14c3f93..44e9be74d 100644
--- a/server_privileges.php
+++ b/server_privileges.php
@@ -1153,7 +1153,7 @@ if (!empty($update_privs)) {
}
$sql_query = $sql_query0 . ' ' . $sql_query1 . ' ' . $sql_query2;
$message = PMA_Message::success('strUpdatePrivMessage');
- $message->addParam('\'' . $username . '\'@\'' . $hostname . '\'');
+ $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
}
@@ -1177,7 +1177,7 @@ if (isset($_REQUEST['revokeall'])) {
}
$sql_query = $sql_query0 . ' ' . $sql_query1;
$message = PMA_Message::success('strRevokeMessage');
- $message->addParam('\'' . $username . '\'@\'' . $hostname . '\'');
+ $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
if (! isset($tablename)) {
unset($dbname);
} else {
@@ -1213,7 +1213,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('strPasswordChanged');
- $message->addParam('\'' . $username . '\'@\'' . $hostname . '\'');
+ $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
}
}
@@ -1595,8 +1595,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));
@@ -1604,8 +1604,8 @@ if (empty($_REQUEST['adduser']) && (! isset($checkprivs) || ! strlen($checkprivs
echo ' - ' . ($dbname_is_wildcard ? $GLOBALS['strDatabases'] : $GLOBALS['strDatabase'] );
if (isset($tablename)) {
echo ' ' . htmlspecialchars($dbname) . '';
+ . '&username=' . htmlspecialchars(urlencode($username)) . '&hostname=' . htmlspecialchars(urlencode($hostname))
+ . '&dbname=' . htmlspecialchars($url_dbname) . '&tablename=">' . htmlspecialchars($dbname) . '';
echo ' - ' . $GLOBALS['strTable'] . ' ' . htmlspecialchars($tablename) . '';
} else {
echo ' ' . htmlspecialchars($dbname) . '';
@@ -1839,16 +1839,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"
@@ -1928,7 +1928,7 @@ if (empty($_REQUEST['adduser']) && (! isset($checkprivs) || ! strlen($checkprivs
if (isset($tablename)) {
echo ' [ ' . $GLOBALS['strTable'] . ' ' . htmlspecialchars($tablename) . ': '
. PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabTable'])
. " ]\n";
@@ -2155,7 +2155,7 @@ if (empty($_REQUEST['adduser']) && (! isset($checkprivs) || ! strlen($checkprivs
// Offer to create a new user for the current database
echo '' . "\n";
diff --git a/sql.php b/sql.php
index 4dbfee246..b7281842d 100644
--- a/sql.php
+++ b/sql.php
@@ -175,14 +175,14 @@ if ($do_confirm) {
.PMA_generate_common_hidden_inputs($db, $table);
?>
-
+
-
-
-
-
-
-
+
+
+
+
+
+
' . "\n"
.' '
diff --git a/tbl_sql.php b/tbl_sql.php
index 5565d923b..f3c3aac6e 100644
--- a/tbl_sql.php
+++ b/tbl_sql.php
@@ -38,7 +38,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