Create PhpMyAdmin\Crypto\Crypto class to handle encryptions

Signed-off-by: Maurício Meneghini Fauth <mauricio@fauth.dev>
This commit is contained in:
Maurício Meneghini Fauth 2021-10-14 12:01:12 -03:00
parent eb9bcbc040
commit 28ad63c969
No known key found for this signature in database
GPG Key ID: 6A16FD38AFC89CC8
13 changed files with 111 additions and 33 deletions

View File

@ -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",

View File

@ -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
-----------------------------

View File

@ -0,0 +1,80 @@
<?php
namespace PhpMyAdmin\Crypto;
use phpseclib\Crypt\AES;
use phpseclib\Crypt\Random;
final class Crypto
{
/**
* @param string $plaintext
*
* @return string
*/
public static function encrypt($plaintext)
{
return self::encryptWithPhpseclib($plaintext);
}
/**
* @param string $ciphertext
*
* @return string
*/
public static function decrypt($ciphertext)
{
return self::decryptWithPhpseclib($ciphertext);
}
/**
* @param string $plaintext
*
* @return string
*/
private static function encryptWithPhpseclib($plaintext)
{
$key = self::getEncryptionKey();
$cipher = new AES(AES::MODE_CBC);
$iv = 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 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');
}
}

View File

@ -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, '-_', '+/')));
}
/**

View File

@ -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
*

View File

@ -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'] = '';

View File

@ -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';

View File

@ -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';

View File

@ -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';

View File

@ -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']);
}

View File

@ -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';

View File

@ -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';

View File

@ -28,6 +28,7 @@ class PmaTestCase extends TestCase
{
require 'libraries/config.default.php';
$GLOBALS['cfg'] = $cfg;
$GLOBALS['PMA_Config']->set('URLQueryEncryption', false);
}
/**