From: Christian Flothmann <christian.flothmann@xabbuh.de>
Date: Thu, 5 Nov 2015 23:29:27 +0100
Subject: CVE-2015-8124: Session Fixation in the "Remember Me" Login Feature

Origin: upstream, https://github.com/symfony/symfony/pull/16631
---
 .../Security/Http/Firewall/RememberMeListener.php  |  8 +++
 .../Tests/Http/Firewall/RememberMeListenerTest.php | 63 ++++++++++++++++++++++
 2 files changed, 71 insertions(+)

diff --git a/src/Symfony/Component/Security/Http/Firewall/RememberMeListener.php b/src/Symfony/Component/Security/Http/Firewall/RememberMeListener.php
index 6ca3842..60e42a9 100644
--- a/src/Symfony/Component/Security/Http/Firewall/RememberMeListener.php
+++ b/src/Symfony/Component/Security/Http/Firewall/RememberMeListener.php
@@ -20,6 +20,7 @@ use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
 use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
 use Symfony\Component\Security\Http\SecurityEvents;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy;
 
 /**
  * RememberMeListener implements authentication capabilities via a cookie
@@ -33,6 +34,7 @@ class RememberMeListener implements ListenerInterface
     private $authenticationManager;
     private $logger;
     private $dispatcher;
+    private $sessionStrategy;
 
     /**
      * Constructor.
@@ -50,6 +52,7 @@ class RememberMeListener implements ListenerInterface
         $this->authenticationManager = $authenticationManager;
         $this->logger = $logger;
         $this->dispatcher = $dispatcher;
+        $this->sessionStrategy = new SessionAuthenticationStrategy(SessionAuthenticationStrategy::MIGRATE);
     }
 
     /**
@@ -70,6 +73,11 @@ class RememberMeListener implements ListenerInterface
 
         try {
             $token = $this->authenticationManager->authenticate($token);
+
+            if ($request->hasSession() && $request->getSession()->isStarted()) {
+                $this->sessionStrategy->onAuthentication($request, $token);
+            }
+
             $this->securityContext->setToken($token);
 
             if (null !== $this->dispatcher) {
diff --git a/src/Symfony/Component/Security/Tests/Http/Firewall/RememberMeListenerTest.php b/src/Symfony/Component/Security/Tests/Http/Firewall/RememberMeListenerTest.php
index 8ad4c55..b8400f8 100644
--- a/src/Symfony/Component/Security/Tests/Http/Firewall/RememberMeListenerTest.php
+++ b/src/Symfony/Component/Security/Tests/Http/Firewall/RememberMeListenerTest.php
@@ -153,6 +153,69 @@ class RememberMeListenerTest extends \PHPUnit_Framework_TestCase
         $listener->handle($event);
     }
 
+    public function testSessionStrategy()
+    {
+        list($listener, $tokenStorage, $service, $manager) = $this->getListener(false, true, true);
+
+        $tokenStorage
+            ->expects($this->once())
+            ->method('getToken')
+            ->will($this->returnValue(null))
+        ;
+
+        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
+        $service
+            ->expects($this->once())
+            ->method('autoLogin')
+            ->will($this->returnValue($token))
+        ;
+
+        $tokenStorage
+            ->expects($this->once())
+            ->method('setToken')
+            ->with($this->equalTo($token))
+        ;
+
+        $manager
+            ->expects($this->once())
+            ->method('authenticate')
+            ->will($this->returnValue($token))
+        ;
+
+        $session = $this->getMock('\Symfony\Component\HttpFoundation\Session\SessionInterface');
+        $session
+            ->expects($this->once())
+            ->method('isStarted')
+            ->will($this->returnValue(true))
+        ;
+        $session
+            ->expects($this->once())
+            ->method('migrate')
+        ;
+
+        $request = $this->getMock('\Symfony\Component\HttpFoundation\Request');
+        $request
+            ->expects($this->any())
+            ->method('hasSession')
+            ->will($this->returnValue(true))
+        ;
+
+        $request
+            ->expects($this->any())
+            ->method('getSession')
+            ->will($this->returnValue($session))
+        ;
+
+        $event = $this->getGetResponseEvent();
+        $event
+            ->expects($this->once())
+            ->method('getRequest')
+            ->will($this->returnValue($request))
+        ;
+
+        $listener->handle($event);
+    }
+
     protected function getGetResponseEvent()
     {
         return $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false);
