From 3a8376426768db455e2cff3653e0e84b23aa76a8 Mon Sep 17 00:00:00 2001 From: Greg Roach Date: Thu, 9 Sep 2021 09:05:17 +0100 Subject: [PATCH] Do not allow the reset-password feature to be used for user-enumeration --- .../RequestHandlers/PasswordRequestAction.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/app/Http/RequestHandlers/PasswordRequestAction.php b/app/Http/RequestHandlers/PasswordRequestAction.php index 0cbb7df6847..7ade888b829 100644 --- a/app/Http/RequestHandlers/PasswordRequestAction.php +++ b/app/Http/RequestHandlers/PasswordRequestAction.php @@ -35,6 +35,7 @@ use Psr\Http\Server\RequestHandlerInterface; use function e; +use function random_int; use function redirect; use function route; use function view; @@ -97,15 +98,17 @@ public function handle(ServerRequestInterface $request): ResponseInterface ); Log::addAuthenticationLog('Password request for user: ' . $user->userName()); - - $message1 = I18N::translate('A password reset link has been sent to “%s”.', e($email)); - $message2 = I18N::translate('This link is valid for one hour.'); - FlashMessages::addMessage($message1 . '
' . $message2, 'success'); } else { - $message = I18N::translate('There is no user account with the email “%s”.', e($email)); - FlashMessages::addMessage($message, 'danger'); + // Email takes a few seconds to send. An instant response would allow + // an attacker to use the speed of the response to infer whether an account exists. + usleep(random_int(500000, 2000000)); } + // For security, send a success message even when we fail. + $message1 = I18N::translate('A password reset link has been sent to “%s”.', e($email)); + $message2 = I18N::translate('This link is valid for one hour.'); + FlashMessages::addMessage($message1 . '
' . $message2, 'success'); + return redirect(route(LoginPage::class, ['tree' => $tree instanceof Tree ? $tree->name() : null])); } }