diff --git a/typo3/sysext/core/Classes/Authentication/AbstractUserAuthentication.php b/typo3/sysext/core/Classes/Authentication/AbstractUserAuthentication.php index 58419cbff6f0..376596526c43 100644 --- a/typo3/sysext/core/Classes/Authentication/AbstractUserAuthentication.php +++ b/typo3/sysext/core/Classes/Authentication/AbstractUserAuthentication.php @@ -1019,8 +1019,12 @@ public function unpack_uc($theUC = '') */ public function pushModuleData($module, $data, $noSave = 0) { + $sessionHash = GeneralUtility::hmac( + $this->userSession->getIdentifier(), + 'core-session-hash' + ); $this->uc['moduleData'][$module] = $data; - $this->uc['moduleSessionID'][$module] = $this->userSession->getIdentifier(); + $this->uc['moduleSessionID'][$module] = $sessionHash; if (!$noSave) { $this->writeUC(); } @@ -1035,8 +1039,18 @@ public function pushModuleData($module, $data, $noSave = 0) */ public function getModuleData($module, $type = '') { - if ($type !== 'ses' || (isset($this->uc['moduleSessionID'][$module]) && $this->uc['moduleSessionID'][$module] == $this->userSession->getIdentifier())) { - return $this->uc['moduleData'][$module]; + $sessionHash = GeneralUtility::hmac( + $this->userSession->getIdentifier(), + 'core-session-hash' + ); + $sessionData = $this->uc['moduleData'][$module] ?? null; + $moduleSessionIdHash = $this->uc['moduleSessionID'][$module] ?? null; + if ($type !== 'ses' + || $sessionData !== null && $moduleSessionIdHash === $sessionHash + // @todo Fallback for non-hashed values in `moduleSessionID`, remove for TYPO3 v11.5 LTS + || $sessionData !== null && $moduleSessionIdHash === $this->userSession->getIdentifier() + ) { + return $sessionData; } return null; } diff --git a/typo3/sysext/core/Tests/Functional/Authentication/AbstractUserAuthenticationTest.php b/typo3/sysext/core/Tests/Functional/Authentication/AbstractUserAuthenticationTest.php new file mode 100644 index 000000000000..a3b193581acb --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Authentication/AbstractUserAuthenticationTest.php @@ -0,0 +1,84 @@ +sessionId = bin2hex(random_bytes(20)); + $this->userSession = UserSession::createNonFixated($this->sessionId); + $this->subject = new AnyUserAuthentication($this->userSession); + } + + protected function tearDown(): void + { + unset($this->sessionId, $this->userSession, $this->subject); + unset($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']); + parent::tearDown(); + } + + /** + * @test + */ + public function pushModuleDataDoesNotRevealPlainSessionId(): void + { + $this->subject->pushModuleData(self::class, true); + self::assertNotContains($this->sessionId, $this->subject->uc['moduleSessionID']); + } + + /** + * @test + */ + public function getModuleDataResolvesHashedSessionId(): void + { + $this->subject->pushModuleData(self::class, true); + self::assertTrue($this->subject->getModuleData(self::class)); + } + + /** + * @test + */ + public function getModuleDataFallsBackToPlainSessionId(): void + { + $this->subject->uc['moduleData'][self::class] = true; + $this->subject->uc['moduleSessionID'][self::class] = $this->sessionId; + self::assertTrue($this->subject->getModuleData(self::class)); + } +} diff --git a/typo3/sysext/core/Tests/Functional/Authentication/Fixtures/AnyUserAuthentication.php b/typo3/sysext/core/Tests/Functional/Authentication/Fixtures/AnyUserAuthentication.php new file mode 100644 index 000000000000..321cb614d013 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Authentication/Fixtures/AnyUserAuthentication.php @@ -0,0 +1,40 @@ +userSession = $userSession; + } +}