Skip to content

Commit b501bba

Browse files
glaubinixnicolas-grekas
authored andcommitted
[Security] Validate that CSRF token in form login is string similar to username/password
1 parent 85d0165 commit b501bba

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

src/Symfony/Component/Security/Http/Authenticator/FormLoginAuthenticator.php

+4
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,10 @@ private function getCredentials(Request $request): array
161161
throw new BadRequestHttpException(sprintf('The key "%s" must be a string, "%s" given.', $this->options['password_parameter'], \gettype($credentials['password'])));
162162
}
163163

164+
if (!\is_string($credentials['csrf_token'] ?? '') && (!\is_object($credentials['csrf_token']) || !method_exists($credentials['csrf_token'], '__toString'))) {
165+
throw new BadRequestHttpException(sprintf('The key "%s" must be a string, "%s" given.', $this->options['csrf_parameter'], \gettype($credentials['csrf_token'])));
166+
}
167+
164168
return $credentials;
165169
}
166170

src/Symfony/Component/Security/Http/Tests/Authenticator/FormLoginAuthenticatorTest.php

+48
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,54 @@ public function __toString()
165165
$this->assertSame('s$cr$t', $credentialsBadge->getPassword());
166166
}
167167

168+
/**
169+
* @dataProvider postOnlyDataProvider
170+
*/
171+
public function testHandleNonStringCsrfTokenWithArray($postOnly)
172+
{
173+
$request = Request::create('/login_check', 'POST', ['_username' => 'foo', 'password' => 'bar', '_csrf_token' => []]);
174+
$request->setSession($this->createSession());
175+
176+
$this->setUpAuthenticator(['post_only' => $postOnly]);
177+
178+
$this->expectException(BadRequestHttpException::class);
179+
$this->expectExceptionMessage('The key "_csrf_token" must be a string, "array" given.');
180+
181+
$this->authenticator->authenticate($request);
182+
}
183+
184+
/**
185+
* @dataProvider postOnlyDataProvider
186+
*/
187+
public function testHandleNonStringCsrfTokenWithInt($postOnly)
188+
{
189+
$request = Request::create('/login_check', 'POST', ['_username' => 'foo', 'password' => 'bar', '_csrf_token' => 42]);
190+
$request->setSession($this->createSession());
191+
192+
$this->setUpAuthenticator(['post_only' => $postOnly]);
193+
194+
$this->expectException(BadRequestHttpException::class);
195+
$this->expectExceptionMessage('The key "_csrf_token" must be a string, "integer" given.');
196+
197+
$this->authenticator->authenticate($request);
198+
}
199+
200+
/**
201+
* @dataProvider postOnlyDataProvider
202+
*/
203+
public function testHandleNonStringCsrfTokenWithObject($postOnly)
204+
{
205+
$request = Request::create('/login_check', 'POST', ['_username' => 'foo', 'password' => 'bar', '_csrf_token' => new \stdClass()]);
206+
$request->setSession($this->createSession());
207+
208+
$this->setUpAuthenticator(['post_only' => $postOnly]);
209+
210+
$this->expectException(BadRequestHttpException::class);
211+
$this->expectExceptionMessage('The key "_csrf_token" must be a string, "object" given.');
212+
213+
$this->authenticator->authenticate($request);
214+
}
215+
168216
public static function postOnlyDataProvider()
169217
{
170218
yield [true];

0 commit comments

Comments
 (0)