Fix broken foreign key links
Fixes: #14270 - Middle-click on foreign key link broken Fixes: #14363 - Broken relational links in tables Pull-request: #15325 Signed-off-by: William Desportes <williamdes@wdes.fr>
This commit is contained in:
commit
d2caddf5e9
@ -1289,4 +1289,32 @@ class Core
|
||||
self::fatalError(__('possible exploit'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign the sql query using hmac using the session token
|
||||
*
|
||||
* @param string $sqlQuery The sql query
|
||||
* @return void
|
||||
*/
|
||||
public static function signSqlQuery($sqlQuery)
|
||||
{
|
||||
/** @var array $cfg */
|
||||
global $cfg;
|
||||
return hash_hmac('sha256', $sqlQuery, $_SESSION[' HMAC_secret '] . $cfg['blowfish_secret']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the sql query has a valid hmac signature
|
||||
*
|
||||
* @param string $sqlQuery The sql query
|
||||
* @return void
|
||||
*/
|
||||
public static function checkSqlQuerySignature($sqlQuery, $signature)
|
||||
{
|
||||
/** @var array $cfg */
|
||||
global $cfg;
|
||||
$hmac = hash_hmac('sha256', $sqlQuery, $_SESSION[' HMAC_secret '] . $cfg['blowfish_secret']);
|
||||
return hash_equals($hmac, $signature);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -5313,16 +5313,19 @@ class Results
|
||||
$title = htmlspecialchars($data);
|
||||
}
|
||||
|
||||
$sqlQuery = 'SELECT * FROM '
|
||||
. Util::backquote($map[$meta->name][3]) . '.'
|
||||
. Util::backquote($map[$meta->name][0])
|
||||
. ' WHERE '
|
||||
. Util::backquote($map[$meta->name][1])
|
||||
. $where_comparison;
|
||||
|
||||
$_url_params = array(
|
||||
'db' => $map[$meta->name][3],
|
||||
'table' => $map[$meta->name][0],
|
||||
'pos' => '0',
|
||||
'sql_query' => 'SELECT * FROM '
|
||||
. Util::backquote($map[$meta->name][3]) . '.'
|
||||
. Util::backquote($map[$meta->name][0])
|
||||
. ' WHERE '
|
||||
. Util::backquote($map[$meta->name][1])
|
||||
. $where_comparison,
|
||||
'sql_signature' => Core::signSqlQuery($sqlQuery),
|
||||
'sql_query' => $sqlQuery,
|
||||
);
|
||||
|
||||
if ($transformation_plugin != $default_function) {
|
||||
|
||||
@ -214,6 +214,7 @@ class AuthenticationSignon extends AuthenticationPlugin
|
||||
/* Restore our token */
|
||||
if (!empty($pma_token)) {
|
||||
$_SESSION[' PMA_token '] = $pma_token;
|
||||
$_SESSION[' HMAC_secret '] = Util::generateRandom(16);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -29,6 +29,7 @@ class Session
|
||||
private static function generateToken()
|
||||
{
|
||||
$_SESSION[' PMA_token '] = Util::generateRandom(16);
|
||||
$_SESSION[' HMAC_secret '] = Util::generateRandom(16);
|
||||
|
||||
/**
|
||||
* Check if token is properly generated (the generation can fail, for example
|
||||
|
||||
@ -1760,7 +1760,8 @@ class Util
|
||||
$tag_params_strings = array();
|
||||
if (($url_length > $GLOBALS['cfg']['LinkLengthLimit'])
|
||||
|| ! $in_suhosin_limits
|
||||
|| strpos($url, 'sql_query=') !== false
|
||||
// Has as sql_query without a signature
|
||||
|| ( strpos($url, 'sql_query=') !== false && strpos($url, 'sql_signature=') === false)
|
||||
|| strpos($url, 'view[as]=') !== false
|
||||
) {
|
||||
$parts = explode('?', $url, 2);
|
||||
|
||||
5
sql.php
5
sql.php
@ -13,6 +13,7 @@ use PhpMyAdmin\Response;
|
||||
use PhpMyAdmin\Sql;
|
||||
use PhpMyAdmin\Url;
|
||||
use PhpMyAdmin\Util;
|
||||
use PhpMyAdmin\Core;
|
||||
|
||||
/**
|
||||
* Gets some core libraries
|
||||
@ -71,6 +72,10 @@ if (isset($_POST['bkm_fields']['bkm_sql_query'])) {
|
||||
$sql_query = $_POST['bkm_fields']['bkm_sql_query'];
|
||||
} elseif (isset($_POST['sql_query'])) {
|
||||
$sql_query = $_POST['sql_query'];
|
||||
} elseif (isset($_GET['sql_query']) && isset($_GET['sql_signature'])) {
|
||||
if (Core::checkSqlQuerySignature($_GET['sql_query'], $_GET['sql_signature'])) {
|
||||
$sql_query = $_GET['sql_query'];
|
||||
}
|
||||
}
|
||||
|
||||
// This one is just to fill $db
|
||||
|
||||
@ -1121,4 +1121,110 @@ class CoreTest extends PmaTestCase
|
||||
|
||||
$this->assertGreaterThan(0, mb_strpos($printed, $warn));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for Core::signSqlQuery
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function testSignSqlQuery()
|
||||
{
|
||||
$_SESSION[' HMAC_secret '] = hash('sha1', 'test');
|
||||
$sqlQuery = 'SELECT * FROM `test`.`db` WHERE 1;';
|
||||
$signature = Core::signSqlQuery($sqlQuery);
|
||||
$hmac = '33371e8680a640dc05944a2a24e6e630d3e9e3dba24464135f2fb954c3a4ffe2';
|
||||
$this->assertSame($hmac, $signature, 'The signature must match the computed one');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for Core::checkSqlQuerySignature
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function testCheckSqlQuerySignature()
|
||||
{
|
||||
$_SESSION[' HMAC_secret '] = hash('sha1', 'test');
|
||||
$sqlQuery = 'SELECT * FROM `test`.`db` WHERE 1;';
|
||||
$hmac = '33371e8680a640dc05944a2a24e6e630d3e9e3dba24464135f2fb954c3a4ffe2';
|
||||
$this->assertTrue(Core::checkSqlQuerySignature($sqlQuery, $hmac));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for Core::checkSqlQuerySignature
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function testCheckSqlQuerySignatureFails()
|
||||
{
|
||||
$_SESSION[' HMAC_secret '] = hash('sha1', '132654987gguieunofz');
|
||||
$sqlQuery = 'SELECT * FROM `test`.`db` WHERE 1;';
|
||||
$hmac = '33371e8680a640dc05944a2a24e6e630d3e9e3dba24464135f2fb954c3a4ffe2';
|
||||
$this->assertFalse(Core::checkSqlQuerySignature($sqlQuery, $hmac));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for Core::checkSqlQuerySignature
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function testCheckSqlQuerySignatureFailsBadHash()
|
||||
{
|
||||
$_SESSION[' HMAC_secret '] = hash('sha1', 'test');
|
||||
$sqlQuery = 'SELECT * FROM `test`.`db` WHERE 1;';
|
||||
$hmac = '3333333380a640dc05944a2a24e6e630d3e9e3dba24464135f2fb954c3eeeeee';
|
||||
$this->assertFalse(Core::checkSqlQuerySignature($sqlQuery, $hmac));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for Core::checkSqlQuerySignature
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function testCheckSqlQuerySignatureFailsNoSession()
|
||||
{
|
||||
$_SESSION[' HMAC_secret '] = 'empty';
|
||||
$sqlQuery = 'SELECT * FROM `test`.`db` WHERE 1;';
|
||||
$hmac = '3333333380a640dc05944a2a24e6e630d3e9e3dba24464135f2fb954c3eeeeee';
|
||||
$this->assertFalse(Core::checkSqlQuerySignature($sqlQuery, $hmac));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for Core::checkSqlQuerySignature
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function testCheckSqlQuerySignatureFailsFromAnotherSession()
|
||||
{
|
||||
$_SESSION[' HMAC_secret '] = hash('sha1', 'firstSession');
|
||||
$sqlQuery = 'SELECT * FROM `test`.`db` WHERE 1;';
|
||||
$hmac = Core::signSqlQuery($sqlQuery);
|
||||
$this->assertTrue(Core::checkSqlQuerySignature($sqlQuery, $hmac));
|
||||
$_SESSION[' HMAC_secret '] = hash('sha1', 'secondSession');
|
||||
// Try to use the token (hmac) from the previous session
|
||||
$this->assertFalse(Core::checkSqlQuerySignature($sqlQuery, $hmac));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for Core::checkSqlQuerySignature
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function testCheckSqlQuerySignatureFailsBlowfishSecretChanged()
|
||||
{
|
||||
$GLOBALS['cfg']['blowfish_secret'] = '';
|
||||
$_SESSION[' HMAC_secret '] = hash('sha1', 'firstSession');
|
||||
$sqlQuery = 'SELECT * FROM `test`.`db` WHERE 1;';
|
||||
$hmac = Core::signSqlQuery($sqlQuery);
|
||||
$this->assertTrue(Core::checkSqlQuerySignature($sqlQuery, $hmac));
|
||||
$GLOBALS['cfg']['blowfish_secret'] = '32154987zd';
|
||||
// Try to use the previous HMAC signature
|
||||
$this->assertFalse(Core::checkSqlQuerySignature($sqlQuery, $hmac));
|
||||
|
||||
$GLOBALS['cfg']['blowfish_secret'] = '32154987zd';
|
||||
// Generate the HMAC signature to check that it works
|
||||
$hmac = Core::signSqlQuery($sqlQuery);
|
||||
// Must work now, (good secret and blowfish_secret)
|
||||
$this->assertTrue(Core::checkSqlQuerySignature($sqlQuery, $hmac));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user