From: Nicolas Grekas <nicolas.grekas@gmail.com>
Date: Thu, 11 Jan 2018 10:05:15 +0100
Subject: [SecurityBundle] Fail if security.http_utils cannot be configured

[CVE-2018-11408] https://symfony.com/blog/cve-2018-11408-open-redirect-vulnerability-on-security-handlers

Origin: upstream, https://github.com/symfony/symfony/commit/c003b7a247296e7fdcfb20c2eb175cfb7aaf3c4e
---
 .../Compiler/AddSessionDomainConstraintPass.php             |  3 ++-
 src/Symfony/Bundle/SecurityBundle/SecurityBundle.php        |  2 +-
 .../Compiler/AddSessionDomainConstraintPassTest.php         | 13 +++++++++++++
 3 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSessionDomainConstraintPass.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSessionDomainConstraintPass.php
index 0adc143..f4a1977 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSessionDomainConstraintPass.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSessionDomainConstraintPass.php
@@ -27,7 +27,7 @@ class AddSessionDomainConstraintPass implements CompilerPassInterface
      */
     public function process(ContainerBuilder $container)
     {
-        if (!$container->hasParameter('session.storage.options') || !$container->has('security.http_utils')) {
+        if (!$container->hasParameter('session.storage.options')) {
             return;
         }
 
@@ -35,6 +35,7 @@ class AddSessionDomainConstraintPass implements CompilerPassInterface
         $domainRegexp = empty($sessionOptions['cookie_domain']) ? '%s' : sprintf('(?:%%s|(?:.+\.)?%s)', preg_quote(trim($sessionOptions['cookie_domain'], '.')));
         $domainRegexp = (empty($sessionOptions['cookie_secure']) ? 'https?://' : 'https://').$domainRegexp;
 
+        // if the service doesn't exist, an exception must be thrown - ignoring would put security at risk
         $container->findDefinition('security.http_utils')->addArgument(sprintf('{^%s$}i', $domainRegexp));
     }
 }
diff --git a/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php b/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php
index bee07f3..18f5db4 100644
--- a/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php
+++ b/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php
@@ -58,7 +58,7 @@ class SecurityBundle extends Bundle
         $extension->addUserProviderFactory(new InMemoryFactory());
         $extension->addUserProviderFactory(new LdapFactory());
         $container->addCompilerPass(new AddSecurityVotersPass());
-        $container->addCompilerPass(new AddSessionDomainConstraintPass(), PassConfig::TYPE_AFTER_REMOVING);
+        $container->addCompilerPass(new AddSessionDomainConstraintPass(), PassConfig::TYPE_BEFORE_REMOVING);
         $container->addCompilerPass(new RegisterCsrfTokenClearingLogoutHandlerPass());
     }
 }
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSessionDomainConstraintPassTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSessionDomainConstraintPassTest.php
index f476b5e..d7ed975 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSessionDomainConstraintPassTest.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSessionDomainConstraintPassTest.php
@@ -96,6 +96,19 @@ class AddSessionDomainConstraintPassTest extends TestCase
         $this->assertTrue($utils->createRedirectResponse($request, 'http://pirate.com/foo')->isRedirect('http://pirate.com/foo'));
     }
 
+    /**
+     * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException
+     * @expectedExceptionMessage You have requested a non-existent service "security.http_utils".
+     */
+    public function testNoHttpUtils()
+    {
+        $container = new ContainerBuilder();
+        $container->setParameter('session.storage.options', array());
+
+        $pass = new AddSessionDomainConstraintPass();
+        $pass->process($container);
+    }
+
     private function createContainer($sessionStorageOptions)
     {
         $container = new ContainerBuilder();
