Merge remote-tracking branch 'origin/QA_4_6' into QA_4_6

This commit is contained in:
Weblate 2017-01-23 23:54:11 +01:00
commit 4938bc223f
25 changed files with 109 additions and 302 deletions

View File

@ -1,7 +1,7 @@
phpMyAdmin - ChangeLog
======================
4.6.6 (not yet released)
4.6.6 (2017-01-23)
- issue #12759 Fix Notice regarding 'Undefined index: old_usergroup'
- issue #12760 Fix Notice regarding 'Undefined index: users'
- issue #12762 Fixed parsing of SQL with BINARY function
@ -39,6 +39,14 @@ phpMyAdmin - ChangeLog
- issue #12881 Fix database search with newer php-gettext
- issue #12894 Fix linter error on unterminated variable name
- issue #12732 Fixed filtering for active processes
- issue [security] Multiple vulnerabilities in setup script, see PMASA-2016-44.
- issue [security] Open redirect, see PMASA-2017-1.
- issue [security] php-gettext code execution, see PMASA-2017-2.
- issue [security] DOS vulnerabiltiy in table editing, see PMASA-2017-3.
- issue [security] CSS injection in themes, see PMASA-2017-4.
- issue [security] Cookie attribute injection attack, see PMASA-2017-5.
- issue [security] SSRF in replication, see PMASA-2017-6.
- issue [security] DOS in replication status, see PMASA-2017-7.
4.6.5.2 (2016-12-05)
- issue #12765 Fixed SQL export with newlines

2
README
View File

@ -1,7 +1,7 @@
phpMyAdmin - Readme
===================
Version 4.6.6-dev
Version 4.6.6
A web interface for MySQL and MariaDB.

View File

@ -51,7 +51,7 @@ copyright = u'2012 - 2016, The phpMyAdmin devel team'
# built documents.
#
# The short X.Y version.
version = '4.6.6-dev'
version = '4.6.6'
# The full version, including alpha/beta/rc tags.
release = version

View File

@ -305,60 +305,13 @@ Using Setup script
------------------
Instead of manually editing :file:`config.inc.php`, you can use phpMyAdmin's
setup feature. First you must manually create a folder ``config``
in the phpMyAdmin directory. This is a security measure. On a
Linux/Unix system you can use the following commands:
setup feature. The file can be generated using the setup and you can download it
for upload to the server.
.. code-block:: sh
cd phpMyAdmin
mkdir config # create directory for saving
chmod o+rw config # give it world writable permissions
And to edit an existing configuration, copy it over first:
.. code-block:: sh
cp config.inc.php config/ # copy current configuration for editing
chmod o+w config/config.inc.php # give it world writable permissions
.. note::
Debian and Ubuntu have simplified this setup and all you need to do is to
execute :program:`/usr/sbin/pma-configure`.
On other platforms, simply create the folder and ensure that your web
server has read and write access to it. :ref:`faq1_26` can help with
this.
Next, open your browser and visit the location where you installed phpMyAdmin, with the ``/setup`` suffix. If you have an existing configuration,
use the ``Load`` button to bring its content inside the setup panel.
Note that **changes are not saved to disk until you explicitly choose ``Save``**
from the *Configuration* area of the screen. Normally the script saves the new
:file:`config.inc.php` to the ``config/`` directory, but if the webserver does
not have the proper permissions you may see the error "Cannot load or
save configuration." Ensure that the ``config/`` directory exists and
has the proper permissions - or use the ``Download`` link to save the
config file locally and upload it (via FTP or some similar means) to the
proper location.
Once the file has been saved, it must be moved out of the ``config/``
directory and the permissions must be reset, again as a security
measure:
.. code-block:: sh
mv config/config.inc.php . # move file to current directory
chmod o-rw config.inc.php # remove world read and write permissions
rm -rf config # remove not needed directory
.. note::
Debian and Ubuntu have simplified this setup and all you need to do is to
execute :program:`/usr/sbin/pma-secure`.
Next, open your browser and visit the location where you installed phpMyAdmin,
with the ``/setup`` suffix. The changes are not saved to the server, you need to
use the :guilabel:`Download` button to save them to your computer and then upload
to the server.
Now the file is ready to be used. You can choose to review or edit the
file with your favorite editor, if you prefer to set some advanced

