VYPR
Moderate severityNVD Advisory· Published Feb 3, 2023· Updated Mar 10, 2025

Symfony vulnerable to Session Fixation of CSRF tokens

CVE-2022-24895

Description

Symfony is a PHP framework for web and console applications and a set of reusable PHP components. When authenticating users Symfony by default regenerates the session ID upon login, but preserves the rest of session attributes. Because this does not clear CSRF tokens upon login, this might enables same-site attackers to bypass the CSRF protection mechanism by performing an attack similar to a session-fixation. This issue has been fixed in the 4.4 branch.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
symfony/security-bundlePackagist
>= 2.0.0, < 4.4.504.4.50
symfony/security-bundlePackagist
>= 5.0.0, < 5.4.205.4.20
symfony/security-bundlePackagist
>= 6.0.0, < 6.0.206.0.20
symfony/security-bundlePackagist
>= 6.1.0, < 6.1.126.1.12
symfony/security-bundlePackagist
>= 6.2.0, < 6.2.66.2.6
symfony/symfonyPackagist
>= 2.0.0, < 4.4.504.4.50
symfony/symfonyPackagist
>= 5.0.0, < 5.4.205.4.20
symfony/symfonyPackagist
>= 6.0.0, < 6.0.206.0.20
symfony/symfonyPackagist
>= 6.1.0, < 6.1.126.1.12
symfony/symfonyPackagist
>= 6.2.0, < 6.2.66.2.6

Affected products

1

Patches

2
076fd2088ada

[Security/Http] Remove CSRF tokens from storage on successful login

