From a804ca15fcad279d7727b91d12a667fd5b925995 Mon Sep 17 00:00:00 2001 From: llupa Date: Sat, 10 Feb 2024 16:22:15 +0100 Subject: [PATCH] [Security] Ignore empty username or password login attempts --- .../Authenticator/FormLoginAuthenticator.php | 8 +++++++ .../Component/Security/Http/CHANGELOG.md | 1 + .../FormLoginAuthenticatorTest.php | 24 +++++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/src/Symfony/Component/Security/Http/Authenticator/FormLoginAuthenticator.php b/src/Symfony/Component/Security/Http/Authenticator/FormLoginAuthenticator.php index 08c265e67129b..9d638b7fd6494 100644 --- a/src/Symfony/Component/Security/Http/Authenticator/FormLoginAuthenticator.php +++ b/src/Symfony/Component/Security/Http/Authenticator/FormLoginAuthenticator.php @@ -129,12 +129,20 @@ private function getCredentials(Request $request): array $credentials['username'] = trim($credentials['username']); + if ('' === $credentials['username']) { + throw new BadRequestHttpException(sprintf('The key "%s" must be a non-empty string.', $this->options['username_parameter'])); + } + $request->getSession()->set(SecurityRequestAttributes::LAST_USERNAME, $credentials['username']); if (!\is_string($credentials['password']) && (!\is_object($credentials['password']) || !method_exists($credentials['password'], '__toString'))) { throw new BadRequestHttpException(sprintf('The key "%s" must be a string, "%s" given.', $this->options['password_parameter'], \gettype($credentials['password']))); } + if ('' === (string) $credentials['password']) { + throw new BadRequestHttpException(sprintf('The key "%s" must be a non-empty string.', $this->options['password_parameter'])); + } + return $credentials; } diff --git a/src/Symfony/Component/Security/Http/CHANGELOG.md b/src/Symfony/Component/Security/Http/CHANGELOG.md index e6383fe5ecf8e..a8e710597a989 100644 --- a/src/Symfony/Component/Security/Http/CHANGELOG.md +++ b/src/Symfony/Component/Security/Http/CHANGELOG.md @@ -6,6 +6,7 @@ CHANGELOG * Add `#[IsCsrfTokenValid]` attribute * Add CAS 2.0 access token handler + * Make empty username or empty password on form login attempts return Bad Request (400) 7.0 --- diff --git a/src/Symfony/Component/Security/Http/Tests/Authenticator/FormLoginAuthenticatorTest.php b/src/Symfony/Component/Security/Http/Tests/Authenticator/FormLoginAuthenticatorTest.php index af5c4fad267be..bc8c49b2b3d14 100644 --- a/src/Symfony/Component/Security/Http/Tests/Authenticator/FormLoginAuthenticatorTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Authenticator/FormLoginAuthenticatorTest.php @@ -42,6 +42,30 @@ protected function setUp(): void $this->failureHandler = $this->createMock(AuthenticationFailureHandlerInterface::class); } + public function testHandleWhenUsernameEmpty() + { + $this->expectException(BadRequestHttpException::class); + $this->expectExceptionMessage('The key "_username" must be a non-empty string.'); + + $request = Request::create('/login_check', 'POST', ['_username' => '', '_password' => 's$cr$t']); + $request->setSession($this->createSession()); + + $this->setUpAuthenticator(); + $this->authenticator->authenticate($request); + } + + public function testHandleWhenPasswordEmpty() + { + $this->expectException(BadRequestHttpException::class); + $this->expectExceptionMessage('The key "_password" must be a non-empty string.'); + + $request = Request::create('/login_check', 'POST', ['_username' => 'foo', '_password' => '']); + $request->setSession($this->createSession()); + + $this->setUpAuthenticator(); + $this->authenticator->authenticate($request); + } + /** * @dataProvider provideUsernamesForLength */