View File

@ -101,7 +101,7 @@ class Config
*/
public function checkSystem()
{
$this->set('PMA_VERSION', '4.6.6-dev');
$this->set('PMA_VERSION', '4.6.6');
/**
* @deprecated
*/

View File

@ -431,9 +431,6 @@ class Theme
if (!is_null($fs)) {
return $fs;
}
if (isset($_COOKIE['pma_fontsize'])) {
return htmlspecialchars($_COOKIE['pma_fontsize']);
}
return '82%';
}

View File

@ -482,16 +482,6 @@ class ConfigFile
}
}
/**
* Returns config file path, relative to phpMyAdmin's root path
*
* @return string
*/
public function getFilePath()
{
return SETUP_CONFIG_FILE;
}
/**
* Returns configuration array (full, multidimensional format)
*

View File

@ -112,7 +112,10 @@ class PageSettings
$result = PMA_saveUserprefs($cf->getConfigArray());
if ($result === true) {
// reload page
header('Location: ' . $_SERVER['REQUEST_URI']);
$response = Response::getInstance();
PMA_sendHeaderLocation(
$response->getFooter()->getSelfUrl('unencoded')
);
exit();
} else {
$error = $result;

View File

@ -887,7 +887,7 @@ class DatabaseStructureController extends DatabaseController
if ($this->db == PMA_extractDbOrTable($db_table)
&& preg_match(
"@^" .
mb_substr(PMA_extractDbOrTable($db_table, 'table'), 0, -1) . "@",
preg_quote(mb_substr(PMA_extractDbOrTable($db_table, 'table'), 0, -1)) . "@",
$truename
)
) {

View File

@ -935,6 +935,10 @@ function PMA_cleanupPathInfo()
}
$_PATH_INFO = PMA_getenv('PATH_INFO');
if (! empty($_PATH_INFO) && ! empty($PMA_PHP_SELF)) {
$question_pos = mb_strpos($PMA_PHP_SELF, '?');
if ($question_pos != false) {
$PMA_PHP_SELF = mb_substr($PMA_PHP_SELF, 0, $question_pos);
}
$path_info_pos = mb_strrpos($PMA_PHP_SELF, $_PATH_INFO);
if ($path_info_pos !== false) {
$path_info_part = mb_substr($PMA_PHP_SELF, $path_info_pos, mb_strlen($_PATH_INFO));
@ -943,7 +947,24 @@ function PMA_cleanupPathInfo()
}
}
}
$PMA_PHP_SELF = htmlspecialchars($PMA_PHP_SELF);
$path = [];
foreach(explode('/', $PMA_PHP_SELF) as $part) {
// ignore parts that have no value
if (empty($part) || $part === '.') continue;
if ($part !== '..') {
// cool, we found a new part
array_push($path, $part);
} else if (count($path) > 0) {
// going back up? sure
array_pop($path);
}
// Here we intentionall ignore case where we go too up
// as there is nothing sane to do
}
$PMA_PHP_SELF = htmlspecialchars('/' . join('/', $path));
}
/**

View File

@ -173,10 +173,13 @@ class NavigationTree
* @todo describe a scenario where this code is executed
*/
if (!$GLOBALS['cfg']['Server']['DisableIS']) {
$dbSeparator = $GLOBALS['dbi']->escapeString(
$GLOBALS['cfg']['NavigationTreeDbSeparator']
);
$query = "SELECT (COUNT(DB_first_level) DIV %d) * %d ";
$query .= "from ( ";
$query .= " SELECT distinct SUBSTRING_INDEX(SCHEMA_NAME, ";
$query .= " '" . $GLOBALS['dbi']->escapeString($GLOBALS['cfg']['NavigationTreeDbSeparator']) . "', 1) ";
$query .= " '%s', 1) ";
$query .= " DB_first_level ";
$query .= " FROM INFORMATION_SCHEMA.SCHEMATA ";
$query .= " WHERE `SCHEMA_NAME` < '%s' ";
@ -187,6 +190,7 @@ class NavigationTree
$query,
(int)$GLOBALS['cfg']['FirstLevelNavigationItems'],
(int)$GLOBALS['cfg']['FirstLevelNavigationItems'],
$dbSeparator,
$GLOBALS['dbi']->escapeString($GLOBALS['db'])
)
);

