diff --git a/typo3/sysext/core/Classes/Error/AbstractExceptionHandler.php b/typo3/sysext/core/Classes/Error/AbstractExceptionHandler.php index 2dd0aee73903..124f6d2762bb 100644 --- a/typo3/sysext/core/Classes/Error/AbstractExceptionHandler.php +++ b/typo3/sysext/core/Classes/Error/AbstractExceptionHandler.php @@ -47,6 +47,7 @@ abstract class AbstractExceptionHandler implements ExceptionHandlerInterface, Si 1616175867, // Backend login request is rate limited 1616175847, // Frontend login request is rate limited 1436717275, // Request with unsupported HTTP method + 1699604555, // Outdated __trustedProperties format in extbase property mapping ]; public const IGNORED_HMAC_EXCEPTION_CODES = [ diff --git a/typo3/sysext/extbase/Classes/Mvc/Controller/MvcPropertyMappingConfigurationService.php b/typo3/sysext/extbase/Classes/Mvc/Controller/MvcPropertyMappingConfigurationService.php index 2ac1154fbc73..cfaa2a47b398 100644 --- a/typo3/sysext/extbase/Classes/Mvc/Controller/MvcPropertyMappingConfigurationService.php +++ b/typo3/sysext/extbase/Classes/Mvc/Controller/MvcPropertyMappingConfigurationService.php @@ -137,11 +137,18 @@ public function initializePropertyMappingConfigurationFromRequest(Request $reque } try { - $serializedTrustedProperties = $this->hashService->validateAndStripHmac($trustedPropertiesToken); + $encodedTrustedProperties = $this->hashService->validateAndStripHmac($trustedPropertiesToken); } catch (InvalidHashException | InvalidArgumentForHashGenerationException $e) { throw new BadRequestException('The HMAC of the form could not be validated.', 1581862822); } - $trustedProperties = json_decode($serializedTrustedProperties, true); + $trustedProperties = json_decode($encodedTrustedProperties, true); + if (!is_array($trustedProperties)) { + if (str_starts_with($encodedTrustedProperties, 'a:')) { + throw new BadRequestException('Trusted properties used outdated serialization format instead of json.', 1699604555); + } + throw new BadRequestException('The HMAC of the form could not be utilized.', 1691267306); + } + foreach ($trustedProperties as $propertyName => $propertyConfiguration) { if (!$controllerArguments->hasArgument($propertyName)) { continue; diff --git a/typo3/sysext/extbase/Tests/Unit/Mvc/Controller/MvcPropertyMappingConfigurationServiceTest.php b/typo3/sysext/extbase/Tests/Unit/Mvc/Controller/MvcPropertyMappingConfigurationServiceTest.php index 53fc33e640ae..2fb794edae30 100644 --- a/typo3/sysext/extbase/Tests/Unit/Mvc/Controller/MvcPropertyMappingConfigurationServiceTest.php +++ b/typo3/sysext/extbase/Tests/Unit/Mvc/Controller/MvcPropertyMappingConfigurationServiceTest.php @@ -209,6 +209,49 @@ public function initializePropertyMappingConfigurationThrowsBadRequestExceptionO $requestHashService->initializePropertyMappingConfigurationFromRequest($request, $arguments); } + /** + * @test + */ + public function initializePropertyMappingConfigurationWithNonDecodableTrustedPropertiesThrowsException(): void + { + $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] = 'bar'; + $hashService = new HashService(); + $request = $this->getMockBuilder(Request::class)->onlyMethods(['getInternalArgument'])->disableOriginalConstructor()->getMock(); + $request->method('getInternalArgument')->with('__trustedProperties')->willReturn('garbage' . $hashService->generateHmac('garbage')); + $arguments = new Arguments(); + + $arguments = new Arguments(); + $requestHashService = new MvcPropertyMappingConfigurationService(); + $requestHashService->injectHashService($hashService); + + $this->expectException(BadRequestException::class); + $this->expectExceptionMessage('The HMAC of the form could not be utilized.'); + $this->expectExceptionCode(1691267306); + + $requestHashService->initializePropertyMappingConfigurationFromRequest($request, $arguments); + } + + /** + * @test + */ + public function initializePropertyMappingConfigurationWithOutdatedTrustedPropertiesThrowsException(): void + { + $hashService = new HashService(); + $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] = 'bar'; + $request = $this->getMockBuilder(Request::class)->onlyMethods(['getInternalArgument'])->disableOriginalConstructor()->getMock(); + $request->method('getInternalArgument')->with('__trustedProperties')->willReturn('a:1:{s:3:"foo";s:3:"bar";}' . $hashService->generateHmac('a:1:{s:3:"foo";s:3:"bar";}')); + + $arguments = new Arguments(); + $requestHashService = new MvcPropertyMappingConfigurationService(); + $requestHashService->injectHashService($hashService); + + $this->expectException(BadRequestException::class); + $this->expectExceptionMessage('Trusted properties used outdated serialization format instead of json.'); + $this->expectExceptionCode(1699604555); + + $requestHashService->initializePropertyMappingConfigurationFromRequest($request, $arguments); + } + /** * @test */