Authentication granted with multiple firewalls
Description
Symfony is a PHP framework for web and console applications and a set of reusable PHP components. A vulnerability related to firewall authentication is in Symfony starting with version 5.3.0 and prior to 5.3.2. When an application defines multiple firewalls, the token authenticated by one of the firewalls was available for all other firewalls. This could be abused when the application defines different providers for each part of the application, in such a situation, a user authenticated on a part of the application could be considered authenticated on the rest of the application. Starting in version 5.3.2, a patch ensures that the authenticated token is only available for the firewall that generates it.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
symfony/security-httpPackagist | >= 5.3.0, < 5.3.2 | 5.3.2 |
symfony/symfonyPackagist | >= 5.3.0, < 5.3.2 | 5.3.2 |
Affected products
1- Range: >= 5.3.0, < 5.3.2
Patches
26bf4c3121977security #cve-2021-32693 [SecurityHttp] Fix "Authentication granted with multiple firewalls" (wouterj)
2 files changed · +5 −5
Firewall/ContextListener.php+2 −2 modified@@ -95,7 +95,7 @@ public function authenticate(RequestEvent $event) $request = $event->getRequest(); $session = $request->hasPreviousSession() && $request->hasSession() ? $request->getSession() : null; - $request->attributes->set('_security_firewall_run', true); + $request->attributes->set('_security_firewall_run', $this->sessionKey); if (null !== $session) { $usageIndexValue = $session instanceof Session ? $usageIndexReference = &$session->getUsageIndex() : 0; @@ -169,7 +169,7 @@ public function onKernelResponse(ResponseEvent $event) $request = $event->getRequest(); - if (!$request->hasSession() || !$request->attributes->get('_security_firewall_run', false)) { + if (!$request->hasSession() || $request->attributes->get('_security_firewall_run') !== $this->sessionKey) { return; }
Tests/Firewall/ContextListenerTest.php+3 −3 modified@@ -106,7 +106,7 @@ public function testOnKernelResponseWithoutSession() $tokenStorage = new TokenStorage(); $tokenStorage->setToken(new UsernamePasswordToken('test1', 'pass1', 'phpunit')); $request = new Request(); - $request->attributes->set('_security_firewall_run', true); + $request->attributes->set('_security_firewall_run', '_security_session'); $session = new Session(new MockArraySessionStorage()); $request->setSession($session); @@ -212,7 +212,7 @@ public function testOnKernelResponseListenerRemovesItself() $listener = new ContextListener($tokenStorage, [], 'key123', null, $dispatcher); $request = new Request(); - $request->attributes->set('_security_firewall_run', true); + $request->attributes->set('_security_firewall_run', '_security_key123'); $request->setSession($session); $event = new ResponseEvent($this->createMock(HttpKernelInterface::class), $request, HttpKernelInterface::MAIN_REQUEST, new Response()); @@ -370,7 +370,7 @@ protected function runSessionOnKernelResponse($newToken, $original = null) { $session = new Session(new MockArraySessionStorage()); $request = new Request(); - $request->attributes->set('_security_firewall_run', true); + $request->attributes->set('_security_firewall_run', '_security_session'); $request->setSession($session); $requestStack = new RequestStack(); $requestStack->push($request);
3084764ad82fOnly trigger for the correct firewall in ContextListener::onKernelResponse()
6 files changed · +44 −6
src/Symfony/Bundle/SecurityBundle/composer.json+1 −1 modified@@ -29,7 +29,7 @@ "symfony/security-core": "^5.3", "symfony/security-csrf": "^4.4|^5.0", "symfony/security-guard": "^5.3", - "symfony/security-http": "^5.3" + "symfony/security-http": "^5.3.2" }, "require-dev": { "doctrine/annotations": "^1.10.4",
src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Authenticator/multiple_firewalls.yml+17 −0 added@@ -0,0 +1,17 @@ +imports: +- { resource: ./config.yml } +- { resource: ./security.yml } + +security: + enable_authenticator_manager: true + firewalls: + firewall1: + pattern: /firewall1 + provider: in_memory + form_login: + check_path: /firewall1/login + firewall2: + pattern: /firewall2 + provider: in_memory2 + form_login: + check_path: /firewall2/login
src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Authenticator/routing.yml+8 −0 modified@@ -18,3 +18,11 @@ security_main_profile: security_custom_profile: path: /custom/user_profile defaults: { _controller: Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AuthenticatorBundle\SecurityController::profileAction } + +firewall1_login: + path: /firewall1/login + +firewall2_profile: + path: /firewall2/profile + defaults: + _controller: Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AuthenticatorBundle\ProfileController
src/Symfony/Bundle/SecurityBundle/Tests/Functional/AuthenticatorTest.php+13 −0 modified@@ -87,4 +87,17 @@ public function provideEmailsWithFirewalls() yield ['jane@example.org', 'main']; yield ['john@example.org', 'custom']; } + + public function testMultipleFirewalls() + { + $client = $this->createClient(['test_case' => 'Authenticator', 'root_config' => 'multiple_firewalls.yml']); + + $client->request('POST', '/firewall1/login', [ + '_username' => 'jane@example.org', + '_password' => 'test', + ]); + + $client->request('GET', '/firewall2/profile'); + $this->assertResponseRedirects('http://localhost/login'); + } }
src/Symfony/Component/Security/Http/Firewall/ContextListener.php+2 −2 modified@@ -95,7 +95,7 @@ public function authenticate(RequestEvent $event) $request = $event->getRequest(); $session = $request->hasPreviousSession() && $request->hasSession() ? $request->getSession() : null; - $request->attributes->set('_security_firewall_run', true); + $request->attributes->set('_security_firewall_run', $this->sessionKey); if (null !== $session) { $usageIndexValue = $session instanceof Session ? $usageIndexReference = &$session->getUsageIndex() : 0; @@ -169,7 +169,7 @@ public function onKernelResponse(ResponseEvent $event) $request = $event->getRequest(); - if (!$request->hasSession() || !$request->attributes->get('_security_firewall_run', false)) { + if (!$request->hasSession() || $request->attributes->get('_security_firewall_run') !== $this->sessionKey) { return; }
src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php+3 −3 modified@@ -106,7 +106,7 @@ public function testOnKernelResponseWithoutSession() $tokenStorage = new TokenStorage(); $tokenStorage->setToken(new UsernamePasswordToken('test1', 'pass1', 'phpunit')); $request = new Request(); - $request->attributes->set('_security_firewall_run', true); + $request->attributes->set('_security_firewall_run', '_security_session'); $session = new Session(new MockArraySessionStorage()); $request->setSession($session); @@ -212,7 +212,7 @@ public function testOnKernelResponseListenerRemovesItself() $listener = new ContextListener($tokenStorage, [], 'key123', null, $dispatcher); $request = new Request(); - $request->attributes->set('_security_firewall_run', true); + $request->attributes->set('_security_firewall_run', '_security_key123'); $request->setSession($session); $event = new ResponseEvent($this->createMock(HttpKernelInterface::class), $request, HttpKernelInterface::MAIN_REQUEST, new Response()); @@ -370,7 +370,7 @@ protected function runSessionOnKernelResponse($newToken, $original = null) { $session = new Session(new MockArraySessionStorage()); $request = new Request(); - $request->attributes->set('_security_firewall_run', true); + $request->attributes->set('_security_firewall_run', '_security_session'); $request->setSession($session); $requestStack = new RequestStack(); $requestStack->push($request);
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
9- github.com/advisories/GHSA-rfcf-m67m-jcrqghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2021-32693ghsaADVISORY
- github.com/FriendsOfPHP/security-advisories/blob/master/symfony/security-http/CVE-2021-32693.yamlghsaWEB
- github.com/FriendsOfPHP/security-advisories/blob/master/symfony/symfony/CVE-2021-32693.yamlghsaWEB
- github.com/symfony/security-http/commit/6bf4c31219773a558b019ee12e54572174ff8129ghsax_refsource_MISCWEB
- github.com/symfony/symfony/commit/3084764ad82f29dbb025df19978b9cbc3ab34728ghsax_refsource_MISCWEB
- github.com/symfony/symfony/security/advisories/GHSA-rfcf-m67m-jcrqghsax_refsource_CONFIRMWEB
- symfony.com/blog/cve-2021-32693-authentication-granted-to-all-firewalls-instead-of-just-oneghsax_refsource_MISCWEB
- symfony.com/cve-2021-32693ghsaWEB
News mentions
0No linked articles in our index yet.