View File

@ -424,7 +424,9 @@ class Node
return $retval;
}
$dbSeparator = $GLOBALS['cfg']['NavigationTreeDbSeparator'];
$dbSeparator = $GLOBALS['dbi']->escapeString(
$GLOBALS['cfg']['NavigationTreeDbSeparator']
);
if (isset($GLOBALS['cfg']['Server']['DisableIS'])
&& !$GLOBALS['cfg']['Server']['DisableIS']
) {
@ -434,7 +436,7 @@ class Node
$query .= "SELECT DB_first_level ";
$query .= "FROM ( ";
$query .= "SELECT DISTINCT SUBSTRING_INDEX(SCHEMA_NAME, ";
$query .= "'" . $GLOBALS['dbi']->escapeString($dbSeparator) . "', 1) ";
$query .= "'%s', 1) ";
$query .= "DB_first_level ";
$query .= "FROM INFORMATION_SCHEMA.SCHEMATA ";
$query .= $this->_getWhereClause('SCHEMA_NAME', $searchClause);
@ -444,11 +446,19 @@ class Node
$query .= ") t2 ";
$query .= $this->_getWhereClause('SCHEMA_NAME', $searchClause);
$query .= "AND 1 = LOCATE(CONCAT(DB_first_level, ";
$query .= "'" . $GLOBALS['dbi']->escapeString($dbSeparator) . "'), ";
$query .= "'%s'), ";
$query .= "CONCAT(SCHEMA_NAME, ";
$query .= "'" . $GLOBALS['dbi']->escapeString($dbSeparator) . "')) ";
$query .= "'%s')) ";
$query .= "ORDER BY SCHEMA_NAME ASC";
$retval = $GLOBALS['dbi']->fetchResult($query);
$retval = $GLOBALS['dbi']->fetchResult(
sprintf(
$query,
$dbSeparator,
$dbSeparator,
$dbSeparator
)
);
return $retval;
}

View File