https://github.com/symfony/security-bundleNicolas GrekasJan 23, 2023via ghsa
4 files changed · +9 4
  • composer.json+1 1 modified
    @@ -25,7 +25,7 @@
             "symfony/security-core": "^4.4",
             "symfony/security-csrf": "^4.2|^5.0",
             "symfony/security-guard": "^4.2|^5.0",
    -        "symfony/security-http": "^4.4.5"
    +        "symfony/security-http": "^4.4.50"
         },
         "require-dev": {
             "doctrine/annotations": "^1.10.4",
    
  • Resources/config/security.xml+1 0 modified
    @@ -63,6 +63,7 @@
     
             <service id="security.authentication.session_strategy" class="Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy">
                 <argument>%security.authentication.session_strategy.strategy%</argument>
    +            <argument type="service" id="security.csrf.token_storage" on-invalid="ignore" />
             </service>
             <service id="Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface" alias="security.authentication.session_strategy" />
     
    
  • Tests/Functional/CsrfFormLoginTest.php+6 0 modified
    @@ -19,12 +19,15 @@ class CsrfFormLoginTest extends AbstractWebTestCase
         public function testFormLoginAndLogoutWithCsrfTokens($config)
         {
             $client = $this->createClient(['test_case' => 'CsrfFormLogin', 'root_config' => $config]);
    +        static::$container->get('security.csrf.token_storage')->setToken('foo', 'bar');
     
             $form = $client->request('GET', '/login')->selectButton('login')->form();
             $form['user_login[username]'] = 'johannes';
             $form['user_login[password]'] = 'test';
             $client->submit($form);
     
    +        $this->assertFalse(static::$container->get('security.csrf.token_storage')->hasToken('foo'));
    +
             $this->assertRedirect($client->getResponse(), '/profile');
     
             $crawler = $client->followRedirect();
    @@ -48,11 +51,14 @@ public function testFormLoginAndLogoutWithCsrfTokens($config)
         public function testFormLoginWithInvalidCsrfToken($config)
         {
             $client = $this->createClient(['test_case' => 'CsrfFormLogin', 'root_config' => $config]);
    +        static::$container->get('security.csrf.token_storage')->setToken('foo', 'bar');
     
             $form = $client->request('GET', '/login')->selectButton('login')->form();
             $form['user_login[_token]'] = '';
             $client->submit($form);
     
    +        $this->assertTrue(static::$container->get('security.csrf.token_storage')->hasToken('foo'));
    +
             $this->assertRedirect($client->getResponse(), '/login');
     
             $text = $client->followRedirect()->text(null, true);
    
  • Tests/Functional/LogoutTest.php+1 3 modified
    @@ -36,15 +36,13 @@ public function testSessionLessRememberMeLogout()
         public function testCsrfTokensAreClearedOnLogout()
         {
             $client = $this->createClient(['test_case' => 'LogoutWithoutSessionInvalidation', 'root_config' => 'config.yml']);
    -        static::$container->get('security.csrf.token_storage')->setToken('foo', 'bar');
     
             $client->request('POST', '/login', [
                 '_username' => 'johannes',
                 '_password' => 'test',
             ]);
     
    -        $this->assertTrue(static::$container->get('security.csrf.token_storage')->hasToken('foo'));
    -        $this->assertSame('bar', static::$container->get('security.csrf.token_storage')->getToken('foo'));
    +        static::$container->get('security.csrf.token_storage')->setToken('foo', 'bar');
     
             $client->request('GET', '/logout');
     
    
5909d74ecee3

[Security/Http] Remove CSRF tokens from storage on successful login

https://github.com/symfony/symfonyNicolas GrekasJan 23, 2023via ghsa
6 files changed · +33 7
  • src/Symfony/Bundle/SecurityBundle/composer.json+1 1 modified
    @@ -25,7 +25,7 @@
             "symfony/security-core": "^4.4",
             "symfony/security-csrf": "^4.2|^5.0",
             "symfony/security-guard": "^4.2|^5.0",
    -        "symfony/security-http": "^4.4.5"
    +        "symfony/security-http": "^4.4.50"
         },
         "require-dev": {
             "doctrine/annotations": "^1.10.4",
    
  • src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml+1 0 modified
    @@ -63,6 +63,7 @@
     
             <service id="security.authentication.session_strategy" class="Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy">
                 <argument>%security.authentication.session_strategy.strategy%</argument>
    +            <argument type="service" id="security.csrf.token_storage" on-invalid="ignore" />
             </service>
             <service id="Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface" alias="security.authentication.session_strategy" />
     
    
  • src/Symfony/Bundle/SecurityBundle/Tests/Functional/CsrfFormLoginTest.php+6 0 modified
    @@ -19,12 +19,15 @@ class CsrfFormLoginTest extends AbstractWebTestCase
         public function testFormLoginAndLogoutWithCsrfTokens($config)
         {
             $client = $this->createClient(['test_case' => 'CsrfFormLogin', 'root_config' => $config]);
    +        static::$container->get('security.csrf.token_storage')->setToken('foo', 'bar');
     
             $form = $client->request('GET', '/login')->selectButton('login')->form();
             $form['user_login[username]'] = 'johannes';
             $form['user_login[password]'] = 'test';
             $client->submit($form);
     
    +        $this->assertFalse(static::$container->get('security.csrf.token_storage')->hasToken('foo'));
    +
             $this->assertRedirect($client->getResponse(), '/profile');
     
             $crawler = $client->followRedirect();
    @@ -48,11 +51,14 @@ public function testFormLoginAndLogoutWithCsrfTokens($config)
         public function testFormLoginWithInvalidCsrfToken($config)
         {
             $client = $this->createClient(['test_case' => 'CsrfFormLogin', 'root_config' => $config]);
    +        static::$container->get('security.csrf.token_storage')->setToken('foo', 'bar');
     
             $form = $client->request('GET', '/login')->selectButton('login')->form();
             $form['user_login[_token]'] = '';
             $client->submit($form);
     
    +        $this->assertTrue(static::$container->get('security.csrf.token_storage')->hasToken('foo'));
    +
             $this->assertRedirect($client->getResponse(), '/login');
     
             $text = $client->followRedirect()->text(null, true);
    
  • src/Symfony/Bundle/SecurityBundle/Tests/Functional/LogoutTest.php+1 3 modified
    @@ -36,15 +36,13 @@ public function testSessionLessRememberMeLogout()
         public function testCsrfTokensAreClearedOnLogout()
         {
             $client = $this->createClient(['test_case' => 'LogoutWithoutSessionInvalidation', 'root_config' => 'config.yml']);
    -        static::$container->get('security.csrf.token_storage')->setToken('foo', 'bar');
     
             $client->request('POST', '/login', [
                 '_username' => 'johannes',
                 '_password' => 'test',
             ]);
     
    -        $this->assertTrue(static::$container->get('security.csrf.token_storage')->hasToken('foo'));
    -        $this->assertSame('bar', static::$container->get('security.csrf.token_storage')->getToken('foo'));
    +        static::$container->get('security.csrf.token_storage')->setToken('foo', 'bar');
     
             $client->request('GET', '/logout');
     
    
  • src/Symfony/Component/Security/Http/Session/SessionAuthenticationStrategy.php+11 3 modified
    @@ -13,6 +13,7 @@
     
     use Symfony\Component\HttpFoundation\Request;
     use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
    +use Symfony\Component\Security\Csrf\TokenStorage\ClearableTokenStorageInterface;
     
     /**
      * The default session strategy implementation.
    @@ -31,10 +32,15 @@ class SessionAuthenticationStrategy implements SessionAuthenticationStrategyInte
         public const INVALIDATE = 'invalidate';
     
         private $strategy;
    +    private $csrfTokenStorage = null;
     
    -    public function __construct(string $strategy)
    +    public function __construct(string $strategy, ClearableTokenStorageInterface $csrfTokenStorage = null)
         {
             $this->strategy = $strategy;
    +
    +        if (self::MIGRATE === $strategy) {
    +            $this->csrfTokenStorage = $csrfTokenStorage;
    +        }
         }
     
         /**
    @@ -47,10 +53,12 @@ public function onAuthentication(Request $request, TokenInterface $token)
                     return;
     
                 case self::MIGRATE:
    -                // Note: this logic is duplicated in several authentication listeners
    -                // until Symfony 5.0 due to a security fix with BC compat
                     $request->getSession()->migrate(true);
     
    +                if ($this->csrfTokenStorage) {
    +                    $this->csrfTokenStorage->clear();
    +                }
    +
                     return;
     
                 case self::INVALIDATE:
    
  • src/Symfony/Component/Security/Http/Tests/Session/SessionAuthenticationStrategyTest.php+13 0 modified
    @@ -14,6 +14,7 @@
     use PHPUnit\Framework\TestCase;
     use Symfony\Component\HttpFoundation\Request;
     use Symfony\Component\HttpFoundation\Session\SessionInterface;
    +use Symfony\Component\Security\Csrf\TokenStorage\ClearableTokenStorageInterface;
     use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy;
     use Symfony\Component\Security\Http\Tests\Fixtures\TokenInterface;
     
    @@ -57,6 +58,18 @@ public function testSessionIsInvalidated()
             $strategy->onAuthentication($this->getRequest($session), $this->createMock(TokenInterface::class));
         }
     
    +    public function testCsrfTokensAreCleared()
    +    {
    +        $session = $this->createMock(SessionInterface::class);
    +        $session->expects($this->once())->method('migrate')->with($this->equalTo(true));
    +
    +        $csrfStorage = $this->createMock(ClearableTokenStorageInterface::class);
    +        $csrfStorage->expects($this->once())->method('clear');
    +
    +        $strategy = new SessionAuthenticationStrategy(SessionAuthenticationStrategy::MIGRATE, $csrfStorage);
    +        $strategy->onAuthentication($this->getRequest($session), $this->createMock(TokenInterface::class));
    +    }
    +
         private function getRequest($session = null)
         {
             $request = $this->createMock(Request::class);
    

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

News mentions

0

No linked articles in our index yet.