diff --git a/composer.json b/composer.json index 2423a2565a..c9fcfd9453 100644 --- a/composer.json +++ b/composer.json @@ -65,7 +65,7 @@ "samyoul/u2f-php-server": "<1.1" }, "suggest": { - "ext-openssl": "Cookie encryption", + "ext-openssl": "For encryption performance", "ext-curl": "Updates checking", "ext-opcache": "Better performance", "ext-zlib": "For gz import and export", diff --git a/doc/config.rst b/doc/config.rst index 183b9f5ce9..f0b9ae2218 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -1736,6 +1736,17 @@ Generic settings Define whether phpMyAdmin will continue executing a multi-query statement if one of the queries fails. Default is to abort execution. +.. config:option:: $cfg['URLQueryEncryption'] + + :type: boolean + :default: true + + .. versionadded:: 4.9.8 + + Define whether phpMyAdmin will encrypt sensitive data (like database name + and table name) from the URL query string. Default is to encrypt the URL + query string. + Cookie authentication options ----------------------------- diff --git a/libraries/classes/Crypto/Crypto.php b/libraries/classes/Crypto/Crypto.php new file mode 100644 index 0000000000..128598639d --- /dev/null +++ b/libraries/classes/Crypto/Crypto.php @@ -0,0 +1,80 @@ +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 static function decryptWithPhpseclib($encrypted) + { + $key = self::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); + } + + /** + * @return string + */ + private static function getEncryptionKey() + { + global $PMA_Config; + + return $_SESSION[' HMAC_secret '] . $PMA_Config->get('blowfish_secret'); + } +} diff --git a/libraries/classes/Url.php b/libraries/classes/Url.php index d63d7b6989..c5c411df0b 100644 --- a/libraries/classes/Url.php +++ b/libraries/classes/Url.php @@ -7,8 +7,7 @@ */ namespace PhpMyAdmin; -use phpseclib\Crypt\AES; -use phpseclib\Crypt\Random; +use PhpMyAdmin\Crypto\Crypto; /** * Static methods for URL/hidden inputs generating @@ -223,7 +222,7 @@ class Url $query = http_build_query($params, null, $separator); - if (isset($params['db'])) { + if ($PMA_Config->get('URLQueryEncryption') && isset($params['db'])) { $encryptedQuery = self::encryptQuery($query); $query = http_build_query(['eq' => $encryptedQuery], null, $separator); } @@ -241,17 +240,7 @@ class Url */ public static function encryptQuery($query) { - global $PMA_Config; - - $key = $_SESSION[' HMAC_secret '] . $PMA_Config->get('blowfish_secret'); - $cipher = new AES(AES::MODE_CBC); - $iv = Random::string(16); - $cipher->setIV($iv); - $cipher->setKey($key); - $ciphertext = $cipher->encrypt($query); - $hmac = hash_hmac('sha256', $iv . $ciphertext, $key, true); - - return strtr(base64_encode($hmac . $iv . $ciphertext), '+/', '-_'); + return strtr(base64_encode(Crypto::encrypt($query)), '+/', '-_'); } /** @@ -260,24 +249,7 @@ class Url */ public static function decryptQuery($query) { - global $PMA_Config; - - $encryptedQuery = base64_decode(strtr($query, '-_', '+/')); - $hmac = mb_substr($encryptedQuery, 0, 32, '8bit'); - $iv = mb_substr($encryptedQuery, 32, 16, '8bit'); - $ciphertext = mb_substr($encryptedQuery, 48, null, '8bit'); - $key = $_SESSION[' HMAC_secret '] . $PMA_Config->get('blowfish_secret'); - $calculated = hash_hmac('sha256', $iv . $ciphertext, $key, true); - - if (! hash_equals($hmac, $calculated)) { - return null; - } - - $cipher = new AES(AES::MODE_CBC); - $cipher->setIV($iv); - $cipher->setKey($key); - - return $cipher->decrypt($ciphertext); + return Crypto::decrypt(base64_decode(strtr($query, '-_', '+/'))); } /** diff --git a/libraries/config.default.php b/libraries/config.default.php index e7cf828bff..fdd7c13639 100644 --- a/libraries/config.default.php +++ b/libraries/config.default.php @@ -817,6 +817,13 @@ $cfg['UseDbSearch'] = true; */ $cfg['IgnoreMultiSubmitErrors'] = false; +/** + * Define whether phpMyAdmin will encrypt sensitive data from the URL query string. + * + * @global bool $cfg['URLQueryEncryption'] + */ +$cfg['URLQueryEncryption'] = true; + /** * allow login to any user entered server in cookie based authentication * diff --git a/test/classes/Config/PageSettingsTest.php b/test/classes/Config/PageSettingsTest.php index 677336d323..98a84cba8d 100644 --- a/test/classes/Config/PageSettingsTest.php +++ b/test/classes/Config/PageSettingsTest.php @@ -26,6 +26,7 @@ class PageSettingsTest extends PmaTestCase public function setUp() { $GLOBALS['PMA_Config'] = new Config(); + $GLOBALS['PMA_Config']->set('URLQueryEncryption', false); $GLOBALS['server'] = 1; $GLOBALS['db'] = 'db'; $GLOBALS['table'] = ''; diff --git a/test/classes/Controllers/Server/ServerDatabasesControllerTest.php b/test/classes/Controllers/Server/ServerDatabasesControllerTest.php index 8ff219ba60..2cfda9f14a 100644 --- a/test/classes/Controllers/Server/ServerDatabasesControllerTest.php +++ b/test/classes/Controllers/Server/ServerDatabasesControllerTest.php @@ -34,6 +34,7 @@ class ServerDatabasesControllerTest extends PmaTestCase //$GLOBALS $GLOBALS['PMA_Config'] = new Config(); + $GLOBALS['PMA_Config']->set('URLQueryEncryption', false); $GLOBALS['PMA_Config']->enableBc(); $GLOBALS['db'] = 'db'; diff --git a/test/classes/Display/ResultsTest.php b/test/classes/Display/ResultsTest.php index f986883aac..fdeed4c78a 100644 --- a/test/classes/Display/ResultsTest.php +++ b/test/classes/Display/ResultsTest.php @@ -44,6 +44,7 @@ class ResultsTest extends PmaTestCase $GLOBALS['PMA_PHP_SELF'] = 'index.php'; $this->object = new DisplayResults('as', '', '', ''); $GLOBALS['PMA_Config'] = new Config(); + $GLOBALS['PMA_Config']->set('URLQueryEncryption', false); $GLOBALS['PMA_Config']->enableBc(); $GLOBALS['text_dir'] = 'ltr'; $_SESSION[' HMAC_secret '] = 'test'; diff --git a/test/classes/FooterTest.php b/test/classes/FooterTest.php index 76704d9e36..cd6dc7f13b 100644 --- a/test/classes/FooterTest.php +++ b/test/classes/FooterTest.php @@ -46,6 +46,7 @@ class FooterTest extends PmaTestCase $GLOBALS['table'] = ''; $GLOBALS['text_dir'] = 'ltr'; $GLOBALS['PMA_Config'] = new Config(); + $GLOBALS['PMA_Config']->set('URLQueryEncryption', false); $GLOBALS['PMA_Config']->enableBc(); $GLOBALS['cfg']['Server']['DisableIS'] = false; $GLOBALS['cfg']['Server']['verbose'] = 'verbose host'; diff --git a/test/classes/InsertEditTest.php b/test/classes/InsertEditTest.php index d274ca59b5..8ce35542da 100644 --- a/test/classes/InsertEditTest.php +++ b/test/classes/InsertEditTest.php @@ -62,6 +62,7 @@ class InsertEditTest extends TestCase $GLOBALS['cfg']['LoginCookieValidity'] = 1440; $GLOBALS['cfg']['enable_drag_drop_import'] = true; $GLOBALS['PMA_Config'] = new Config(); + $GLOBALS['PMA_Config']->set('URLQueryEncryption', false); $this->insertEdit = new InsertEdit($GLOBALS['dbi']); } diff --git a/test/classes/Navigation/NavigationTreeTest.php b/test/classes/Navigation/NavigationTreeTest.php index 0149332035..f391db0459 100644 --- a/test/classes/Navigation/NavigationTreeTest.php +++ b/test/classes/Navigation/NavigationTreeTest.php @@ -43,6 +43,7 @@ class NavigationTreeTest extends PmaTestCase { $GLOBALS['server'] = 1; $GLOBALS['PMA_Config'] = new Config(); + $GLOBALS['PMA_Config']->set('URLQueryEncryption', false); $GLOBALS['PMA_Config']->enableBc(); $GLOBALS['cfg']['Server']['host'] = 'localhost'; $GLOBALS['cfg']['Server']['user'] = 'root'; diff --git a/test/classes/Plugins/Auth/AuthenticationCookieTest.php b/test/classes/Plugins/Auth/AuthenticationCookieTest.php index fc5e034c20..060d0a0945 100644 --- a/test/classes/Plugins/Auth/AuthenticationCookieTest.php +++ b/test/classes/Plugins/Auth/AuthenticationCookieTest.php @@ -37,6 +37,7 @@ class AuthenticationCookieTest extends PmaTestCase function setUp() { $GLOBALS['PMA_Config'] = new Config(); + $GLOBALS['PMA_Config']->set('URLQueryEncryption', false); $GLOBALS['PMA_Config']->enableBc(); $GLOBALS['server'] = 0; $GLOBALS['text_dir'] = 'ltr'; diff --git a/test/classes/PmaTestCase.php b/test/classes/PmaTestCase.php index b2e72b7a51..889958347d 100644 --- a/test/classes/PmaTestCase.php +++ b/test/classes/PmaTestCase.php @@ -28,6 +28,7 @@ class PmaTestCase extends TestCase { require 'libraries/config.default.php'; $GLOBALS['cfg'] = $cfg; + $GLOBALS['PMA_Config']->set('URLQueryEncryption', false); } /**