Merge branch 'QA_4_9-security' into QA_4_9
This commit is contained in:
commit
10c9709f7d
@ -1,6 +1,12 @@
|
||||
phpMyAdmin - ChangeLog
|
||||
======================
|
||||
|
||||
4.9.5 (2020-03-20)
|
||||
- issue [security] Fix SQL injection with certain usernames (PMASA-2020-2)
|
||||
- issue [security] Fix SQL injection in particular search situations (PMASA-2020-3)
|
||||
- issue [security] Fix SQL injection and XSS flaw (PMASA-2020-4)
|
||||
- issue Deprecate "options" for the external transformation; options must now be hard-coded along with the program name directly in the file.
|
||||
|
||||
4.9.4 (2020-01-07)
|
||||
- issue #15724 Fix 2FA was disabled by a bug
|
||||
- issue [security] Fix SQL injection vulnerability on the user accounts page (PMASA-2020-1)
|
||||
|
||||
@ -420,8 +420,8 @@ class TableSearchController extends TableController
|
||||
public function getDataRowAction()
|
||||
{
|
||||
$extra_data = array();
|
||||
$row_info_query = 'SELECT * FROM `' . $_POST['db'] . '`.`'
|
||||
. $_POST['table'] . '` WHERE ' . $_POST['where_clause'];
|
||||
$row_info_query = 'SELECT * FROM ' . Util::backquote($_POST['db']) . '.'
|
||||
. Util::backquote($_POST['table']) . ' WHERE ' . $_POST['where_clause'];
|
||||
$result = $this->dbi->query(
|
||||
$row_info_query . ";",
|
||||
DatabaseInterface::CONNECT_USER,
|
||||
|
||||
@ -5163,6 +5163,8 @@ class Results
|
||||
if (count($url_params) > 0
|
||||
&& (!empty($tmpdb) && !empty($meta->orgtable))
|
||||
) {
|
||||
$url_params['where_clause_sign'] = Core::signSqlQuery($url_params['where_clause']);
|
||||
|
||||
$result = '<a href="tbl_get_field.php'
|
||||
. Url::getCommon($url_params)
|
||||
. '" class="disableAjax">'
|
||||
|
||||
@ -467,7 +467,7 @@ class Error extends Message
|
||||
public function isUserError()
|
||||
{
|
||||
return $this->hide_location ||
|
||||
($this->getNumber() & (E_USER_WARNING | E_USER_ERROR | E_USER_NOTICE));
|
||||
($this->getNumber() & (E_USER_WARNING | E_USER_ERROR | E_USER_NOTICE | E_USER_DEPRECATED));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -166,12 +166,12 @@ class ErrorHandler
|
||||
*/
|
||||
if (error_reporting() == 0 &&
|
||||
$this->error_reporting != 0 &&
|
||||
($errno & (E_USER_WARNING | E_USER_ERROR | E_USER_NOTICE)) == 0
|
||||
($errno & (E_USER_WARNING | E_USER_ERROR | E_USER_NOTICE | E_USER_DEPRECATED)) == 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (($errno & (E_USER_WARNING | E_USER_ERROR | E_USER_NOTICE)) == 0) {
|
||||
if (($errno & (E_USER_WARNING | E_USER_ERROR | E_USER_NOTICE | E_USER_DEPRECATED)) == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -229,6 +229,7 @@ class ErrorHandler
|
||||
case E_USER_NOTICE:
|
||||
case E_USER_WARNING:
|
||||
case E_USER_ERROR:
|
||||
case E_USER_DEPRECATED:
|
||||
// just collect the error
|
||||
// display is called from outside
|
||||
break;
|
||||
|
||||
@ -29,10 +29,10 @@ abstract class ExternalTransformationsPlugin extends TransformationsPlugin
|
||||
. ' data via standard input. Returns the standard output of the'
|
||||
. ' application. The default is Tidy, to pretty-print HTML code.'
|
||||
. ' For security reasons, you have to manually edit the file'
|
||||
. ' libraries/classes/Plugins/Transformations/Output/Text_Plain_External'
|
||||
. '.php and list the tools you want to make available.'
|
||||
. ' libraries/classes/Plugins/Transformations/Abs/ExternalTransformationsPlugin.php'
|
||||
. ' and list the tools you want to make available.'
|
||||
. ' The first option is then the number of the program you want to'
|
||||
. ' use and the second option is the parameters for the program.'
|
||||
. ' use. The second option should be blank for historical reasons.'
|
||||
. ' The third option, if set to 1, will convert the output using'
|
||||
. ' htmlspecialchars() (Default 1). The fourth option, if set to 1,'
|
||||
. ' will prevent wrapping and ensure that the output appears all on'
|
||||
@ -108,6 +108,16 @@ abstract class ExternalTransformationsPlugin extends TransformationsPlugin
|
||||
$program = $allowed_programs[0];
|
||||
}
|
||||
|
||||
if (isset($options[1]) && strlen((string) $options[1]) > 0) {
|
||||
trigger_error(sprintf(
|
||||
__(
|
||||
'You are using the external transformation command line options field, which has been deprecated for security reasons. '
|
||||
. 'Add all command line options directly to the definition in %s.'
|
||||
),
|
||||
'[code]libraries/classes/Plugins/Transformations/Abs/ExternalTransformationsPlugin.php[/code]'
|
||||
), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
// needs PHP >= 4.3.0
|
||||
$newstring = '';
|
||||
$descriptorspec = array(
|
||||
|
||||
@ -1812,8 +1812,11 @@ class Privileges
|
||||
&& $mode == 'change'
|
||||
) {
|
||||
$row = $GLOBALS['dbi']->fetchSingleRow(
|
||||
'SELECT `plugin` FROM `mysql`.`user` WHERE '
|
||||
. '`User` = "' . $username . '" AND `Host` = "' . $hostname . '" LIMIT 1'
|
||||
'SELECT `plugin` FROM `mysql`.`user` WHERE `User` = "'
|
||||
. $GLOBALS['dbi']->escapeString($username)
|
||||
. '" AND `Host` = "'
|
||||
. $GLOBALS['dbi']->escapeString($hostname)
|
||||
. '" LIMIT 1'
|
||||
);
|
||||
// Table 'mysql'.'user' may not exist for some previous
|
||||
// versions of MySQL - in that case consider fallback value
|
||||
@ -1824,8 +1827,11 @@ class Privileges
|
||||
list($username, $hostname) = $GLOBALS['dbi']->getCurrentUserAndHost();
|
||||
|
||||
$row = $GLOBALS['dbi']->fetchSingleRow(
|
||||
'SELECT `plugin` FROM `mysql`.`user` WHERE '
|
||||
. '`User` = "' . $username . '" AND `Host` = "' . $hostname . '"'
|
||||
'SELECT `plugin` FROM `mysql`.`user` WHERE `User` = "'
|
||||
. $GLOBALS['dbi']->escapeString($username)
|
||||
. '" AND `Host` = "'
|
||||
. $GLOBALS['dbi']->escapeString($hostname)
|
||||
. '"'
|
||||
);
|
||||
if (isset($row) && $row && ! empty($row['plugin'])) {
|
||||
$authentication_plugin = $row['plugin'];
|
||||
@ -1965,8 +1971,8 @@ class Privileges
|
||||
. " `authentication_string` = '" . $hashedPassword
|
||||
. "', `Password` = '', "
|
||||
. " `plugin` = '" . $authentication_plugin . "'"
|
||||
. " WHERE `User` = '" . $username . "' AND Host = '"
|
||||
. $hostname . "';";
|
||||
. " WHERE `User` = '" . $GLOBALS['dbi']->escapeString($username)
|
||||
. "' AND Host = '" . $GLOBALS['dbi']->escapeString($hostname) . "';";
|
||||
} else {
|
||||
// USE 'SET PASSWORD ...' syntax for rest of the versions
|
||||
// Backup the old value, to be reset later
|
||||
@ -1976,8 +1982,8 @@ class Privileges
|
||||
$orig_value = $row['@@old_passwords'];
|
||||
$update_plugin_query = "UPDATE `mysql`.`user` SET"
|
||||
. " `plugin` = '" . $authentication_plugin . "'"
|
||||
. " WHERE `User` = '" . $username . "' AND Host = '"
|
||||
. $hostname . "';";
|
||||
. " WHERE `User` = '" . $GLOBALS['dbi']->escapeString($username)
|
||||
. "' AND Host = '" . $GLOBALS['dbi']->escapeString($hostname) . "';";
|
||||
|
||||
// Update the plugin for the user
|
||||
if (!($GLOBALS['dbi']->tryQuery($update_plugin_query))) {
|
||||
|
||||
@ -114,7 +114,8 @@ class UserPassword
|
||||
if ($serverType == 'MySQL'
|
||||
&& $serverVersion >= 50706
|
||||
) {
|
||||
$sql_query = 'ALTER USER \'' . $username . '\'@\'' . $hostname
|
||||
$sql_query = 'ALTER USER \'' . $GLOBALS['dbi']->escapeString($username)
|
||||
. '\'@\'' . $GLOBALS['dbi']->escapeString($hostname)
|
||||
. '\' IDENTIFIED WITH ' . $orig_auth_plugin . ' BY '
|
||||
. (($password == '') ? '\'\'' : '\'***\'');
|
||||
} elseif (($serverType == 'MySQL'
|
||||
@ -182,7 +183,8 @@ class UserPassword
|
||||
$serverVersion = $GLOBALS['dbi']->getVersion();
|
||||
|
||||
if ($serverType == 'MySQL' && $serverVersion >= 50706) {
|
||||
$local_query = 'ALTER USER \'' . $username . '\'@\'' . $hostname . '\''
|
||||
$local_query = 'ALTER USER \'' . $GLOBALS['dbi']->escapeString($username)
|
||||
. '\'@\'' . $GLOBALS['dbi']->escapeString($hostname) . '\''
|
||||
. ' IDENTIFIED with ' . $orig_auth_plugin . ' BY '
|
||||
. (($password == '')
|
||||
? '\'\''
|
||||
@ -208,8 +210,8 @@ class UserPassword
|
||||
. " `authentication_string` = '" . $hashedPassword
|
||||
. "', `Password` = '', "
|
||||
. " `plugin` = '" . $orig_auth_plugin . "'"
|
||||
. " WHERE `User` = '" . $username . "' AND Host = '"
|
||||
. $hostname . "';";
|
||||
. " WHERE `User` = '" . $GLOBALS['dbi']->escapeString($username)
|
||||
. "' AND Host = '" . $GLOBALS['dbi']->escapeString($hostname) . "';";
|
||||
} else {
|
||||
$local_query = 'SET password = ' . (($password == '')
|
||||
? '\'\''
|
||||
|
||||
@ -38,6 +38,15 @@ if (!$GLOBALS['dbi']->getColumns($db, $table)) {
|
||||
PhpMyAdmin\Util::mysqlDie(__('Invalid table name'));
|
||||
}
|
||||
|
||||
if (! isset($_GET['where_clause'])
|
||||
|| ! isset($_GET['where_clause_sign'])
|
||||
|| ! Core::checkSqlQuerySignature($_GET['where_clause'], $_GET['where_clause_sign'])
|
||||
) {
|
||||
/* l10n: In case a SQL query did not pass a security check */
|
||||
Core::fatalError(__('There is an issue with your request.'));
|
||||
exit;
|
||||
}
|
||||
|
||||
/* Grab data */
|
||||
$sql = 'SELECT ' . PhpMyAdmin\Util::backquote($_GET['transform_key'])
|
||||
. ' FROM ' . PhpMyAdmin\Util::backquote($table)
|
||||
|
||||
@ -46,6 +46,7 @@ class ResultsTest extends PmaTestCase
|
||||
$GLOBALS['PMA_Config'] = new Config();
|
||||
$GLOBALS['PMA_Config']->enableBc();
|
||||
$GLOBALS['text_dir'] = 'ltr';
|
||||
$_SESSION[' HMAC_secret '] = 'test';
|
||||
|
||||
$dbi = $this->getMockBuilder('PhpMyAdmin\DatabaseInterface')
|
||||
->disableOriginalConstructor()
|
||||
@ -1323,7 +1324,7 @@ class ResultsTest extends PmaTestCase
|
||||
$meta = new stdClass();
|
||||
$meta->type = 'BLOB';
|
||||
$meta->orgtable = 'bar';
|
||||
$url_params = array('db' => 'foo', 'table' => 'bar');
|
||||
$url_params = array('db' => 'foo', 'table' => 'bar', 'where_clause' => 'where_clause');
|
||||
|
||||
return array(
|
||||
array(
|
||||
@ -1337,9 +1338,7 @@ class ResultsTest extends PmaTestCase
|
||||
$meta,
|
||||
$url_params,
|
||||
null,
|
||||
'<a href="tbl_get_field.php?db=foo&table=bar&server=0'
|
||||
. '&lang=en'
|
||||
. '" class="disableAjax">1001</a>'
|
||||
'class="disableAjax">1001</a>'
|
||||
),
|
||||
array(
|
||||
true,
|
||||
@ -1352,9 +1351,7 @@ class ResultsTest extends PmaTestCase
|
||||
$meta,
|
||||
$url_params,
|
||||
null,
|
||||
'<a href="tbl_get_field.php?db=foo&table=bar&server=0'
|
||||
. '&lang=en'
|
||||
. '" class="disableAjax">0x123456</a>'
|
||||
'class="disableAjax">0x123456</a>'
|
||||
),
|
||||
array(
|
||||
true,
|
||||
@ -1367,9 +1364,7 @@ class ResultsTest extends PmaTestCase
|
||||
$meta,
|
||||
$url_params,
|
||||
null,
|
||||
'<a href="tbl_get_field.php?db=foo&table=bar&server=0'
|
||||
. '&lang=en'
|
||||
. '" class="disableAjax">[BLOB - 4 B]</a>'
|
||||
'class="disableAjax">[BLOB - 4 B]</a>'
|
||||
),
|
||||
array(
|
||||
false,
|
||||
@ -1431,7 +1426,7 @@ class ResultsTest extends PmaTestCase
|
||||
$_SESSION['tmpval']['display_binary'] = $display_binary;
|
||||
$_SESSION['tmpval']['display_blob'] = $display_blob;
|
||||
$GLOBALS['cfg']['LimitChars'] = 50;
|
||||
$this->assertEquals(
|
||||
$this->assertContains(
|
||||
$output,
|
||||
$this->_callPrivateFunction(
|
||||
'_handleNonPrintableContents',
|
||||
@ -1471,7 +1466,7 @@ class ResultsTest extends PmaTestCase
|
||||
$meta2->decimals = 0;
|
||||
$meta2->name = 'varchar';
|
||||
$meta2->orgname = 'varchar';
|
||||
$url_params = array('db' => 'foo', 'table' => 'tbl');
|
||||
$url_params = array('db' => 'foo', 'table' => 'tbl', 'where_clause' => 'where_clause');
|
||||
|
||||
return array(
|
||||
array(
|
||||
@ -1489,11 +1484,7 @@ class ResultsTest extends PmaTestCase
|
||||
array(),
|
||||
0,
|
||||
'binary',
|
||||
'<td class="left hex">' . PHP_EOL
|
||||
. ' <a href="tbl_get_field.php?'
|
||||
. 'db=foo&table=tbl&server=0&lang=en'
|
||||
. '" '
|
||||
. 'class="disableAjax">[BLOB - 4 B]</a>' . PHP_EOL
|
||||
'class="disableAjax">[BLOB - 4 B]</a>' . PHP_EOL
|
||||
. '</td>' . PHP_EOL
|
||||
),
|
||||
array(
|
||||
@ -1596,7 +1587,7 @@ class ResultsTest extends PmaTestCase
|
||||
$_SESSION['tmpval']['relational_display'] = false;
|
||||
$GLOBALS['cfg']['LimitChars'] = 50;
|
||||
$GLOBALS['cfg']['ProtectBinary'] = $protectBinary;
|
||||
$this->assertEquals(
|
||||
$this->assertContains(
|
||||
$output,
|
||||
$this->_callPrivateFunction(
|
||||
'_getDataCellForNonNumericColumns',
|
||||
|
||||
Loading…
Reference in New Issue
Block a user