Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/phpmyadmin/phpmyadmin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaurĂ­cio Meneghini Fauth <mauricio@fauth.dev>2022-01-10 19:33:03 +0300
committerGitHub <noreply@github.com>2022-01-10 19:33:03 +0300
commitae11d5260b4bde42100c8696218a2bfd11a2d740 (patch)
tree325cd230d1a6b711cdc35dfdc36fa3d55b289cb7 /libraries
parentbfd335bfd4ebff6634a5492d967253c6cf89792f (diff)
parentede23967967ac4e715b2df392a1388c2fb69942b (diff)
Merge pull request #334 from phpmyadmin/security/315
Encrypt the URL query when sensitive data is present
Diffstat (limited to 'libraries')
-rw-r--r--libraries/classes/Controllers/Server/ServerBinlogController.php6
-rw-r--r--libraries/classes/Controllers/Table/TableStructureController.php9
-rw-r--r--libraries/classes/Core.php32
-rw-r--r--libraries/classes/Crypto/Crypto.php155
-rw-r--r--libraries/classes/Display/Results.php135
-rw-r--r--libraries/classes/ErrorReport.php1
-rw-r--r--libraries/classes/Export.php6
-rw-r--r--libraries/classes/Index.php5
-rw-r--r--libraries/classes/InsertEdit.php7
-rw-r--r--libraries/classes/Navigation/Navigation.php2
-rw-r--r--libraries/classes/Navigation/NavigationTree.php49
-rw-r--r--libraries/classes/Navigation/Nodes/NodeDatabase.php2
-rw-r--r--libraries/classes/Navigation/Nodes/NodeDatabaseChild.php2
-rw-r--r--libraries/classes/Operations.php6
-rw-r--r--libraries/classes/ReplicationGui.php18
-rw-r--r--libraries/classes/Rte/RteList.php28
-rw-r--r--libraries/classes/Server/Privileges.php2
-rw-r--r--libraries/classes/Server/Status/Processes.php6
-rw-r--r--libraries/classes/Server/UserGroups.php6
-rw-r--r--libraries/classes/Sql.php2
-rw-r--r--libraries/classes/Tracking.php6
-rw-r--r--libraries/classes/Url.php88
-rw-r--r--libraries/classes/Util.php49
-rw-r--r--libraries/common.inc.php2
-rw-r--r--libraries/config.default.php14
25 files changed, 484 insertions, 154 deletions
diff --git a/libraries/classes/Controllers/Server/ServerBinlogController.php b/libraries/classes/Controllers/Server/ServerBinlogController.php
index 57983ec3d2..807b7223bf 100644
--- a/libraries/classes/Controllers/Server/ServerBinlogController.php
+++ b/libraries/classes/Controllers/Server/ServerBinlogController.php
@@ -193,7 +193,7 @@ class ServerBinlogController extends Controller
}
$html .= '<a href="server_binlog.php" data-post="'
- . Url::getCommon($this_url_params, '') . '"';
+ . Url::getCommon($this_url_params, '', false) . '"';
if (Util::showIcons('TableNavigationLinksMode')) {
$html .= ' title="' . _pgettext('Previous page', 'Previous') . '">';
} else {
@@ -215,7 +215,7 @@ class ServerBinlogController extends Controller
$tempTitle = __('Show Full Queries');
$tempImgMode = 'full';
}
- $html .= '<a href="server_binlog.php" data-post="' . Url::getCommon($this_url_params, '')
+ $html .= '<a href="server_binlog.php" data-post="' . Url::getCommon($this_url_params, '', false)
. '" title="' . $tempTitle . '">'
. '<img src="' . $GLOBALS['pmaThemeImage'] . 's_' . $tempImgMode
. 'text.png" alt="' . $tempTitle . '" /></a>';
@@ -226,7 +226,7 @@ class ServerBinlogController extends Controller
$this_url_params = $url_params;
$this_url_params['pos'] = $pos + $GLOBALS['cfg']['MaxRows'];
$html .= ' - <a href="server_binlog.php" data-post="'
- . Url::getCommon($this_url_params, '')
+ . Url::getCommon($this_url_params, '', false)
. '"';
if (Util::showIcons('TableNavigationLinksMode')) {
$html .= ' title="' . _pgettext('Next page', 'Next') . '">';
diff --git a/libraries/classes/Controllers/Table/TableStructureController.php b/libraries/classes/Controllers/Table/TableStructureController.php
index 5ace136ab6..80dccdb8e5 100644
--- a/libraries/classes/Controllers/Table/TableStructureController.php
+++ b/libraries/classes/Controllers/Table/TableStructureController.php
@@ -1241,13 +1241,6 @@ class TableStructureController extends TableController
'DistinctValues' => Util::getIcon('b_browse', __('Distinct values')),
);
- $edit_view_url = '';
- if ($this->_tbl_is_view && ! $this->_db_is_system_schema) {
- $edit_view_url = Url::getCommon(
- array('db' => $this->db, 'table' => $this->table)
- );
- }
-
/**
* Displays Space usage and row statistics
*/
@@ -1275,11 +1268,11 @@ class TableStructureController extends TableController
'tbl_is_view' => $this->_tbl_is_view,
'mime_map' => $mime_map,
'url_query' => $this->_url_query,
+ 'url_params' => $url_params,
'titles' => $titles,
'tbl_storage_engine' => $this->_tbl_storage_engine,
'primary' => $primary_index,
'columns_with_unique_index' => $columns_with_unique_index,
- 'edit_view_url' => $edit_view_url,
'columns_list' => $columns_list,
'table_stats' => isset($tablestats) ? $tablestats : null,
'fields' => $fields,
diff --git a/libraries/classes/Core.php b/libraries/classes/Core.php
index bf5edde41a..621544edf5 100644
--- a/libraries/classes/Core.php
+++ b/libraries/classes/Core.php
@@ -1317,4 +1317,36 @@ class Core
$hmac = hash_hmac('sha256', $sqlQuery, $_SESSION[' HMAC_secret '] . $cfg['blowfish_secret']);
return hash_equals($hmac, $signature);
}
+
+ /**
+ * @return void
+ */
+ public static function populateRequestWithEncryptedQueryParams()
+ {
+ if (
+ (! isset($_GET['eq']) || ! is_string($_GET['eq']))
+ && (! isset($_POST['eq']) || ! is_string($_POST['eq']))
+ ) {
+ unset($_GET['eq'], $_POST['eq'], $_REQUEST['eq']);
+ return;
+ }
+
+ $isFromPost = isset($_POST['eq']);
+ $decryptedQuery = Url::decryptQuery($isFromPost ? $_POST['eq'] : $_GET['eq']);
+ unset($_GET['eq'], $_POST['eq'], $_REQUEST['eq']);
+ if ($decryptedQuery === null) {
+ return;
+ }
+
+ $urlQueryParams = (array) json_decode($decryptedQuery);
+ foreach ($urlQueryParams as $urlQueryParamKey => $urlQueryParamValue) {
+ if ($isFromPost) {
+ $_POST[$urlQueryParamKey] = $urlQueryParamValue;
+ } else {
+ $_GET[$urlQueryParamKey] = $urlQueryParamValue;
+ }
+
+ $_REQUEST[$urlQueryParamKey] = $urlQueryParamValue;
+ }
+ }
}
diff --git a/libraries/classes/Crypto/Crypto.php b/libraries/classes/Crypto/Crypto.php
new file mode 100644
index 0000000000..6449f7dca5
--- /dev/null
+++ b/libraries/classes/Crypto/Crypto.php
@@ -0,0 +1,155 @@
+<?php
+
+namespace PhpMyAdmin\Crypto;
+
+use phpseclib\Crypt\AES;
+use phpseclib\Crypt\Random;
+
+final class Crypto
+{
+ /** @var bool */
+ private $hasRandomBytesSupport;
+
+ /** @var bool */
+ private $hasSodiumSupport;
+
+ /**
+ * @param bool $forceFallback Force the usage of the fallback functions.
+ */
+ public function __construct($forceFallback = false)
+ {
+ $this->hasRandomBytesSupport = ! $forceFallback && is_callable('random_bytes');
+ $this->hasSodiumSupport = ! $forceFallback
+ && $this->hasRandomBytesSupport
+ && is_callable('sodium_crypto_secretbox')
+ && is_callable('sodium_crypto_secretbox_open')
+ && defined('SODIUM_CRYPTO_SECRETBOX_NONCEBYTES')
+ && defined('SODIUM_CRYPTO_SECRETBOX_KEYBYTES');
+ }
+
+ /**
+ * @param string $plaintext
+ *
+ * @return string
+ */
+ public function encrypt($plaintext)
+ {
+ if ($this->hasSodiumSupport) {
+ return $this->encryptWithSodium($plaintext);
+ }
+
+ return $this->encryptWithPhpseclib($plaintext);
+ }
+
+ /**
+ * @param string $ciphertext
+ *
+ * @return string
+ */
+ public function decrypt($ciphertext)
+ {
+ if ($this->hasSodiumSupport) {
+ return $this->decryptWithSodium($ciphertext);
+ }
+
+ return $this->decryptWithPhpseclib($ciphertext);
+ }
+
+ /**
+ * @return string
+ */
+ private function getEncryptionKey()
+ {
+ global $PMA_Config;
+
+ $keyLength = $this->hasSodiumSupport ? SODIUM_CRYPTO_SECRETBOX_KEYBYTES : 32;
+
+ $key = $PMA_Config->get('URLQueryEncryptionSecretKey');
+ if (is_string($key) && mb_strlen($key, '8bit') === $keyLength) {
+ return $key;
+ }
+
+ $key = isset($_SESSION['URLQueryEncryptionSecretKey']) ? $_SESSION['URLQueryEncryptionSecretKey'] : null;
+ if (is_string($key) && mb_strlen($key, '8bit') === $keyLength) {
+ return $key;
+ }
+
+ $key = $this->hasRandomBytesSupport ? random_bytes($keyLength) : Random::string($keyLength);
+ $_SESSION['URLQueryEncryptionSecretKey'] = $key;
+
+ return $key;
+ }
+
+ /**
+ * @param string $plaintext
+ *
+ * @return string
+ */
+ private function encryptWithPhpseclib($plaintext)
+ {
+ $key = $this->getEncryptionKey();
+ $cipher = new AES(AES::MODE_CBC);
+ $iv = $this->hasRandomBytesSupport ? random_bytes(16) : Random::string(16);
+ $cipher->setIV($iv);
+ $cipher->setKey($key);
+ $ciphertext = $cipher->encrypt($plaintext);
+ $hmac = hash_hmac('sha256', $iv . $ciphertext, $key, true);
+
+ return $hmac . $iv . $ciphertext;
+ }
+
+ /**
+ * @param string $encrypted
+ *
+ * @return string|null
+ */
+ private function decryptWithPhpseclib($encrypted)
+ {
+ $key = $this->getEncryptionKey();
+ $hmac = mb_substr($encrypted, 0, 32, '8bit');
+ $iv = mb_substr($encrypted, 32, 16, '8bit');
+ $ciphertext = mb_substr($encrypted, 48, null, '8bit');
+ $calculatedHmac = hash_hmac('sha256', $iv . $ciphertext, $key, true);
+ if (! hash_equals($hmac, $calculatedHmac)) {
+ return null;
+ }
+
+ $cipher = new AES(AES::MODE_CBC);
+ $cipher->setIV($iv);
+ $cipher->setKey($key);
+
+ return $cipher->decrypt($ciphertext);
+ }
+
+ /**
+ * @param string $plaintext
+ *
+ * @return string
+ */
+ private function encryptWithSodium($plaintext)
+ {
+ $key = $this->getEncryptionKey();
+ $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
+ $ciphertext = sodium_crypto_secretbox($plaintext, $nonce, $key);
+
+ return $nonce . $ciphertext;
+ }
+
+ /**
+ * @param string $encrypted
+ *
+ * @return string|null
+ */
+ private function decryptWithSodium($encrypted)
+ {
+ $key = $this->getEncryptionKey();
+ $nonce = mb_substr($encrypted, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit');
+ $ciphertext = mb_substr($encrypted, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');
+ $decrypted = sodium_crypto_secretbox_open($ciphertext, $nonce, $key);
+ if ($decrypted === false) {
+ return null;
+ }
+
+ return $decrypted;
+ }
+}
diff --git a/libraries/classes/Display/Results.php b/libraries/classes/Display/Results.php
index 6809c227c9..e371df95c4 100644
--- a/libraries/classes/Display/Results.php
+++ b/libraries/classes/Display/Results.php
@@ -1736,9 +1736,8 @@ class Results
$tmp_image = '<img class="fulltext" src="' . $tmp_image_file . '" alt="'
. $tmp_txt . '" title="' . $tmp_txt . '" />';
- $tmp_url = 'sql.php' . Url::getCommon($url_params_full_text);
- return Util::linkOrButton($tmp_url, $tmp_image);
+ return Util::linkOrButton('sql.php', $url_params_full_text, $tmp_image);
} // end of the '_getFullOrPartialTextButtonOrLink()' function
@@ -1869,13 +1868,11 @@ class Results
'session_max_rows' => $session_max_rows,
'is_browse_distinct' => $this->__get('is_browse_distinct'),
);
- $single_order_url = 'sql.php' . Url::getCommon($_single_url_params);
- $multi_order_url = 'sql.php' . Url::getCommon($_multi_url_params);
// Displays the sorting URL
// enable sort order swapping for image
$order_link = $this->_getSortOrderLink(
- $order_img, $fields_meta, $single_order_url, $multi_order_url
+ $order_img, $fields_meta, $_single_url_params, $_multi_url_params
);
$sorted_header_html .= $this->_getDraggableClassForSortableColumns(
@@ -2143,10 +2140,10 @@ class Results
/**
* Get sort order link
*
- * @param string $order_img the sort order image
- * @param array $fields_meta set of field properties
- * @param string $order_url the url for sort
- * @param string $multi_order_url the url for sort
+ * @param string $order_img the sort order image
+ * @param array $fields_meta set of field properties
+ * @param array $order_url_params the url params for sort
+ * @param array $multi_order_url_params the url params for sort
*
* @return string the sort order link
*
@@ -2155,7 +2152,7 @@ class Results
* @see _getTableHeaders()
*/
private function _getSortOrderLink(
- $order_img, $fields_meta, $order_url, $multi_order_url
+ $order_img, $fields_meta, $order_url_params, $multi_order_url_params
) {
$order_link_params = array(
'class' => 'sortlink'
@@ -2163,10 +2160,12 @@ class Results
$order_link_content = htmlspecialchars($fields_meta->name);
$inner_link_content = $order_link_content . $order_img
- . '<input type="hidden" value="' . $multi_order_url . '" />';
+ . '<input type="hidden" value="sql.php'
+ . Url::getCommon($multi_order_url_params, '?', false)
+ . '" />';
return Util::linkOrButton(
- $order_url, $inner_link_content, $order_link_params
+ 'sql.php', $order_url_params, $inner_link_content, $order_link_params
);
} // end of the '_getSortOrderLink()' function
@@ -2608,7 +2607,7 @@ class Results
// 1. Prepares the row
// In print view these variable needs to be initialized
- $del_url = $del_str = $edit_anchor_class
+ $del_url = $del_str = $edit_anchor_class = $editCopyUrlParams = $delUrlParams
= $edit_str = $js_conf = $copy_url = $copy_str = $edit_url = null;
// 1.2 Defines the URLs for the modify/delete link(s)
@@ -2643,7 +2642,7 @@ class Results
if ($displayParts['edit_lnk'] == self::UPDATE_ROW) {
list($edit_url, $copy_url, $edit_str, $copy_str,
- $edit_anchor_class)
+ $edit_anchor_class, $editCopyUrlParams)
= $this->_getModifiedLinks(
$where_clause,
$clause_is_unique, $url_sql_query
@@ -2652,7 +2651,7 @@ class Results
} // end if (1.2.1)
// 1.2.2 Delete/Kill link(s)
- list($del_url, $del_str, $js_conf)
+ list($del_url, $del_str, $js_conf, $delUrlParams)
= $this->_getDeleteAndKillLinks(
$where_clause, $clause_is_unique,
$url_sql_query, $displayParts['del_lnk'],
@@ -2668,7 +2667,7 @@ class Results
self::POSITION_LEFT, $del_url, $displayParts, $row_no,
$where_clause, $where_clause_html, $condition_array,
$edit_url, $copy_url, $edit_anchor_class,
- $edit_str, $copy_str, $del_str, $js_conf
+ $edit_str, $copy_str, $del_str, $js_conf, $editCopyUrlParams, $delUrlParams
);
} elseif ($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_NONE) {
@@ -2677,7 +2676,7 @@ class Results
self::POSITION_NONE, $del_url, $displayParts, $row_no,
$where_clause, $where_clause_html, $condition_array,
$edit_url, $copy_url, $edit_anchor_class,
- $edit_str, $copy_str, $del_str, $js_conf
+ $edit_str, $copy_str, $del_str, $js_conf, $editCopyUrlParams, $delUrlParams
);
} // end if (1.3)
@@ -2711,7 +2710,7 @@ class Results
self::POSITION_RIGHT, $del_url, $displayParts, $row_no,
$where_clause, $where_clause_html, $condition_array,
$edit_url, $copy_url, $edit_anchor_class,
- $edit_str, $copy_str, $del_str, $js_conf
+ $edit_str, $copy_str, $del_str, $js_conf, $editCopyUrlParams, $delUrlParams
);
}
@@ -3327,15 +3326,9 @@ class Results
'goto' => 'sql.php',
);
- $edit_url = 'tbl_change.php'
- . Url::getCommon(
- $_url_params + array('default_action' => 'update')
- );
+ $edit_url = 'tbl_change.php';
- $copy_url = 'tbl_change.php'
- . Url::getCommon(
- $_url_params + array('default_action' => 'insert')
- );
+ $copy_url = 'tbl_change.php';
$edit_str = $this->_getActionLinkContent(
'b_edit', __('Edit')
@@ -3350,7 +3343,7 @@ class Results
$edit_anchor_class .= ' nonunique';
}
- return array($edit_url, $copy_url, $edit_str, $copy_str, $edit_anchor_class);
+ return array($edit_url, $copy_url, $edit_str, $copy_str, $edit_anchor_class, $_url_params);
} // end of the '_getModifiedLinks()' function
@@ -3401,7 +3394,7 @@ class Results
'message_to_show' => __('The row has been deleted.'),
'goto' => $lnk_goto,
);
- $del_url = 'sql.php' . Url::getCommon($_url_params);
+ $del_url = 'sql.php';
$js_conf = 'DELETE FROM ' . Sanitize::jsFormat($this->__get('table'))
. ' WHERE ' . Sanitize::jsFormat($where_clause, false)
@@ -3428,16 +3421,16 @@ class Results
'goto' => $lnk_goto,
);
- $del_url = 'sql.php' . Url::getCommon($_url_params);
+ $del_url = 'sql.php';
$js_conf = $kill;
$del_str = Util::getIcon(
'b_drop', __('Kill')
);
} else {
- $del_url = $del_str = $js_conf = null;
+ $del_url = $del_str = $js_conf = $_url_params = null;
}
- return array($del_url, $del_str, $js_conf);
+ return array($del_url, $del_str, $js_conf, $_url_params);
} // end of the '_getDeleteAndKillLinks()' function
@@ -3505,6 +3498,8 @@ class Results
* @param string $copy_str the label for copy row
* @param string $del_str the label for delete row
* @param string $js_conf text for the JS confirmation
+ * @param array $editCopyUrlParams URL parameters
+ * @param array $delUrlParams URL parameters
*
* @return string html content
*
@@ -3515,7 +3510,7 @@ class Results
private function _getPlacedLinks(
$dir, $del_url, array $displayParts, $row_no, $where_clause, $where_clause_html,
array $condition_array, $edit_url, $copy_url,
- $edit_anchor_class, $edit_str, $copy_str, $del_str, $js_conf
+ $edit_anchor_class, $edit_str, $copy_str, $del_str, $js_conf, $editCopyUrlParams, $delUrlParams
) {
if (! isset($js_conf)) {
@@ -3526,7 +3521,7 @@ class Results
$dir, $del_url, $displayParts,
$row_no, $where_clause, $where_clause_html, $condition_array,
$edit_url, $copy_url, $edit_anchor_class,
- $edit_str, $copy_str, $del_str, $js_conf
+ $edit_str, $copy_str, $del_str, $js_conf, $editCopyUrlParams, $delUrlParams
);
} // end of the '_getPlacedLinks()' function
@@ -4804,8 +4799,8 @@ class Results
/**
* Generates HTML to display the Create view in span tag
*
- * @param array $analyzed_sql_results analyzed sql results
- * @param string $url_query String with URL Parameters
+ * @param array $analyzed_sql_results analyzed sql results
+ * @param array $url_query URL Parameters
*
* @return string
*
@@ -4813,14 +4808,15 @@ class Results
*
* @see _getResultsOperations()
*/
- private function _getLinkForCreateView(array $analyzed_sql_results, $url_query)
+ private function _getLinkForCreateView(array $analyzed_sql_results, $urlParams)
{
$results_operations_html = '';
if (empty($analyzed_sql_results['procedure'])) {
$results_operations_html .= '<span>'
. Util::linkOrButton(
- 'view_create.php' . $url_query,
+ 'view_create.php',
+ $urlParams,
Util::getIcon(
'b_view_add', __('Create view'), true
),
@@ -4867,6 +4863,7 @@ class Results
{
$html = Util::linkOrButton(
'#',
+ null,
Util::getIcon(
'b_insrow', __('Copy to clipboard'), true
),
@@ -4887,6 +4884,7 @@ class Results
{
$html = Util::linkOrButton(
'#',
+ null,
Util::getIcon(
'b_print', __('Print'), true
),
@@ -4927,7 +4925,6 @@ class Results
'printview' => '1',
'sql_query' => $this->__get('sql_query'),
);
- $url_query = Url::getCommon($_url_params);
if (!$header_shown) {
$results_operations_html .= $header;
@@ -4937,7 +4934,7 @@ class Results
// show only view and not other options
if ($only_view) {
$results_operations_html .= $this->_getLinkForCreateView(
- $analyzed_sql_results, $url_query
+ $analyzed_sql_results, $_url_params
);
if ($header_shown) {
@@ -4992,7 +4989,8 @@ class Results
}
$results_operations_html .= Util::linkOrButton(
- 'tbl_export.php' . Url::getCommon($_url_params),
+ 'tbl_export.php',
+ $_url_params,
Util::getIcon(
'b_tblexport', __('Export'), true
)
@@ -5001,7 +4999,8 @@ class Results
// prepare chart
$results_operations_html .= Util::linkOrButton(
- 'tbl_chart.php' . Url::getCommon($_url_params),
+ 'tbl_chart.php',
+ $_url_params,
Util::getIcon(
'b_chart', __('Display chart'), true
)
@@ -5021,8 +5020,8 @@ class Results
if ($geometry_found) {
$results_operations_html
.= Util::linkOrButton(
- 'tbl_gis_visualization.php'
- . Url::getCommon($_url_params),
+ 'tbl_gis_visualization.php',
+ $_url_params,
Util::getIcon(
'b_globe',
__('Visualize GIS data'),
@@ -5047,7 +5046,7 @@ class Results
}
$results_operations_html .= $this->_getLinkForCreateView(
- $analyzed_sql_results, $url_query
+ $analyzed_sql_results, $_url_params
);
if ($header_shown) {
@@ -5367,7 +5366,7 @@ class Results
$tag_params['class'] = 'ajax';
}
$result .= Util::linkOrButton(
- 'sql.php' . Url::getCommon($_url_params),
+ 'sql.php', $_url_params,
$displayedData, $tag_params
);
}
@@ -5443,6 +5442,7 @@ class Results
* Prepares an Edit link
*
* @param string $edit_url edit url
+ * @param array $urlParams URL parameters
* @param string $class css classes for td element
* @param string $edit_str text for the edit link
* @param string $where_clause where clause
@@ -5455,7 +5455,7 @@ class Results
* @see _getTableBody(), _getCheckboxAndLinks()
*/
private function _getEditLink(
- $edit_url, $class, $edit_str, $where_clause, $where_clause_html
+ $edit_url, $urlParams, $class, $edit_str, $where_clause, $where_clause_html
) {
$ret = '';
@@ -5463,7 +5463,7 @@ class Results
$ret .= '<td class="' . $class . ' center print_ignore" '
. ' ><span class="nowrap">'
- . Util::linkOrButton($edit_url, $edit_str);
+ . Util::linkOrButton($edit_url, $urlParams, $edit_str);
/*
* Where clause for selecting this row uniquely is provided as
* a hidden input. Used by jQuery scripts for handling grid editing
@@ -5484,6 +5484,7 @@ class Results
* Prepares an Copy link
*
* @param string $copy_url copy url
+ * @param array $urlParams URL parameters
* @param string $copy_str text for the copy link
* @param string $where_clause where clause
* @param string $where_clause_html url encoded where clause
@@ -5496,7 +5497,7 @@ class Results
* @see _getTableBody(), _getCheckboxAndLinks()
*/
private function _getCopyLink(
- $copy_url, $copy_str, $where_clause, $where_clause_html, $class
+ $copy_url, $urlParams, $copy_str, $where_clause, $where_clause_html, $class
) {
$ret = '';
@@ -5508,7 +5509,7 @@ class Results
}
$ret .= 'center print_ignore" ' . ' ><span class="nowrap">'
- . Util::linkOrButton($copy_url, $copy_str);
+ . Util::linkOrButton($copy_url, $urlParams, $copy_str);
/*
* Where clause for selecting this row uniquely is provided as
@@ -5529,10 +5530,11 @@ class Results
/**
* Prepares a Delete link
*
- * @param string $del_url delete url
- * @param string $del_str text for the delete link
- * @param string $js_conf text for the JS confirmation
- * @param string $class css classes for the td element
+ * @param string $del_url delete url
+ * @param array $delUrlParams URL parameters
+ * @param string $del_str text for the delete link
+ * @param string $js_conf text for the JS confirmation
+ * @param string $class css classes for the td element
*
* @return string the generated HTML
*
@@ -5540,7 +5542,7 @@ class Results
*
* @see _getTableBody(), _getCheckboxAndLinks()
*/
- private function _getDeleteLink($del_url, $del_str, $js_conf, $class)
+ private function _getDeleteLink($del_url, $delUrlParams, $del_str, $js_conf, $class)
{
$ret = '';
@@ -5556,6 +5558,7 @@ class Results
$ret .= 'center print_ignore" ' . ' >'
. Util::linkOrButton(
$del_url,
+ $delUrlParams,
$del_str,
array('class' => 'delete_row requireConfirm' . $ajax)
)
@@ -5586,6 +5589,8 @@ class Results
* @param string $copy_str text for the copy link
* @param string $del_str text for the delete link
* @param string $js_conf text for the JS confirmation
+ * @param array $editCopyUrlParams URL parameters
+ * @param array $delUrlParams URL parameters
*
* @return string the generated HTML
*
@@ -5596,49 +5601,51 @@ class Results
private function _getCheckboxAndLinks(
$position, $del_url, array $displayParts, $row_no, $where_clause,
$where_clause_html, array $condition_array,
- $edit_url, $copy_url, $class, $edit_str, $copy_str, $del_str, $js_conf
+ $edit_url, $copy_url, $class, $edit_str, $copy_str, $del_str, $js_conf, $editCopyUrlParams, $delUrlParams
) {
$ret = '';
+ $editUrlParams = $editCopyUrlParams + array('default_action' => 'update');
+ $copyUrlParams = $editCopyUrlParams + array('default_action' => 'insert');
if ($position == self::POSITION_LEFT) {
$ret .= $this->_getCheckboxForMultiRowSubmissions(
- $del_url, $displayParts, $row_no, $where_clause_html,
+ $del_url . Url::getCommon($delUrlParams), $displayParts, $row_no, $where_clause_html,
$condition_array, '_left', ''
);
$ret .= $this->_getEditLink(
- $edit_url, $class, $edit_str, $where_clause, $where_clause_html
+ $edit_url, $editUrlParams, $class, $edit_str, $where_clause, $where_clause_html
);
$ret .= $this->_getCopyLink(
- $copy_url, $copy_str, $where_clause, $where_clause_html, ''
+ $copy_url, $copyUrlParams, $copy_str, $where_clause, $where_clause_html, ''
);
- $ret .= $this->_getDeleteLink($del_url, $del_str, $js_conf, '');
+ $ret .= $this->_getDeleteLink($del_url, $delUrlParams, $del_str, $js_conf, '');
} elseif ($position == self::POSITION_RIGHT) {
- $ret .= $this->_getDeleteLink($del_url, $del_str, $js_conf, '');
+ $ret .= $this->_getDeleteLink($del_url, $delUrlParams, $del_str, $js_conf, '');
$ret .= $this->_getCopyLink(
- $copy_url, $copy_str, $where_clause, $where_clause_html, ''
+ $copy_url, $copyUrlParams, $copy_str, $where_clause, $where_clause_html, ''
);
$ret .= $this->_getEditLink(
- $edit_url, $class, $edit_str, $where_clause, $where_clause_html
+ $edit_url, $editUrlParams, $class, $edit_str, $where_clause, $where_clause_html
);
$ret .= $this->_getCheckboxForMultiRowSubmissions(
- $del_url, $displayParts, $row_no, $where_clause_html,
+ $del_url . Url::getCommon($delUrlParams), $displayParts, $row_no, $where_clause_html,
$condition_array, '_right', ''
);
} else { // $position == self::POSITION_NONE
$ret .= $this->_getCheckboxForMultiRowSubmissions(
- $del_url, $displayParts, $row_no, $where_clause_html,
+ $del_url . Url::getCommon($delUrlParams), $displayParts, $row_no, $where_clause_html,
$condition_array, '_left', ''
);
}
diff --git a/libraries/classes/ErrorReport.php b/libraries/classes/ErrorReport.php
index 6a3e65a230..3abef4815d 100644
--- a/libraries/classes/ErrorReport.php
+++ b/libraries/classes/ErrorReport.php
@@ -197,6 +197,7 @@ class ErrorReport
unset($queryArray["table"]);
unset($queryArray["token"]);
unset($queryArray["server"]);
+ unset($queryArray["eq"]);
$query = http_build_query($queryArray);
} else {
$query = '';
diff --git a/libraries/classes/Export.php b/libraries/classes/Export.php
index e4d028b224..affcc00af2 100644
--- a/libraries/classes/Export.php
+++ b/libraries/classes/Export.php
@@ -479,14 +479,14 @@ class Export
*/
$back_button = '<p id="export_back_button">[ <a href="';
if ($export_type == 'server') {
- $back_button .= 'server_export.php" data-post="' . Url::getCommon([], '');
+ $back_button .= 'server_export.php" data-post="' . Url::getCommon([], '', false);
} elseif ($export_type == 'database') {
- $back_button .= 'db_export.php" data-post="' . Url::getCommon(array('db' => $db), '');
+ $back_button .= 'db_export.php" data-post="' . Url::getCommon(array('db' => $db), '', false);
} else {
$back_button .= 'tbl_export.php" data-post="' . Url::getCommon(
array(
'db' => $db, 'table' => $table
- ), ''
+ ), '', false
);
}
diff --git a/libraries/classes/Index.php b/libraries/classes/Index.php
index 4c6aebde0d..d1f12a032c 100644
--- a/libraries/classes/Index.php
+++ b/libraries/classes/Index.php
@@ -741,7 +741,7 @@ class Index
$r .= '" ' . $row_span . '>'
. ' <a class="';
$r .= 'ajax';
- $r .= '" href="tbl_indexes.php" data-post="' . Url::getCommon($this_params, '')
+ $r .= '" href="tbl_indexes.php" data-post="' . Url::getCommon($this_params, '', false)
. '">' . Util::getIcon('b_edit', __('Edit')) . '</a>'
. '</td>' . "\n";
$this_params = $GLOBALS['url_params'];
@@ -766,7 +766,8 @@ class Index
$r .= '<input type="hidden" class="drop_primary_key_index_msg"'
. ' value="' . $js_msg . '" />';
$r .= Util::linkOrButton(
- 'sql.php' . Url::getCommon($this_params),
+ 'sql.php',
+ $this_params,
Util::getIcon('b_drop', __('Drop')),
array('class' => 'drop_primary_key_index_anchor ajax')
);
diff --git a/libraries/classes/InsertEdit.php b/libraries/classes/InsertEdit.php
index ad692f0509..99201cde7e 100644
--- a/libraries/classes/InsertEdit.php
+++ b/libraries/classes/InsertEdit.php
@@ -280,12 +280,12 @@ class InsertEdit
if (! $is_show) {
return ' : <a href="tbl_change.php" data-post="'
- . Url::getCommon($this_url_params, '') . '">'
+ . Url::getCommon($this_url_params, '', false) . '">'
. $this->showTypeOrFunctionLabel($which)
. '</a>';
}
return '<th><a href="tbl_change.php" data-post="'
- . Url::getCommon($this_url_params, '')
+ . Url::getCommon($this_url_params, '', false)
. '" title="' . __('Hide') . '">'
. $this->showTypeOrFunctionLabel($which)
. '</a></th>';
@@ -857,7 +857,7 @@ class InsertEdit
'rownumber' => $rownumber,
'data' => $data
),
- ''
+ '', false
) . '">'
. str_replace("'", "\'", $titles['Browse']) . '</a>';
return $html_output;
@@ -1704,6 +1704,7 @@ class InsertEdit
return '<span class="open_gis_editor">'
. Util::linkOrButton(
'#',
+ null,
$edit_str,
array(),
'_blank'
diff --git a/libraries/classes/Navigation/Navigation.php b/libraries/classes/Navigation/Navigation.php
index 486bd2f74c..145167a45a 100644
--- a/libraries/classes/Navigation/Navigation.php
+++ b/libraries/classes/Navigation/Navigation.php
@@ -231,7 +231,7 @@ class Navigation
$html .= '<tr>';
$html .= '<td>' . htmlspecialchars($hiddenItem) . '</td>';
$html .= '<td style="width:80px"><a href="navigation.php" data-post="'
- . Url::getCommon($params, '') . '"'
+ . Url::getCommon($params, '', false) . '"'
. ' class="unhideNavItem ajax">'
. Util::getIcon('show', __('Show'))
. '</a></td>';
diff --git a/libraries/classes/Navigation/NavigationTree.php b/libraries/classes/Navigation/NavigationTree.php
index 78659a4b7f..1bc35947de 100644
--- a/libraries/classes/Navigation/NavigationTree.php
+++ b/libraries/classes/Navigation/NavigationTree.php
@@ -102,13 +102,13 @@ class NavigationTree
$this->_pos = $this->_getNavigationDbPos();
}
// Get the active node
- if (isset($_REQUEST['aPath'])) {
- $this->_aPath[0] = $this->_parsePath($_REQUEST['aPath']);
- $this->_pos2_name[0] = $_REQUEST['pos2_name'];
- $this->_pos2_value[0] = $_REQUEST['pos2_value'];
- if (isset($_REQUEST['pos3_name'])) {
- $this->_pos3_name[0] = $_REQUEST['pos3_name'];
- $this->_pos3_value[0] = $_REQUEST['pos3_value'];
+ if (isset($_POST['aPath'])) {
+ $this->_aPath[0] = $this->_parsePath($_POST['aPath']);
+ $this->_pos2_name[0] = $_POST['pos2_name'];
+ $this->_pos2_value[0] = $_POST['pos2_value'];
+ if (isset($_POST['pos3_name'])) {
+ $this->_pos3_name[0] = $_POST['pos3_name'];
+ $this->_pos3_value[0] = $_POST['pos3_value'];
}
} else {
if (isset($_POST['n0_aPath'])) {
@@ -129,8 +129,8 @@ class NavigationTree
}
}
}
- if (isset($_REQUEST['vPath'])) {
- $this->_vPath[0] = $this->_parsePath($_REQUEST['vPath']);
+ if (isset($_POST['vPath'])) {
+ $this->_vPath[0] = $this->_parsePath($_POST['vPath']);
} else {
if (isset($_POST['n0_vPath'])) {
$count = 0;
@@ -142,11 +142,11 @@ class NavigationTree
}
}
}
- if (isset($_REQUEST['searchClause'])) {
- $this->_searchClause = $_REQUEST['searchClause'];
+ if (isset($_POST['searchClause'])) {
+ $this->_searchClause = $_POST['searchClause'];
}
- if (isset($_REQUEST['searchClause2'])) {
- $this->_searchClause2 = $_REQUEST['searchClause2'];
+ if (isset($_POST['searchClause2'])) {
+ $this->_searchClause2 = $_POST['searchClause2'];
}
// Initialise the tree by creating a root node
$node = NodeFactory::getInstance('NodeDatabaseContainer', 'root');
@@ -1156,7 +1156,7 @@ class NavigationTree
}
foreach ($icons as $key => $icon) {
- $link = vsprintf($iconLinks[$key], $args);
+ $link = $this->encryptQueryParams(vsprintf($iconLinks[$key], $args));
if ($linkClass != '') {
$retval .= "<a class='$linkClass' href='$link'>";
$retval .= "{$icon}</a>";
@@ -1174,7 +1174,7 @@ class NavigationTree
foreach ($node->parents(true) as $parent) {;
$args[] = urlencode($parent->real_name);
}
- $link = vsprintf($node->links['text'], $args);
+ $link = $this->encryptQueryParams(vsprintf($node->links['text'], $args));
$title = isset($node->links['title']) ? $node->links['title'] : '';
if ($node->type == Node::CONTAINER) {
$retval .= "&nbsp;<a class='hover_show_full' href='$link'>";
@@ -1557,4 +1557,23 @@ class NavigationTree
return $retval;
}
+
+ /**
+ * @param string $link
+ *
+ * @return string
+ */
+ private function encryptQueryParams($link)
+ {
+ global $PMA_Config;
+
+ if (! $PMA_Config->get('URLQueryEncryption')) {
+ return $link;
+ }
+
+ $url = parse_url($link);
+ parse_str(htmlspecialchars_decode($url['query']), $query);
+
+ return $url['path'] . '?' . htmlspecialchars(Url::buildHttpQuery($query));
+ }
}
diff --git a/libraries/classes/Navigation/Nodes/NodeDatabase.php b/libraries/classes/Navigation/Nodes/NodeDatabase.php
index d9828a02f6..0844f56380 100644
--- a/libraries/classes/Navigation/Nodes/NodeDatabase.php
+++ b/libraries/classes/Navigation/Nodes/NodeDatabase.php
@@ -678,7 +678,7 @@ class NodeDatabase extends Node
);
$ret = '<span class="dbItemControls">'
. '<a href="navigation.php" data-post="'
- . Url::getCommon($params, '') . '"'
+ . Url::getCommon($params, '', false) . '"'
. ' class="showUnhide ajax">'
. Util::getImage(
'show',
diff --git a/libraries/classes/Navigation/Nodes/NodeDatabaseChild.php b/libraries/classes/Navigation/Nodes/NodeDatabaseChild.php
index ecae8fab2d..e562af0b74 100644
--- a/libraries/classes/Navigation/Nodes/NodeDatabaseChild.php
+++ b/libraries/classes/Navigation/Nodes/NodeDatabaseChild.php
@@ -49,7 +49,7 @@ abstract class NodeDatabaseChild extends Node
$ret = '<span class="navItemControls">'
. '<a href="navigation.php" data-post="'
- . Url::getCommon($params, '') . '"'
+ . Url::getCommon($params, '', false) . '"'
. ' class="hideNavItem ajax">'
. Util::getImage('hide', __('Hide'))
. '</a></span>';
diff --git a/libraries/classes/Operations.php b/libraries/classes/Operations.php
index 620031f7ac..df94c04c71 100644
--- a/libraries/classes/Operations.php
+++ b/libraries/classes/Operations.php
@@ -1507,7 +1507,8 @@ class Operations
{
return '<li>'
. Util::linkOrButton(
- 'sql.php' . Url::getCommon(array_merge($url_params, $params)),
+ 'sql.php',
+ array_merge($url_params, $params),
$action_message,
['class' => 'maintain_action ajax']
)
@@ -1567,7 +1568,8 @@ class Operations
public function getDeleteDataOrTablelink(array $url_params, $syntax, $link, $htmlId)
{
return '<li>' . Util::linkOrButton(
- 'sql.php' . Url::getCommon($url_params),
+ 'sql.php',
+ $url_params,
$link,
array('id' => $htmlId, 'class' => 'ajax')
)
diff --git a/libraries/classes/ReplicationGui.php b/libraries/classes/ReplicationGui.php
index f9e3534df8..e1f0e1e5ff 100644
--- a/libraries/classes/ReplicationGui.php
+++ b/libraries/classes/ReplicationGui.php
@@ -73,7 +73,7 @@ class ReplicationGui
$_url_params['repl_clear_scr'] = true;
$html .= ' <li><a href="server_replication.php" data-post="';
- $html .= Url::getCommon($_url_params, '')
+ $html .= Url::getCommon($_url_params, '', false)
. '" id="master_addslaveuser_href">';
$html .= __('Add slave replication user') . '</a></li>';
}
@@ -188,7 +188,7 @@ class ReplicationGui
}
$_url_params['sr_slave_control_parm'] = 'IO_THREAD';
- $slave_control_io_link = Url::getCommon($_url_params, '');
+ $slave_control_io_link = Url::getCommon($_url_params, '', false);
if ($server_slave_replication[0]['Slave_SQL_Running'] == 'No') {
$_url_params['sr_slave_action'] = 'start';
@@ -197,7 +197,7 @@ class ReplicationGui
}
$_url_params['sr_slave_control_parm'] = 'SQL_THREAD';
- $slave_control_sql_link = Url::getCommon($_url_params, '');
+ $slave_control_sql_link = Url::getCommon($_url_params, '', false);
if ($server_slave_replication[0]['Slave_IO_Running'] == 'No'
|| $server_slave_replication[0]['Slave_SQL_Running'] == 'No'
@@ -208,15 +208,15 @@ class ReplicationGui
}
$_url_params['sr_slave_control_parm'] = null;
- $slave_control_full_link = Url::getCommon($_url_params, '');
+ $slave_control_full_link = Url::getCommon($_url_params, '', false);
$_url_params['sr_slave_action'] = 'reset';
- $slave_control_reset_link = Url::getCommon($_url_params, '');
+ $slave_control_reset_link = Url::getCommon($_url_params, '', false);
$_url_params = $GLOBALS['url_params'];
$_url_params['sr_take_action'] = true;
$_url_params['sr_slave_skip_error'] = true;
- $slave_skip_error_link = Url::getCommon($_url_params, '');
+ $slave_skip_error_link = Url::getCommon($_url_params, '', false);
if ($server_slave_replication[0]['Slave_SQL_Running'] == 'No') {
$html .= Message::error(
@@ -233,7 +233,7 @@ class ReplicationGui
$_url_params['sl_configure'] = true;
$_url_params['repl_clear_scr'] = true;
- $reconfiguremaster_link = Url::getCommon($_url_params, '');
+ $reconfiguremaster_link = Url::getCommon($_url_params, '', false);
$html .= __(
'Server is configured as slave in a replication process. Would you ' .
@@ -293,7 +293,7 @@ class ReplicationGui
'This server is not configured as slave in a replication process. '
. 'Would you like to %sconfigure%s it?'
),
- '<a href="server_replication.php" data-post="' . Url::getCommon($_url_params, '') . '">',
+ '<a href="server_replication.php" data-post="' . Url::getCommon($_url_params, '', false) . '">',
'</a>'
);
}
@@ -355,7 +355,7 @@ class ReplicationGui
'This server is not configured as master in a replication process. '
. 'Would you like to %sconfigure%s it?'
),
- '<a href="server_replication.php" data-post="' . Url::getCommon($_url_params, '') . '">',
+ '<a href="server_replication.php" data-post="' . Url::getCommon($_url_params, '', false) . '">',
'</a>'
);
$html .= '</fieldset>';
diff --git a/libraries/classes/Rte/RteList.php b/libraries/classes/Rte/RteList.php
index fedf3278b6..677a5c7831 100644
--- a/libraries/classes/Rte/RteList.php
+++ b/libraries/classes/Rte/RteList.php
@@ -191,7 +191,7 @@ class RteList
*/
public static function getRoutineRow(array $routine, $rowclass = '')
{
- global $url_query, $db, $titles;
+ global $url_query, $url_params, $db, $titles;
$sql_drop = sprintf(
'DROP %s IF EXISTS %s',
@@ -316,7 +316,11 @@ class RteList
$retval .= " </td>\n";
$retval .= " <td>\n";
$retval .= Util::linkOrButton(
- 'sql.php' . $url_query . '&amp;sql_query=' . urlencode($sql_drop) . '&amp;goto=db_routines.php' . urlencode("?db={$db}"),
+ 'sql.php',
+ array_merge(
+ $url_params,
+ ['sql_query' => $sql_drop, 'goto' => 'db_routines.php' . Url::getCommon(['db' => $db])]
+ ),
$titles['Drop'],
['class' => 'ajax drop_anchor']
);
@@ -343,7 +347,7 @@ class RteList
*/
public static function getTriggerRow(array $trigger, $rowclass = '')
{
- global $url_query, $db, $table, $titles;
+ global $url_query, $url_params, $db, $table, $titles;
$retval = " <tr class='$rowclass'>\n";
$retval .= " <td>\n";
@@ -360,8 +364,8 @@ class RteList
$retval .= " </td>\n";
if (empty($table)) {
$retval .= " <td>\n";
- $retval .= "<a href='db_triggers.php{$url_query}"
- . "&amp;table=" . urlencode($trigger['table']) . "'>"
+ $retval .= "<a href='db_triggers.php"
+ . Url::getCommon(array_merge($url_params, ['table' => $trigger['table']])) . "'>"
. htmlspecialchars($trigger['table']) . "</a>";
$retval .= " </td>\n";
}
@@ -390,7 +394,11 @@ class RteList
$retval .= " <td>\n";
if (Util::currentUserHasPrivilege('TRIGGER', $db)) {
$retval .= Util::linkOrButton(
- 'sql.php' . $url_query . '&amp;sql_query=' . urlencode($trigger['drop']) . '&amp;goto=db_triggers.php' . urlencode("?db={$db}"),
+ 'sql.php',
+ array_merge(
+ $url_params,
+ ['sql_query' => $trigger['drop'], 'goto' => 'db_triggers.php' . Url::getCommon(['db' => $db])]
+ ),
$titles['Drop'],
['class' => 'ajax drop_anchor']
);
@@ -419,7 +427,7 @@ class RteList
*/
public static function getEventRow(array $event, $rowclass = '')
{
- global $url_query, $db, $titles;
+ global $url_query, $url_params, $db, $titles;
$sql_drop = sprintf(
'DROP EVENT IF EXISTS %s',
@@ -468,7 +476,11 @@ class RteList
$retval .= " <td>\n";
if (Util::currentUserHasPrivilege('EVENT', $db)) {
$retval .= Util::linkOrButton(
- 'sql.php' . $url_query . '&amp;sql_query=' . urlencode($sql_drop) . '&amp;goto=db_events.php' . urlencode("?db={$db}"),
+ 'sql.php',
+ array_merge(
+ $url_params,
+ ['sql_query' => $sql_drop, 'goto' => 'db_events.php' . Url::getCommon(['db' => $db])]
+ ),
$titles['Drop'],
['class' => 'ajax drop_anchor']
);
diff --git a/libraries/classes/Server/Privileges.php b/libraries/classes/Server/Privileges.php
index a62d111606..eb34b250b3 100644
--- a/libraries/classes/Server/Privileges.php
+++ b/libraries/classes/Server/Privileges.php
@@ -2844,7 +2844,7 @@ class Privileges
$html .= ' href="server_privileges.php';
if ($linktype == 'revoke') {
- $html .= '" data-post="' . Url::getCommon($params, '');
+ $html .= '" data-post="' . Url::getCommon($params, '', false);
} else {
$html .= Url::getCommon($params);
}
diff --git a/libraries/classes/Server/Status/Processes.php b/libraries/classes/Server/Status/Processes.php
index 336b28b6ee..df888b1973 100644
--- a/libraries/classes/Server/Status/Processes.php
+++ b/libraries/classes/Server/Status/Processes.php
@@ -141,7 +141,7 @@ class Processes
}
$retval .= '<th>';
- $columnUrl = Url::getCommon($column);
+ $columnUrl = Url::getCommon($column, '', false);
$retval .= '<a href="server_status_processes.php" data-post="' . $columnUrl . '" class="sortlink">';
$retval .= $column['column_name'];
@@ -179,7 +179,7 @@ class Processes
if (isset($_POST['sort_order'])) {
$url_params['sort_order'] = $_POST['sort_order'];
}
- $retval .= '<a href="server_status_processes.php" data-post="' . Url::getCommon($url_params, '') . '" >';
+ $retval .= '<a href="server_status_processes.php" data-post="' . Url::getCommon($url_params, '', false) . '" >';
if ($show_full_sql) {
$retval .= Util::getImage('s_partialtext',
__('Truncate Shown Queries'), ['class' => 'icon_fulltext']);
@@ -275,7 +275,7 @@ class Processes
$retval = '<tr>';
$retval .= '<td><a class="ajax kill_process" href="server_status_processes.php"'
- . ' data-post="' . Url::getCommon(['kill' => $process['Id']], '') . '">'
+ . ' data-post="' . Url::getCommon(['kill' => $process['Id']], '', false) . '">'
. __('Kill') . '</a></td>';
$retval .= '<td class="value">' . $process['Id'] . '</td>';
$retval .= '<td>' . htmlspecialchars($process['User']) . '</td>';
diff --git a/libraries/classes/Server/UserGroups.php b/libraries/classes/Server/UserGroups.php
index 337cd9a903..35ecac2443 100644
--- a/libraries/classes/Server/UserGroups.php
+++ b/libraries/classes/Server/UserGroups.php
@@ -115,7 +115,7 @@ class UserGroups
array(
'viewUsers' => 1, 'userGroup' => $groupName
),
- ''
+ '', false
)
. '">'
. Util::getIcon('b_usrlist', __('View users'))
@@ -126,7 +126,7 @@ class UserGroups
array(
'editUserGroup' => 1, 'userGroup' => $groupName
),
- ''
+ '', false
)
. '">'
. Util::getIcon('b_edit', __('Edit')) . '</a>';
@@ -137,7 +137,7 @@ class UserGroups
array(
'deleteUserGroup' => 1, 'userGroup' => $groupName
),
- ''
+ '', false
)
. '">'
. Util::getIcon('b_drop', __('Delete')) . '</a>';
diff --git a/libraries/classes/Sql.php b/libraries/classes/Sql.php
index f48c85f45b..e7e6619d85 100644
--- a/libraries/classes/Sql.php
+++ b/libraries/classes/Sql.php
@@ -227,7 +227,7 @@ class Sql
. htmlspecialchars($_POST['curr_value'])
. '</span>'
. '<a href="browse_foreigners.php" data-post="'
- . Url::getCommon($_url_params, '') . '"'
+ . Url::getCommon($_url_params, '', false) . '"'
. 'class="ajax browse_foreign" ' . '>'
. __('Browse foreign values')
. '</a>';
diff --git a/libraries/classes/Tracking.php b/libraries/classes/Tracking.php
index 82c8b25aac..87c8d04ec7 100644
--- a/libraries/classes/Tracking.php
+++ b/libraries/classes/Tracking.php
@@ -199,20 +199,20 @@ class Tracking
$html .= Url::getCommon($url_params + [
'version' => $version['version'],
'submit_delete_version' => true,
- ], '');
+ ], '', false);
$html .= '">' . $delete . '</a></td>';
$html .= '<td><a href="tbl_tracking.php" data-post="';
$html .= Url::getCommon($url_params + [
'report' => 'true',
'version' => $version['version'],
- ], '');
+ ], '', false);
$html .= '">' . $report . '</a>';
$html .= '&nbsp;&nbsp;';
$html .= '<a href="tbl_tracking.php" data-post="';
$html .= Url::getCommon($url_params + [
'snapshot' => 'true',
'version' => $version['version'],
- ], '');
+ ], '', false);
$html .= '">' . $structure . '</a>';
$html .= '</td>';
$html .= '</tr>';
diff --git a/libraries/classes/Url.php b/libraries/classes/Url.php
index f527819fbb..9ff516458f 100644
--- a/libraries/classes/Url.php
+++ b/libraries/classes/Url.php
@@ -7,6 +7,8 @@
*/
namespace PhpMyAdmin;
+use PhpMyAdmin\Crypto\Crypto;
+
/**
* Static methods for URL/hidden inputs generating
*
@@ -159,14 +161,15 @@ class Url
*
* @param mixed $params optional, Contains an associative array with url params
* @param string $divider optional character to use instead of '?'
+ * @param bool $encrypt whether to encrypt URL params
*
* @return string string with URL parameters
* @access public
*/
- public static function getCommon($params = array(), $divider = '?')
+ public static function getCommon($params = array(), $divider = '?', $encrypt = true)
{
return htmlspecialchars(
- Url::getCommonRaw($params, $divider)
+ Url::getCommonRaw($params, $divider, $encrypt)
);
}
@@ -195,15 +198,15 @@ class Url
*
* @param mixed $params optional, Contains an associative array with url params
* @param string $divider optional character to use instead of '?'
+ * @param bool $encrypt whether to encrypt URL params
*
* @return string string with URL parameters
* @access public
*/
- public static function getCommonRaw($params = array(), $divider = '?')
+ public static function getCommonRaw($params = array(), $divider = '?', $encrypt = true)
{
/** @var Config $PMA_Config */
global $PMA_Config;
- $separator = Url::getArgSeparator();
// avoid overwriting when creating navi panel links to servers
if (isset($GLOBALS['server'])
@@ -218,7 +221,7 @@ class Url
$params['lang'] = $GLOBALS['lang'];
}
- $query = http_build_query($params, null, $separator);
+ $query = self::buildHttpQuery($params, $encrypt);
if ($divider != '?' || strlen($query) > 0) {
return $divider . $query;
@@ -228,6 +231,81 @@ class Url
}
/**
+ * @param array<string, mixed> $params
+ * @param bool $encrypt whether to encrypt URL params
+ *
+ * @return string
+ */
+ public static function buildHttpQuery($params, $encrypt = true)
+ {
+ global $PMA_Config;
+
+ $separator = self::getArgSeparator();
+
+ if (! $encrypt || ! $PMA_Config->get('URLQueryEncryption')) {
+ return http_build_query($params, null, $separator);
+ }
+
+ $data = $params;
+ $keys = [
+ 'db',
+ 'table',
+ 'field',
+ 'sql_query',
+ 'sql_signature',
+ 'where_clause',
+ 'goto',
+ 'back',
+ 'message_to_show',
+ 'username',
+ 'hostname',
+ 'dbname',
+ 'tablename',
+ 'checkprivsdb',
+ 'checkprivstable',
+ ];
+ $paramsToEncrypt = [];
+ foreach ($params as $paramKey => $paramValue) {
+ if (! in_array($paramKey, $keys)) {
+ continue;
+ }
+
+ $paramsToEncrypt[$paramKey] = $paramValue;
+ unset($data[$paramKey]);
+ }
+
+ if ($paramsToEncrypt !== []) {
+ $data['eq'] = self::encryptQuery(json_encode($paramsToEncrypt));
+ }
+
+ return http_build_query($data, null, $separator);
+ }
+
+ /**
+ * @param string $query
+ *
+ * @return string
+ */
+ public static function encryptQuery($query)
+ {
+ $crypto = new Crypto();
+
+ return strtr(base64_encode($crypto->encrypt($query)), '+/', '-_');
+ }
+
+ /**
+ * @param string $query
+ *
+ * @return string|null
+ */
+ public static function decryptQuery($query)
+ {
+ $crypto = new Crypto();
+
+ return $crypto->decrypt(base64_decode(strtr($query, '-_', '+/')));
+ }
+
+ /**
* Returns url separator
*
* extracted from arg_separator.input as set in php.ini
diff --git a/libraries/classes/Util.php b/libraries/classes/Util.php
index 50945d6b5d..b624c6962c 100644
--- a/libraries/classes/Util.php
+++ b/libraries/classes/Util.php
@@ -1039,7 +1039,8 @@ class Util
$explain_params['sql_query'] = 'EXPLAIN ' . $sql_query;
$explain_link = ' [&nbsp;'
. self::linkOrButton(
- 'import.php' . Url::getCommon($explain_params),
+ 'import.php',
+ $explain_params,
__('Explain SQL')
) . '&nbsp;]';
} elseif (preg_match(
@@ -1050,7 +1051,8 @@ class Util
= mb_substr($sql_query, 8);
$explain_link = ' [&nbsp;'
. self::linkOrButton(
- 'import.php' . Url::getCommon($explain_params),
+ 'import.php',
+ $explain_params,
__('Skip Explain SQL')
) . ']';
$url = 'https://mariadb.org/explain_analyzer/analyze/'
@@ -1059,6 +1061,7 @@ class Util
$explain_link .= ' ['
. self::linkOrButton(
htmlspecialchars('url.php?url=' . urlencode($url)),
+ null,
sprintf(__('Analyze Explain at %s'), 'mariadb.org'),
array(),
'_blank'
@@ -1074,9 +1077,8 @@ class Util
if (! empty($cfg['SQLQuery']['Edit'])
&& empty($GLOBALS['show_as_php'])
) {
- $edit_link .= Url::getCommon($url_params);
$edit_link = ' [&nbsp;'
- . self::linkOrButton($edit_link, __('Edit'))
+ . self::linkOrButton($edit_link, $url_params, __('Edit'))
. '&nbsp;]';
} else {
$edit_link = '';
@@ -1089,14 +1091,16 @@ class Util
if (! empty($GLOBALS['show_as_php'])) {
$php_link = ' [&nbsp;'
. self::linkOrButton(
- 'import.php' . Url::getCommon($url_params),
+ 'import.php',
+ $url_params,
__('Without PHP code')
)
. '&nbsp;]';
$php_link .= ' [&nbsp;'
. self::linkOrButton(
- 'import.php' . Url::getCommon($url_params),
+ 'import.php',
+ $url_params,
__('Submit query')
)
. '&nbsp;]';
@@ -1105,7 +1109,8 @@ class Util
$php_params['show_as_php'] = 1;
$php_link = ' [&nbsp;'
. self::linkOrButton(
- 'import.php' . Url::getCommon($php_params),
+ 'import.php',
+ $php_params,
__('Create PHP code')
)
. '&nbsp;]';
@@ -1121,7 +1126,7 @@ class Util
) {
$refresh_link = 'import.php' . Url::getCommon($url_params);
$refresh_link = ' [&nbsp;'
- . self::linkOrButton($refresh_link, __('Refresh')) . ']';
+ . self::linkOrButton('import.php', $url_params, __('Refresh')) . ']';
} else {
$refresh_link = '';
} //refresh
@@ -1163,6 +1168,7 @@ class Util
$inline_edit_link = ' ['
. self::linkOrButton(
'#',
+ null,
_pgettext('Inline edit query', 'Edit inline'),
array('class' => 'inline_edit_sql')
)
@@ -1707,17 +1713,22 @@ class Util
* - URL components are over Suhosin limits
* - There is SQL query in the parameters
*
- * @param string $url the URL
- * @param string $message the link message
- * @param mixed $tag_params string: js confirmation; array: additional tag
- * params (f.e. style="")
- * @param string $target target
+ * @param string $urlPath the URL
+ * @param array|null $urlParams URL parameters
+ * @param string $message the link message
+ * @param mixed $tag_params string: js confirmation; array: additional tag params (f.e. style="")
+ * @param string $target target
*
* @return string the results to be echoed or saved in an array
*/
public static function linkOrButton(
- $url, $message, $tag_params = array(), $target = ''
+ $urlPath, $urlParams, $message, $tag_params = array(), $target = ''
) {
+ $url = $urlPath;
+ if (is_array($urlParams)) {
+ $url = $urlPath . Url::getCommon($urlParams, '?', false);
+ }
+
$url_length = strlen($url);
if (! is_array($tag_params)) {
@@ -1776,7 +1787,11 @@ class Util
) {
$url .= '?' . explode('&', $parts[1], 2)[0];
}
-
+ } else {
+ $url = $urlPath;
+ if (is_array($urlParams)) {
+ $url = $urlPath . Url::getCommon($urlParams);
+ }
}
foreach ($tag_params as $par_name => $par_value) {
@@ -4737,9 +4752,7 @@ class Util
$urlParams['tbl_group'] = $_REQUEST['tbl_group'];
}
- $url = 'db_structure.php' . Url::getCommon($urlParams);
-
- return self::linkOrButton($url, $title . $orderImg, $orderLinkParams);
+ return self::linkOrButton('db_structure.php', $urlParams, $title . $orderImg, $orderLinkParams);
}
/**
diff --git a/libraries/common.inc.php b/libraries/common.inc.php
index 8ec80a9638..6705fd08be 100644
--- a/libraries/common.inc.php
+++ b/libraries/common.inc.php
@@ -132,6 +132,8 @@ if (! defined('PMA_NO_SESSION')) {
Session::setUp($GLOBALS['PMA_Config'], $GLOBALS['error_handler']);
}
+Core::populateRequestWithEncryptedQueryParams();
+
/**
* init some variables LABEL_variables_init
*/
diff --git a/libraries/config.default.php b/libraries/config.default.php
index fcd54c9a18..8f4f296b70 100644
--- a/libraries/config.default.php
+++ b/libraries/config.default.php
@@ -825,6 +825,20 @@ $cfg['UseDbSearch'] = true;
$cfg['IgnoreMultiSubmitErrors'] = false;
/**
+ * Define whether phpMyAdmin will encrypt sensitive data from the URL query string.
+ *
+ * @global bool $cfg['URLQueryEncryption']
+ */
+$cfg['URLQueryEncryption'] = false;
+
+/**
+ * A secret key used to encrypt/decrypt the URL query string. Should be 32 bytes long.
+ *
+ * @global string $cfg['URLQueryEncryptionSecretKey']
+ */
+$cfg['URLQueryEncryptionSecretKey'] = '';
+
+/**
* allow login to any user entered server in cookie based authentication
*
* @global boolean $cfg['AllowArbitraryServer']