diff --git a/libraries/classes/Server/Privileges.php b/libraries/classes/Server/Privileges.php index 301b8fd705..d5eab27246 100644 --- a/libraries/classes/Server/Privileges.php +++ b/libraries/classes/Server/Privileges.php @@ -1551,7 +1551,7 @@ class Privileges $userTable = Util::backquote($configurableMenusFeature->database) . '.' . Util::backquote($configurableMenusFeature->users); $sqlQuery = 'SELECT `usergroup` FROM ' . $userTable - . ' WHERE `username` = \'' . $username . '\'' + . ' WHERE `username` = \'' . $this->dbi->escapeString($username) . '\'' . ' LIMIT 1'; $usergroup = $this->dbi->fetchValue($sqlQuery, 0, DatabaseInterface::CONNECT_CONTROL); diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index d1e71efd54..88e5c32f16 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -47141,9 +47141,14 @@ parameters: count: 7 path: test/classes/Server/PrivilegesTest.php + - + message: "#^Parameter \\#3 \\$subject of function str_replace expects array\\|string, mixed given\\.$#" + count: 1 + path: test/classes/Server/PrivilegesTest.php + - message: "#^Property PhpMyAdmin\\\\Server\\\\Privileges\\:\\:\\$dbi \\(PhpMyAdmin\\\\DatabaseInterface\\) does not accept mixed\\.$#" - count: 10 + count: 11 path: test/classes/Server/PrivilegesTest.php - diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 187ea61028..d99fc80d1f 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -15981,11 +15981,15 @@ - + + $string + + $export $extra_data['new_privileges'] $extra_data['new_user_string'] $extra_data['new_user_string'] + $string $title diff --git a/test/classes/Server/PrivilegesTest.php b/test/classes/Server/PrivilegesTest.php index 0b8d90a5b0..adc2401f41 100644 --- a/test/classes/Server/PrivilegesTest.php +++ b/test/classes/Server/PrivilegesTest.php @@ -1156,6 +1156,29 @@ class PrivilegesTest extends AbstractTestCase $this->serverPrivileges->dbi = $dbi_old; } + public function testGetUserGroupForUserEscapesTheUsername(): void + { + $username = 'pma\' UNION SELECT \'injected'; + + $dbi_old = $GLOBALS['dbi']; + $dbi = $this->createMock(DatabaseInterface::class); + + $dbi->method('escapeString')->willReturnCallback(static function ($string) { + return str_replace("'", "\\'", $string); + }); + $dbi->expects(self::once())->method('fetchValue') + ->with(self::stringContains('WHERE `username` = \'pma\\\' UNION SELECT \\\'injected\'')) + ->willReturn('pma_usergroup'); + + $GLOBALS['dbi'] = $dbi; + $this->serverPrivileges->dbi = $dbi; + + self::assertSame('pma_usergroup', $this->serverPrivileges->getUserGroupForUser($username)); + + $GLOBALS['dbi'] = $dbi_old; + $this->serverPrivileges->dbi = $dbi_old; + } + /** * Test for getUsersOverview */