Add unit tests
Signed-off-by: Maurício Meneghini Fauth <mauricio@fauth.dev>
This commit is contained in:
parent
3095181bb3
commit
d057b68aa1
@ -1317,4 +1317,27 @@ 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'])) {
|
||||
unset($_GET['eq'], $_REQUEST['eq']);
|
||||
return;
|
||||
}
|
||||
|
||||
$decryptedQuery = Url::decryptQuery($_GET['eq']);
|
||||
unset($_GET['eq'], $_REQUEST['eq']);
|
||||
if ($decryptedQuery === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$urlQueryParams = (array) json_decode($decryptedQuery);
|
||||
foreach ($urlQueryParams as $urlQueryParamKey => $urlQueryParamValue) {
|
||||
$_GET[$urlQueryParamKey] = $urlQueryParamValue;
|
||||
$_REQUEST[$urlQueryParamKey] = $urlQueryParamValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,10 +13,14 @@ final class Crypto
|
||||
/** @var bool */
|
||||
private $hasSodiumSupport;
|
||||
|
||||
public function __construct()
|
||||
/**
|
||||
* @param bool $forceFallback Force the usage of the fallback functions.
|
||||
*/
|
||||
public function __construct($forceFallback = false)
|
||||
{
|
||||
$this->hasRandomBytesSupport = is_callable('random_bytes');
|
||||
$this->hasSodiumSupport = $this->hasRandomBytesSupport
|
||||
$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')
|
||||
|
||||
@ -1574,6 +1574,6 @@ class NavigationTree
|
||||
$url = parse_url($link);
|
||||
parse_str(htmlspecialchars_decode($url['query']), $query);
|
||||
|
||||
return $url['path'] . '?' . Url::buildHttpQuery($query);
|
||||
return $url['path'] . '?' . htmlspecialchars(Url::buildHttpQuery($query));
|
||||
}
|
||||
}
|
||||
|
||||
@ -270,7 +270,9 @@ class Url
|
||||
unset($data[$paramKey]);
|
||||
}
|
||||
|
||||
$data['eq'] = self::encryptQuery(json_encode($paramsToEncrypt));
|
||||
if ($paramsToEncrypt !== []) {
|
||||
$data['eq'] = self::encryptQuery(json_encode($paramsToEncrypt));
|
||||
}
|
||||
|
||||
return http_build_query($data, null, $separator);
|
||||
}
|
||||
|
||||
@ -43,7 +43,6 @@ use PhpMyAdmin\Response;
|
||||
use PhpMyAdmin\Session;
|
||||
use PhpMyAdmin\ThemeManager;
|
||||
use PhpMyAdmin\Tracker;
|
||||
use PhpMyAdmin\Url;
|
||||
use PhpMyAdmin\Util;
|
||||
|
||||
/**
|
||||
@ -133,16 +132,7 @@ if (! defined('PMA_NO_SESSION')) {
|
||||
Session::setUp($GLOBALS['PMA_Config'], $GLOBALS['error_handler']);
|
||||
}
|
||||
|
||||
if (isset($_GET['eq']) && is_string($_GET['eq'])) {
|
||||
$decryptedQuery = Url::decryptQuery($_GET['eq']);
|
||||
if ($decryptedQuery !== null) {
|
||||
$urlQueryParams = json_decode($decryptedQuery);
|
||||
foreach ($urlQueryParams as $urlQueryParamKey => $urlQueryParamValue) {
|
||||
$_GET[$urlQueryParamKey] = $urlQueryParamValue;
|
||||
$_REQUEST[$urlQueryParamKey] = $urlQueryParamValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
Core::populateRequestWithEncryptedQueryParams();
|
||||
|
||||
/**
|
||||
* init some variables LABEL_variables_init
|
||||
|
||||
@ -11,6 +11,7 @@ use PhpMyAdmin\Config;
|
||||
use PhpMyAdmin\Core;
|
||||
use PhpMyAdmin\Sanitize;
|
||||
use PhpMyAdmin\Tests\PmaTestCase;
|
||||
use PhpMyAdmin\Url;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
@ -50,6 +51,7 @@ class CoreTest extends PmaTestCase
|
||||
$GLOBALS['db'] = '';
|
||||
$GLOBALS['table'] = '';
|
||||
$GLOBALS['PMA_PHP_SELF'] = 'http://example.net/';
|
||||
$GLOBALS['PMA_Config']->set('URLQueryEncryption', false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1226,4 +1228,61 @@ class CoreTest extends PmaTestCase
|
||||
// Must work now, (good secret and blowfish_secret)
|
||||
$this->assertTrue(Core::checkSqlQuerySignature($sqlQuery, $hmac));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testPopulateRequestWithEncryptedQueryParams()
|
||||
{
|
||||
global $PMA_Config;
|
||||
|
||||
$_SESSION = [];
|
||||
$PMA_Config->set('URLQueryEncryption', true);
|
||||
$PMA_Config->set('URLQueryEncryptionSecretKey', str_repeat('a', 32));
|
||||
|
||||
$_GET = ['pos' => '0', 'eq' => Url::encryptQuery('{"db":"test_db","table":"test_table"}')];
|
||||
$_REQUEST = $_GET;
|
||||
|
||||
Core::populateRequestWithEncryptedQueryParams();
|
||||
|
||||
$expected = ['pos' => '0', 'db' => 'test_db', 'table' => 'test_table'];
|
||||
|
||||
$this->assertEquals($expected, $_GET);
|
||||
$this->assertEquals($expected, $_REQUEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*
|
||||
* @dataProvider providerForTestPopulateRequestWithEncryptedQueryParamsWithInvalidParam
|
||||
*/
|
||||
public function testPopulateRequestWithEncryptedQueryParamsWithInvalidParam($encrypted, $decrypted)
|
||||
{
|
||||
global $PMA_Config;
|
||||
|
||||
$_SESSION = [];
|
||||
$PMA_Config->set('URLQueryEncryption', true);
|
||||
$PMA_Config->set('URLQueryEncryptionSecretKey', str_repeat('a', 32));
|
||||
|
||||
$_GET = $encrypted;
|
||||
$_REQUEST = $encrypted;
|
||||
|
||||
Core::populateRequestWithEncryptedQueryParams();
|
||||
|
||||
$this->assertEquals($decrypted, $_GET);
|
||||
$this->assertEquals($decrypted, $_REQUEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[][][]
|
||||
*/
|
||||
public function providerForTestPopulateRequestWithEncryptedQueryParamsWithInvalidParam()
|
||||
{
|
||||
return [
|
||||
[[], []],
|
||||
[['eq' => []], []],
|
||||
[['eq' => ''], []],
|
||||
[['eq' => 'invalid'], []],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
114
test/classes/Crypto/CryptoTest.php
Normal file
114
test/classes/Crypto/CryptoTest.php
Normal file
@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
namespace PhpMyAdmin\Tests\Crypto;
|
||||
|
||||
use PhpMyAdmin\Crypto\Crypto;
|
||||
use PhpMyAdmin\Tests\PmaTestCase;
|
||||
|
||||
/**
|
||||
* @covers \PhpMyAdmin\Crypto\Crypto
|
||||
*/
|
||||
class CryptoTest extends PmaTestCase
|
||||
{
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testWithValidKeyFromConfig()
|
||||
{
|
||||
global $PMA_Config;
|
||||
|
||||
$_SESSION = [];
|
||||
$PMA_Config->set('URLQueryEncryptionSecretKey', str_repeat('a', 32));
|
||||
|
||||
$cryptoWithSodium = new Crypto();
|
||||
$encrypted = $cryptoWithSodium->encrypt('test');
|
||||
$this->assertNotSame('test', $encrypted);
|
||||
$this->assertSame('test', $cryptoWithSodium->decrypt($encrypted));
|
||||
$this->assertArrayNotHasKey('URLQueryEncryptionSecretKey', $_SESSION);
|
||||
|
||||
$cryptoWithPhpseclib = new Crypto(true);
|
||||
$encrypted = $cryptoWithPhpseclib->encrypt('test');
|
||||
$this->assertNotSame('test', $encrypted);
|
||||
$this->assertSame('test', $cryptoWithPhpseclib->decrypt($encrypted));
|
||||
$this->assertArrayNotHasKey('URLQueryEncryptionSecretKey', $_SESSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testWithValidKeyFromSession()
|
||||
{
|
||||
global $PMA_Config;
|
||||
|
||||
$_SESSION = ['URLQueryEncryptionSecretKey' => str_repeat('a', 32)];
|
||||
$PMA_Config->set('URLQueryEncryptionSecretKey', '');
|
||||
|
||||
$cryptoWithSodium = new Crypto();
|
||||
$encrypted = $cryptoWithSodium->encrypt('test');
|
||||
$this->assertNotSame('test', $encrypted);
|
||||
$this->assertSame('test', $cryptoWithSodium->decrypt($encrypted));
|
||||
$this->assertArrayHasKey('URLQueryEncryptionSecretKey', $_SESSION);
|
||||
|
||||
$cryptoWithPhpseclib = new Crypto(true);
|
||||
$encrypted = $cryptoWithPhpseclib->encrypt('test');
|
||||
$this->assertNotSame('test', $encrypted);
|
||||
$this->assertSame('test', $cryptoWithPhpseclib->decrypt($encrypted));
|
||||
$this->assertArrayHasKey('URLQueryEncryptionSecretKey', $_SESSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testWithNewSessionKey()
|
||||
{
|
||||
global $PMA_Config;
|
||||
|
||||
$_SESSION = [];
|
||||
$PMA_Config->set('URLQueryEncryptionSecretKey', '');
|
||||
|
||||
$cryptoWithSodium = new Crypto();
|
||||
$encrypted = $cryptoWithSodium->encrypt('test');
|
||||
$this->assertNotSame('test', $encrypted);
|
||||
$this->assertSame('test', $cryptoWithSodium->decrypt($encrypted));
|
||||
$this->assertArrayHasKey('URLQueryEncryptionSecretKey', $_SESSION);
|
||||
$this->assertEquals(32, mb_strlen($_SESSION['URLQueryEncryptionSecretKey'], '8bit'));
|
||||
|
||||
$cryptoWithPhpseclib = new Crypto(true);
|
||||
$encrypted = $cryptoWithPhpseclib->encrypt('test');
|
||||
$this->assertNotSame('test', $encrypted);
|
||||
$this->assertSame('test', $cryptoWithPhpseclib->decrypt($encrypted));
|
||||
$this->assertArrayHasKey('URLQueryEncryptionSecretKey', $_SESSION);
|
||||
$this->assertEquals(32, mb_strlen($_SESSION['URLQueryEncryptionSecretKey'], '8bit'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testDecryptWithInvalidKey()
|
||||
{
|
||||
global $PMA_Config;
|
||||
|
||||
$_SESSION = [];
|
||||
$PMA_Config->set('URLQueryEncryptionSecretKey', str_repeat('a', 32));
|
||||
|
||||
$cryptoWithSodium = new Crypto();
|
||||
$encrypted = $cryptoWithSodium->encrypt('test');
|
||||
$this->assertNotSame('test', $encrypted);
|
||||
$this->assertSame('test', $cryptoWithSodium->decrypt($encrypted));
|
||||
|
||||
$PMA_Config->set('URLQueryEncryptionSecretKey', str_repeat('b', 32));
|
||||
|
||||
$cryptoWithSodium = new Crypto();
|
||||
$this->assertNull($cryptoWithSodium->decrypt($encrypted));
|
||||
|
||||
$cryptoWithPhpseclib = new Crypto(true);
|
||||
$encrypted = $cryptoWithPhpseclib->encrypt('test');
|
||||
$this->assertNotSame('test', $encrypted);
|
||||
$this->assertSame('test', $cryptoWithPhpseclib->decrypt($encrypted));
|
||||
|
||||
$PMA_Config->set('URLQueryEncryptionSecretKey', str_repeat('a', 32));
|
||||
|
||||
$cryptoWithPhpseclib = new Crypto(true);
|
||||
$this->assertNull($cryptoWithPhpseclib->decrypt($encrypted));
|
||||
}
|
||||
}
|
||||
@ -11,6 +11,8 @@ use PhpMyAdmin\Config;
|
||||
use PhpMyAdmin\Navigation\NavigationTree;
|
||||
use PhpMyAdmin\Tests\PmaTestCase;
|
||||
use PhpMyAdmin\Theme;
|
||||
use PhpMyAdmin\Url;
|
||||
use ReflectionMethod;
|
||||
|
||||
/*
|
||||
* we must set $GLOBALS['server'] here
|
||||
@ -101,4 +103,37 @@ class NavigationTreeTest extends PmaTestCase
|
||||
$result = $this->object->renderDbSelect();
|
||||
$this->assertContains('pma_navigation_select_database', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testEncryptQueryParams()
|
||||
{
|
||||
global $PMA_Config;
|
||||
|
||||
$_SESSION = [];
|
||||
$PMA_Config->set('URLQueryEncryption', false);
|
||||
$PMA_Config->set('URLQueryEncryptionSecretKey', str_repeat('a', 32));
|
||||
|
||||
$method = new ReflectionMethod($this->object, 'encryptQueryParams');
|
||||
$method->setAccessible(true);
|
||||
|
||||
$link = 'tbl_structure.php?server=1&db=test_db&table=test_table&pos=0';
|
||||
|
||||
$actual = $method->invoke($this->object, $link);
|
||||
$this->assertEquals($link, $actual);
|
||||
|
||||
$PMA_Config->set('URLQueryEncryption', true);
|
||||
|
||||
$actual = $method->invoke($this->object, $link);
|
||||
$this->assertStringStartsWith('tbl_structure.php?server=1&pos=0&eq=', $actual);
|
||||
|
||||
$url = parse_url($actual);
|
||||
parse_str(htmlspecialchars_decode($url['query']), $query);
|
||||
|
||||
$this->assertRegExp('/^[a-zA-Z0-9-_=]+$/', $query['eq']);
|
||||
$decrypted = Url::decryptQuery($query['eq']);
|
||||
$this->assertJson($decrypted);
|
||||
$this->assertSame('{"db":"test_db","table":"test_table"}', $decrypted);
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,6 +27,7 @@ class UrlTest extends TestCase
|
||||
public function setUp()
|
||||
{
|
||||
unset($_COOKIE['pma_lang']);
|
||||
$GLOBALS['PMA_Config']->set('URLQueryEncryption', false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -105,4 +106,61 @@ class UrlTest extends TestCase
|
||||
$expected = '?server=x' . htmlentities($separator) . 'lang=en' ;
|
||||
$this->assertEquals($expected, Url::getCommon());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testBuildHttpQueryWithUrlQueryEncryptionDisabled()
|
||||
{
|
||||
global $PMA_Config;
|
||||
|
||||
$PMA_Config->set('URLQueryEncryption', false);
|
||||
$params = ['db' => 'test_db', 'table' => 'test_table', 'pos' => 0];
|
||||
$this->assertEquals('db=test_db&table=test_table&pos=0', Url::buildHttpQuery($params));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testBuildHttpQueryWithUrlQueryEncryptionEnabled()
|
||||
{
|
||||
global $PMA_Config;
|
||||
|
||||
$_SESSION = [];
|
||||
$PMA_Config->set('URLQueryEncryption', true);
|
||||
$PMA_Config->set('URLQueryEncryptionSecretKey', str_repeat('a', 32));
|
||||
|
||||
$params = ['db' => 'test_db', 'table' => 'test_table', 'pos' => 0];
|
||||
$query = Url::buildHttpQuery($params);
|
||||
$this->assertStringStartsWith('pos=0&eq=', $query);
|
||||
parse_str($query, $queryParams);
|
||||
$this->assertCount(2, $queryParams);
|
||||
$this->assertSame('0', $queryParams['pos']);
|
||||
$this->assertTrue(is_string($queryParams['eq']));
|
||||
$this->assertNotSame('', $queryParams['eq']);
|
||||
$this->assertRegExp('/^[a-zA-Z0-9-_=]+$/', $queryParams['eq']);
|
||||
$decrypted = Url::decryptQuery($queryParams['eq']);
|
||||
$this->assertJson($decrypted);
|
||||
$this->assertSame('{"db":"test_db","table":"test_table"}', $decrypted);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testQueryEncryption()
|
||||
{
|
||||
global $PMA_Config;
|
||||
|
||||
$_SESSION = [];
|
||||
$PMA_Config->set('URLQueryEncryption', true);
|
||||
$PMA_Config->set('URLQueryEncryptionSecretKey', str_repeat('a', 32));
|
||||
|
||||
$query = '{"db":"test_db","table":"test_table"}';
|
||||
$encrypted = Url::encryptQuery($query);
|
||||
$this->assertNotSame($query, $encrypted);
|
||||
$this->assertNotSame('', $encrypted);
|
||||
$this->assertRegExp('/^[a-zA-Z0-9-_=]+$/', $encrypted);
|
||||
$decrypted = Url::decryptQuery($encrypted);
|
||||
$this->assertSame($query, $decrypted);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user