@ -350,6 +350,10 @@ class gettext_reader {
* @return int array index of the right plural form
*/
function select_string($n) {
if (!is_int($n)) {
throw new InvalidArgumentException(
"Select_string only accepts integers: " . $n);
}
$string = $this->get_plural_forms();
$string = str_replace('nplurals',"\$total",$string);
$string = str_replace("n",$n,$string);

View File

@ -906,7 +906,10 @@ function PMA_handleControlRequest()
$messageSuccess = null;
$messageError = null;
if (isset($_REQUEST['slave_changemaster'])) {
if (isset($_REQUEST['slave_changemaster']) && ! $GLOBALS['cfg']['AllowArbitraryServer']) {
$_SESSION['replication']['sr_action_status'] = 'error';
$_SESSION['replication']['sr_action_info'] = __('Connection to server is disabled, please enable $cfg[\'AllowArbitraryServer\'] in phpMyAdmin configuration.');
} elseif (isset($_REQUEST['slave_changemaster'])) {
$result = PMA_handleRequestForSlaveChangeMaster();
} elseif (isset($_REQUEST['sr_slave_server_control'])) {
$result = PMA_handleRequestForSlaveServerControl();

View File

@ -25,17 +25,6 @@ define('CHANGELOG_FILE', './ChangeLog');
*/
define('LICENSE_FILE', './LICENSE');
/**
* Path to config file generated using setup script.
*/
define('SETUP_CONFIG_FILE', './config/config.inc.php');
/**
* Whether setup requires writable directory where config
* file will be generated.
*/
define('SETUP_DIR_WRITABLE', true);
/**
* Directory where SQL scripts to create/upgrade configuration storage reside.
*/

View File

@ -15,28 +15,9 @@ require './lib/common.inc.php';
require './libraries/config/setup.forms.php';
/**
* Loads configuration file path
*
* Do this in a function to avoid messing up with global $cfg
*
* @param string $config_file_path
*
* @return array
*/
function loadConfig($config_file_path)
{
$cfg = array();
if (file_exists($config_file_path)) {
include $config_file_path;
}
return $cfg;
}
$form_display = new FormDisplay($GLOBALS['ConfigFile']);
$form_display->registerForm('_config.php', $forms['_config.php']);
$form_display->save('_config.php');
$config_file_path = $GLOBALS['ConfigFile']->getFilePath();
if (isset($_POST['eol'])) {
$_SESSION['eol'] = ($_POST['eol'] == 'unix') ? 'unix' : 'win';
@ -58,40 +39,6 @@ if (PMA_ifSetOr($_POST['submit_clear'], '')) {
PMA_downloadHeader('config.inc.php', 'text/plain');
echo ConfigGenerator::getConfigFile($GLOBALS['ConfigFile']);
exit;
} elseif (PMA_ifSetOr($_POST['submit_save'], '')) {
//
// Save generated config file on the server
//
$result = @file_put_contents(
$config_file_path,
ConfigGenerator::getConfigFile($GLOBALS['ConfigFile'])
);
if ($result === false) {
$state = 'config_not_saved';
} else {
$state = 'config_saved';
}
header('HTTP/1.1 303 See Other');
header('Location: index.php' . PMA_URL_getCommon() . '&action_done=' . $state);
exit;
} elseif (PMA_ifSetOr($_POST['submit_load'], '')) {
//
// Load config file from the server
//
$GLOBALS['ConfigFile']->setConfigData(
loadConfig($config_file_path)
);
header('HTTP/1.1 303 See Other');
header('Location: index.php' . PMA_URL_getCommon());
exit;
} elseif (PMA_ifSetOr($_POST['submit_delete'], '')) {
//
// Delete config file on the server
//
@unlink($config_file_path);
header('HTTP/1.1 303 See Other');
header('Location: index.php' . PMA_URL_getCommon());
exit;
} else {
//
// Show generated config file in a <textarea>

View File

@ -18,10 +18,6 @@ if (!defined('PHPMYADMIN')) {
require_once './libraries/config/FormDisplay.tpl.php';
require_once './setup/lib/index.lib.php';
$config_readable = false;
$config_writable = false;
$config_exists = false;
PMA_checkConfigRw($config_readable, $config_writable, $config_exists);
echo '<h2>' , __('Configuration file') , '</h2>';
echo PMA_displayFormTop('config.php');
@ -40,11 +36,6 @@ echo '<tr>';
echo '<td class="lastrow" style="text-align: left">';
echo '<input type="submit" name="submit_download" value="'
, __('Download') , '" class="green" />';
echo '<input type="submit" name="submit_save" value="' , __('Save') , '"';
if (!$config_writable) {
echo ' disabled="disabled"';
}
echo '/>';
echo '</td>';
echo '</tr>';

View File

@ -45,26 +45,6 @@ if (isset($_GET['version_check'])) {
$configChecker = new ServerConfigChecks($GLOBALS['ConfigFile']);
$configChecker->performConfigChecks();
//
// Check whether we can read/write configuration
//
$config_readable = false;
$config_writable = false;
$config_exists = false;
PMA_checkConfigRw($config_readable, $config_writable, $config_exists);
if (!$config_writable || !$config_readable) {
PMA_messagesSet(
'error', 'config_rw', __('Cannot load or save configuration'),
PMA_sanitize(
__(
'Please create web server writable folder [em]config[/em] in '
. 'phpMyAdmin top level directory as described in '
. '[doc@setup_script]documentation[/doc]. Otherwise you will be '
. 'only able to download or display it.'
)
)
);
}
//
// Https connection warning (check done on the client side)
//
@ -80,8 +60,7 @@ $text .= __(
$text .= '</a>';
PMA_messagesSet('notice', 'no_https', __('Insecure connection'), $text);
echo '<form id="select_lang" method="post" action="'
, htmlspecialchars($_SERVER['REQUEST_URI']) , '">';
echo '<form id="select_lang" method="post">';
echo PMA_URL_getHiddenInputs();
echo '<bdo lang="en" dir="ltr"><label for="lang">';
echo __('Language') , (__('Language') != 'Language' ? ' - Language' : '');
@ -276,26 +255,6 @@ echo '<tr>';
echo '<td colspan="2" class="lastrow" style="text-align: left">';
echo '<input type="submit" name="submit_display" value="' , __('Display') , '" />';
echo '<input type="submit" name="submit_download" value="' , __('Download') , '" />';
echo '&nbsp; &nbsp;';
echo '<input type="submit" name="submit_save" value="' , __('Save') , '"';
if (!$config_writable) {
echo ' disabled="disabled"';
}
echo '/>';
echo '<input type="submit" name="submit_load" value="' , __('Load') , '"';
if (!$config_exists) {
echo ' disabled="disabled"';
}
echo '/>';
echo '<input type="submit" name="submit_delete" value="' , __('Delete') , '"';
if (!$config_exists || !$config_writable) {
echo ' disabled="disabled"';
}
echo '/>';
echo '&nbsp; &nbsp;';
echo '<input type="submit" name="submit_clear" value="' , __('Clear')
, '" class="red" />';

View File

@ -12,6 +12,10 @@
*/
require './lib/common.inc.php';
if (file_exists(CONFIG_FILE)) {
PMA_fatalError(__('Configuration already exists, setup is disabled!'));
}
$page = PMA_isValid($_GET['page'], 'scalar') ? $_GET['page'] : null;
$page = preg_replace('/[^a-z]/', '', $page);
if ($page === '') {

View File

@ -181,28 +181,3 @@ function PMA_versionCheck()
}
}
}
/**
* Checks whether config file is readable/writable
*
* @param bool &$is_readable whether the file is readable
* @param bool &$is_writable whether the file is writable
* @param bool &$file_exists whether the file exists
*
* @return void
*/
function PMA_checkConfigRw(&$is_readable, &$is_writable, &$file_exists)
{
$file_path = $GLOBALS['ConfigFile']->getFilePath();
$file_dir = dirname($file_path);
$is_readable = true;
$is_writable = @is_dir($file_dir);
if (SETUP_DIR_WRITABLE) {
$is_writable = $is_writable && @is_writable($file_dir);
}
$file_exists = file_exists($file_path);
if ($file_exists) {
$is_readable = is_readable($file_path);
$is_writable = $is_writable && @is_writable($file_path);
}
}

View File

@ -310,6 +310,10 @@ if ($is_insert && count($value_sets) > 0) {
//
// Note: logic passes here for inline edit
$message = PMA\libraries\Message::success(__('No change'));
// Avoid infinite recursion
if ($goto_include == 'tbl_replace.php') {
$goto_include = 'tbl_change.php';
}
$active_page = $goto_include;
include '' . PMA_securePath($goto_include);
exit;

View File

@ -17,12 +17,11 @@ $linkAttribs = isset($linkAttribs) ? $linkAttribs : null;
if (!isset($logo)) {
$logo = null;
if (isset($GLOBALS['pmaThemeImage'])) {
$imgTag = '<img src="' . $GLOBALS['pmaThemeImage'] . '%s" '
. 'alt="phpMyAdmin" id="imgpmalogo" />';
$imgTag = '<img src="%s%s" ' . 'alt="phpMyAdmin" id="imgpmalogo" />';
if (@file_exists($GLOBALS['pmaThemeImage'] . 'logo_left.png')) {
$logo = sprintf($imgTag, 'logo_left.png');
$logo = sprintf($imgTag, $GLOBALS['pmaThemeImage'], 'logo_left.png');
} elseif (@file_exists($GLOBALS['pmaThemeImage'] . 'pma_logo2.png')) {
$logo = sprintf($imgTag, 'pma_logo2.png');
$logo = sprintf($imgTag, $GLOBALS['pmaThemeImage'], 'pma_logo2.png');
}
}
}

View File

@ -577,17 +577,6 @@ class ConfigFileTest extends PMATestCase
);
}
/**
* Test for ConfigFile::getFilePath
*
* @return void
* @test
*/
public function testGetFilePath()
{
$this->assertNotEmpty($this->object->getFilePath());
}
/**
* Test for ConfigFile::getConfigArray
*

View File

@ -160,73 +160,6 @@ class PMA_SetupIndex_Test extends PHPUnit_Framework_TestCase
}
/**
* Test for PMA_checkConfigRw
*
* @return void
*/
public function testPMACheckConfigRw()
{
if (! PMA_HAS_RUNKIT) {
$this->markTestSkipped('Cannot redefine constant');
}
$redefine = null;
$GLOBALS['cfg']['AvailableCharsets'] = array();
$GLOBALS['server'] = 0;
$GLOBALS['ConfigFile'] = new ConfigFile();
if (!defined('SETUP_CONFIG_FILE')) {
define('SETUP_CONFIG_FILE', 'test/test_data/configfile');
} else {
$redefine = 'SETUP_CONFIG_FILE';
runkit_constant_redefine(
'SETUP_CONFIG_FILE',
'test/test_data/configfile'
);
}
$is_readable = false;
$is_writable = false;
$file_exists = false;
PMA_checkConfigRw($is_readable, $is_writable, $file_exists);
$this->assertTrue(
$is_readable
);
$this->assertTrue(
$is_writable
);
$this->assertFalse(
$file_exists
);
runkit_constant_redefine(
'SETUP_CONFIG_FILE',
'test/test_data/test.file'
);
PMA_checkConfigRw($is_readable, $is_writable, $file_exists);
$this->assertTrue(
$is_readable
);
$this->assertTrue(
$is_writable
);
$this->assertTrue(
$file_exists
);
if ($redefine !== null) {
runkit_constant_redefine('SETUP_CONFIG_FILE', $redefine);
} else {
runkit_constant_remove('SETUP_CONFIG_FILE');
}
}
/**
* Test for ServerConfigChecks::performConfigChecks
*

View File

@ -66,6 +66,30 @@ class PMA_CleanupPathInfo_Test extends PHPUnit_Framework_TestCase
'/; cookieinj=value/',
'/phpmyadmin/index.php'
),
array(
'',
'//example.com/../phpmyadmin/index.php',
'',
'/phpmyadmin/index.php'
),
array(
'',
'//example.com/../../.././phpmyadmin/index.php',
'',
'/phpmyadmin/index.php'
),
array(
'',
'/page.php/malicouspathinfo?malicouspathinfo',
'malicouspathinfo',
'/page.php'
),
array(
'/phpmyadmin/./index.php',
'/phpmyadmin/./index.php',
'',
'/phpmyadmin/index.php'
),
array(
'/phpmyadmin/index.php',
'/phpmyadmin/index.php',