Skip to content

Commit

Permalink
[SECURITY] Destroy user sessions on password change
Browse files Browse the repository at this point in the history
The password reset process for TYPO3 backend and
frontend users does not destroy possible existing
user sessions after the password has been changed.

With this patch, all existing user sessions are
destroyed when the password is changed in the
password reset process.

Resolves: #98462
Releases: main, 11.5, 10.4
Change-Id: I6744bfcf7cae56b4e525f2e0f9a44d06cf14396c
Security-Bulletin: TYPO3-CORE-SA-2022-014
Security-References: CVE-2022-23502
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/77101
Tested-by: Oliver Hader <[email protected]>
Reviewed-by: Oliver Hader <[email protected]>
  • Loading branch information
derhansen authored and ohader committed Dec 13, 2022
1 parent 28be9cd commit d9ffbf2
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 0 deletions.
13 changes: 13 additions & 0 deletions typo3/sysext/backend/Classes/Authentication/PasswordReset.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
use TYPO3\CMS\Core\PasswordPolicy\PasswordPolicyAction;
use TYPO3\CMS\Core\PasswordPolicy\PasswordPolicyValidator;
use TYPO3\CMS\Core\PasswordPolicy\Validator\Dto\ContextData;
use TYPO3\CMS\Core\Session\SessionManager;
use TYPO3\CMS\Core\SysLog\Action\Login as SystemLogLoginAction;
use TYPO3\CMS\Core\SysLog\Error as SystemLogErrorClassification;
use TYPO3\CMS\Core\SysLog\Type as SystemLogType;
Expand Down Expand Up @@ -340,6 +341,8 @@ public function resetPassword(ServerRequestInterface $request, Context $context)
->getConnectionForTable('be_users')
->update('be_users', ['password_reset_token' => '', 'password' => $this->getHasher()->getHashedPassword($newPassword)], ['uid' => $userId]);

$this->invalidateUserSessions($userId);

$this->logger->info('Password reset successful for user {user_id)', ['user_id' => $userId]);
$this->log(
'Password reset successful for user %s',
Expand Down Expand Up @@ -493,4 +496,14 @@ protected function isValidPassword(string $password, array $user): bool
$contextData = new ContextData(currentPasswordHash: $user['password']);
return $passwordPolicyValidator->isValidPassword($password, $contextData);
}

/**
* Invalidate all backend user sessions by given user id
*/
protected function invalidateUserSessions(int $userId): void
{
$sessionManager = GeneralUtility::makeInstance(SessionManager::class);
$sessionBackend = $sessionManager->getSessionBackend('BE');
$sessionManager->invalidateAllSessionsByUserId($sessionBackend, $userId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use TYPO3\CMS\Core\Context\Exception\AspectNotFoundException;
use TYPO3\CMS\Core\Crypto\PasswordHashing\InvalidPasswordHashException;
use TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashFactory;
use TYPO3\CMS\Core\Session\SessionManager;
use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Error\Error;
Expand Down Expand Up @@ -206,7 +207,9 @@ public function changePasswordAction(string $newPass, string $hash): ResponseInt
return $hashedPassword;
}

$user = $this->userRepository->findOneByForgotPasswordHash(GeneralUtility::hmac($hash));
$this->userRepository->updatePasswordAndInvalidateHash(GeneralUtility::hmac($hash), $hashedPassword);
$this->invalidateUserSessions($user['uid']);

$this->addFlashMessage($this->getTranslation('change_password_done_message'));

Expand Down Expand Up @@ -315,4 +318,14 @@ protected function exposeNoneExistentUser(?array $user): bool
true
);
}

/**
* Invalidate all frontend user sessions by given user id
*/
protected function invalidateUserSessions(int $userId): void
{
$sessionManager = GeneralUtility::makeInstance(SessionManager::class);
$sessionBackend = $sessionManager->getSessionBackend('FE');
$sessionManager->invalidateAllSessionsByUserId($sessionBackend, $userId);
}
}

0 comments on commit d9ffbf2

Please sign in to comment.