diff --git a/CHANGELOG.md b/CHANGELOG.md index bdb7ae655..ab0365a17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ This file is a running track of new features and fixes to each version of the pa This project follows [Semantic Versioning](http://semver.org) guidelines. +## v0.7.9 (Derelict Dermodactylus) +### Fixed +* Fixes a two-factor authentication bypass present in the password reset process for an account. + ## v0.7.8 (Derelict Dermodactylus) ### Added * Nodes can now be put into maintenance mode to deny access to servers temporarily. diff --git a/app/Http/Controllers/Auth/ResetPasswordController.php b/app/Http/Controllers/Auth/ResetPasswordController.php index 468a7f6d6..22aee3eb5 100644 --- a/app/Http/Controllers/Auth/ResetPasswordController.php +++ b/app/Http/Controllers/Auth/ResetPasswordController.php @@ -2,12 +2,17 @@ namespace Pterodactyl\Http\Controllers\Auth; +use Illuminate\Support\Str; use Illuminate\Http\JsonResponse; +use Illuminate\Contracts\Hashing\Hasher; use Illuminate\Support\Facades\Password; +use Illuminate\Auth\Events\PasswordReset; +use Illuminate\Contracts\Events\Dispatcher; use Pterodactyl\Exceptions\DisplayException; use Pterodactyl\Http\Controllers\Controller; use Illuminate\Foundation\Auth\ResetsPasswords; use Pterodactyl\Http\Requests\Auth\ResetPasswordRequest; +use Pterodactyl\Contracts\Repository\UserRepositoryInterface; class ResetPasswordController extends Controller { @@ -20,6 +25,40 @@ class ResetPasswordController extends Controller */ public $redirectTo = '/'; + /** + * @var bool + */ + protected $hasTwoFactor = false; + + /** + * @var \Illuminate\Contracts\Events\Dispatcher + */ + private $dispatcher; + + /** + * @var \Illuminate\Contracts\Hashing\Hasher + */ + private $hasher; + + /** + * @var \Pterodactyl\Contracts\Repository\UserRepositoryInterface + */ + private $userRepository; + + /** + * ResetPasswordController constructor. + * + * @param \Illuminate\Contracts\Events\Dispatcher $dispatcher + * @param \Illuminate\Contracts\Hashing\Hasher $hasher + * @param \Pterodactyl\Contracts\Repository\UserRepositoryInterface $userRepository + */ + public function __construct(Dispatcher $dispatcher, Hasher $hasher, UserRepositoryInterface $userRepository) + { + $this->dispatcher = $dispatcher; + $this->hasher = $hasher; + $this->userRepository = $userRepository; + } + /** * Reset the given user's password. * @@ -49,6 +88,35 @@ class ResetPasswordController extends Controller throw new DisplayException(trans($response)); } + /** + * Reset the given user's password. If the user has two-factor authentication enabled on their + * account do not automatically log them in. In those cases, send the user back to the login + * form with a note telling them their password was changed and to log back in. + * + * @param \Illuminate\Contracts\Auth\CanResetPassword|\Pterodactyl\Models\User $user + * @param string $password + * + * @throws \Pterodactyl\Exceptions\Model\DataValidationException + * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException + */ + protected function resetPassword($user, $password) + { + $user = $this->userRepository->update($user->id, [ + 'password' => $this->hasher->make($password), + $user->getRememberTokenName() => Str::random(60), + ]); + + $this->dispatcher->dispatch(new PasswordReset($user)); + + // If the user is not using 2FA log them in, otherwise skip this step and force a + // fresh login where they'll be prompted to enter a token. + if (! $user->use_totp) { + $this->guard()->login($user); + } + + $this->hasTwoFactor = $user->use_totp; + } + /** * Send a successful password reset response back to the callee. * @@ -59,6 +127,7 @@ class ResetPasswordController extends Controller return response()->json([ 'success' => true, 'redirect_to' => $this->redirectTo, + 'send_to_login' => $this->hasTwoFactor, ]); } }