Skip to content

Commit

Permalink
[TASK] Streamline frontend user password recovery process
Browse files Browse the repository at this point in the history
The ext:felogin recovery process is using a non-typesafe comparison
which might be exploited with a probability of 0.000000294% and is
storing the recovery token as plain MD5-hash in database.

In order to streamline the process non-typesafe comparison is using
PHP's hash_equals() method; for keeping backward compatibility just
HMAC-SHA1 is applied to the recovery token in database.

Since exploitations to this scenario are very unlikely (for a 50%
chance an attacker would have to trigger the creation of around
170 million recovery requests) it is not handled with a security
workflow - but using the public workflow.

Resolves: #89952
Releases: master, 10.2, 9.5, 8.7
Change-Id: Idcb7b7d6eb418124dc17f1707284b6abe8a8b63b
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/62693
Tested-by: Oliver Hader <oliver.hader@typo3.org>
Reviewed-by: Oliver Hader <oliver.hader@typo3.org>
  • Loading branch information
ohader committed Dec 17, 2019
1 parent 6ea5b19 commit d075cde
Showing 1 changed file with 8 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,13 @@ protected function changePassword()
$user = $this->pi_getRecord('fe_users', (int)$uid);
$userHash = $user['felogin_forgotHash'];
$compareHash = explode('|', $userHash);
if (!$compareHash || !$compareHash[1] || $compareHash[0] < time() || $hash[0] != $compareHash[0] || md5($hash[1]) != $compareHash[1]) {
if (strlen($compareHash[1]) === 40) {
$hashEquals = hash_equals($compareHash[1], GeneralUtility::hmac((string)$hash[1]));
} else {
// backward-compatibility for previous MD5 hashes
$hashEquals = hash_equals($compareHash[1], md5($hash[1]));
}
if (!$compareHash || !$compareHash[1] || $compareHash[0] < time() || !hash_equals($compareHash[0], $hash[0]) || !$hashEquals) {
$markerArray['###STATUS_MESSAGE###'] = $this->getDisplayText(
'change_password_notvalid_message',
$this->conf['changePasswordNotValidMessage_stdWrap.']
Expand Down Expand Up @@ -459,7 +465,7 @@ protected function generateAndSendHash($user)
$validEndString = date($this->conf['dateFormat'], $validEnd);
$hash = md5(GeneralUtility::makeInstance(Random::class)->generateRandomBytes(64));
$randHash = $validEnd . '|' . $hash;
$randHashDB = $validEnd . '|' . md5($hash);
$randHashDB = $validEnd . '|' . GeneralUtility::hmac($hash);

// Write hash to DB
$userTable = $this->frontendController->fe_user->user_table;
Expand Down

0 comments on commit d075cde

Please # to comment.