[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#988457: unblock: symfony/4.4.19+dfsg-2



Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock
X-Debbugs-Cc: team@security.debian.org

Please unblock package symfony

I’ve uploaded a targeted fix for a user enumeration [CVE-2021-21424].
Since symfony is a key package, it won’t migrate on its own despite the
autopkgtests. I also fixed two typos in the packages description.

[ Checklist ]
  [x] all changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in testing

Regards

unblock symfony/4.4.19+dfsg-2
diff --git a/debian/changelog b/debian/changelog
index 342ccafaef..db978be8b7 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+symfony (4.4.19+dfsg-2) unstable; urgency=medium
+
+  * Prevent user enumeration via response content [CVE-2021-21424]
+  * typo fix: var-exporter and phpunit-bridge description
+
+ -- David Prévot <taffit@debian.org>  Thu, 13 May 2021 05:33:42 -0400
+
 symfony (4.4.19+dfsg-1) unstable; urgency=medium
 
   [ Fabien Potencier ]
diff --git a/debian/control b/debian/control
index c5df2fc3cc..d19d505d56 100644
--- a/debian/control
+++ b/debian/control
@@ -765,7 +765,7 @@ Breaks: ${phpcomposer:Debian-conflict}, ${phpcomposer:Debian-replace}
 Provides: ${phpcomposer:Debian-provide}
 Homepage: https://symfony.com/doc/4.4/components/var_exporter.html
 Description: export serializable PHP data structure to plain PHP code
- The Symfony VarExporter allows one to exporte any serializable PHP data
+ The Symfony VarExporter allows one to export any serializable PHP data
  structure to plain PHP code.
  .
  Symfony is a PHP framework, a set of tools and a development methodology.
@@ -864,7 +864,7 @@ Breaks: ${phpcomposer:Debian-replace}
 Provides: ${phpcomposer:Debian-provide}
 Homepage: https://symfony.com/doc/4.4/components/phpunit_bridge.html
 Description: integration for PHPUnit with Symfony Components
- The Symfony PHPUnit Bridge utilities for PHPUnit, especially user
+ The Symfony PHPUnit Bridge provides utilities for PHPUnit, especially user
  deprecation notices management.
  .
  PHPUnit is a unit testing suite for the PHP language, modelled on the
diff --git a/debian/patches/Merge-branch-3.4-into-4.4.patch b/debian/patches/Merge-branch-3.4-into-4.4.patch
new file mode 100644
index 0000000000..02d7a16017
--- /dev/null
+++ b/debian/patches/Merge-branch-3.4-into-4.4.patch
@@ -0,0 +1,210 @@
+From: Nicolas Grekas <nicolas.grekas@gmail.com>
+Date: Wed, 12 May 2021 14:42:28 +0200
+Subject: Merge branch '3.4' into 4.4
+
+* 3.4:
+  [Security][Guard] Prevent user enumeration via response content
+
+Origin: upstream, https://github.com/symfony/symfony/commit/f012eee6c6034a94566dff596fe4e16dfc5d9c1f https://github.com/symfony/symfony/commit/d5c0fbac859374754ee14b524a1e157534ee07de
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2021-21424
+---
+ .../SecurityBundle/Resources/config/guard.xml      |  3 +-
+ .../Provider/UserAuthenticationProvider.php        |  3 +-
+ .../Provider/UserAuthenticationProviderTest.php    |  6 +--
+ .../Guard/Firewall/GuardAuthenticationListener.php | 13 +++++-
+ .../Firewall/GuardAuthenticationListenerTest.php   | 51 ++++++++++++++++++++++
+ 5 files changed, 70 insertions(+), 6 deletions(-)
+
+diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/guard.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/guard.xml
+index 7b17aff..2fae143 100644
+--- a/src/Symfony/Bundle/SecurityBundle/Resources/config/guard.xml
++++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/guard.xml
+@@ -17,7 +17,7 @@
+                 <argument type="service" id="security.authentication.session_strategy" />
+             </call>
+         </service>
+-        
++
+         <service id="Symfony\Component\Security\Guard\GuardAuthenticatorHandler" alias="security.authentication.guard_handler" />
+ 
+         <!-- See GuardAuthenticationFactory -->
+@@ -42,6 +42,7 @@
+             <argument /> <!-- Provider-shared Key -->
+             <argument /> <!-- Authenticator -->
+             <argument type="service" id="logger" on-invalid="null" />
++            <argument>%security.authentication.hide_user_not_found%</argument>
+         </service>
+     </services>
+ </container>
+diff --git a/src/Symfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.php b/src/Symfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.php
+index 9912259..86ef627 100644
+--- a/src/Symfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.php
++++ b/src/Symfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.php
+@@ -14,6 +14,7 @@ namespace Symfony\Component\Security\Core\Authentication\Provider;
+ use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
+ use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
+ use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
++use Symfony\Component\Security\Core\Exception\AccountStatusException;
+ use Symfony\Component\Security\Core\Exception\AuthenticationException;
+ use Symfony\Component\Security\Core\Exception\AuthenticationServiceException;
+ use Symfony\Component\Security\Core\Exception\BadCredentialsException;
+@@ -80,7 +81,7 @@ abstract class UserAuthenticationProvider implements AuthenticationProviderInter
+             $this->userChecker->checkPreAuth($user);
+             $this->checkAuthentication($user, $token);
+             $this->userChecker->checkPostAuth($user);
+-        } catch (BadCredentialsException $e) {
++        } catch (AccountStatusException $e) {
+             if ($this->hideUserNotFoundExceptions) {
+                 throw new BadCredentialsException('Bad credentials.', 0, $e);
+             }
+diff --git a/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/UserAuthenticationProviderTest.php b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/UserAuthenticationProviderTest.php
+index 1ce9b79..66c3697 100644
+--- a/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/UserAuthenticationProviderTest.php
++++ b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/UserAuthenticationProviderTest.php
+@@ -83,7 +83,7 @@ class UserAuthenticationProviderTest extends TestCase
+ 
+     public function testAuthenticateWhenPreChecksFails()
+     {
+-        $this->expectException(CredentialsExpiredException::class);
++        $this->expectException(BadCredentialsException::class);
+         $userChecker = $this->createMock(UserCheckerInterface::class);
+         $userChecker->expects($this->once())
+                     ->method('checkPreAuth')
+@@ -101,7 +101,7 @@ class UserAuthenticationProviderTest extends TestCase
+ 
+     public function testAuthenticateWhenPostChecksFails()
+     {
+-        $this->expectException(AccountExpiredException::class);
++        $this->expectException(BadCredentialsException::class);
+         $userChecker = $this->createMock(UserCheckerInterface::class);
+         $userChecker->expects($this->once())
+                     ->method('checkPostAuth')
+@@ -128,7 +128,7 @@ class UserAuthenticationProviderTest extends TestCase
+         ;
+         $provider->expects($this->once())
+                  ->method('checkAuthentication')
+-                 ->willThrowException(new BadCredentialsException())
++                 ->willThrowException(new CredentialsExpiredException())
+         ;
+ 
+         $provider->authenticate($this->getSupportedToken());
+diff --git a/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php b/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php
+index 45f20c3..4375fac 100644
+--- a/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php
++++ b/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php
+@@ -17,7 +17,10 @@ use Symfony\Component\HttpFoundation\Response;
+ use Symfony\Component\HttpKernel\Event\RequestEvent;
+ use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
+ use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
++use Symfony\Component\Security\Core\Exception\AccountStatusException;
+ use Symfony\Component\Security\Core\Exception\AuthenticationException;
++use Symfony\Component\Security\Core\Exception\BadCredentialsException;
++use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
+ use Symfony\Component\Security\Guard\AuthenticatorInterface;
+ use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;
+ use Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken;
+@@ -44,12 +47,13 @@ class GuardAuthenticationListener extends AbstractListener implements ListenerIn
+     private $guardAuthenticators;
+     private $logger;
+     private $rememberMeServices;
++    private $hideUserNotFoundExceptions;
+ 
+     /**
+      * @param string                            $providerKey         The provider (i.e. firewall) key
+      * @param iterable|AuthenticatorInterface[] $guardAuthenticators The authenticators, with keys that match what's passed to GuardAuthenticationProvider
+      */
+-    public function __construct(GuardAuthenticatorHandler $guardHandler, AuthenticationManagerInterface $authenticationManager, string $providerKey, iterable $guardAuthenticators, LoggerInterface $logger = null)
++    public function __construct(GuardAuthenticatorHandler $guardHandler, AuthenticationManagerInterface $authenticationManager, string $providerKey, iterable $guardAuthenticators, LoggerInterface $logger = null, bool $hideUserNotFoundExceptions = true)
+     {
+         if (empty($providerKey)) {
+             throw new \InvalidArgumentException('$providerKey must not be empty.');
+@@ -60,6 +64,7 @@ class GuardAuthenticationListener extends AbstractListener implements ListenerIn
+         $this->providerKey = $providerKey;
+         $this->guardAuthenticators = $guardAuthenticators;
+         $this->logger = $logger;
++        $this->hideUserNotFoundExceptions = $hideUserNotFoundExceptions;
+     }
+ 
+     /**
+@@ -164,6 +169,12 @@ class GuardAuthenticationListener extends AbstractListener implements ListenerIn
+                 $this->logger->info('Guard authentication failed.', ['exception' => $e, 'authenticator' => \get_class($guardAuthenticator)]);
+             }
+ 
++            // Avoid leaking error details in case of invalid user (e.g. user not found or invalid account status)
++            // to prevent user enumeration via response content
++            if ($this->hideUserNotFoundExceptions && ($e instanceof UsernameNotFoundException || $e instanceof AccountStatusException)) {
++                $e = new BadCredentialsException('Bad credentials.', 0, $e);
++            }
++
+             $response = $this->guardHandler->handleAuthenticationFailure($e, $request, $guardAuthenticator, $this->providerKey);
+ 
+             if ($response instanceof Response) {
+diff --git a/src/Symfony/Component/Security/Guard/Tests/Firewall/GuardAuthenticationListenerTest.php b/src/Symfony/Component/Security/Guard/Tests/Firewall/GuardAuthenticationListenerTest.php
+index 7d1c8e7..512bf31 100644
+--- a/src/Symfony/Component/Security/Guard/Tests/Firewall/GuardAuthenticationListenerTest.php
++++ b/src/Symfony/Component/Security/Guard/Tests/Firewall/GuardAuthenticationListenerTest.php
+@@ -19,6 +19,9 @@ use Symfony\Component\HttpKernel\Event\RequestEvent;
+ use Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager;
+ use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
+ use Symfony\Component\Security\Core\Exception\AuthenticationException;
++use Symfony\Component\Security\Core\Exception\BadCredentialsException;
++use Symfony\Component\Security\Core\Exception\LockedException;
++use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
+ use Symfony\Component\Security\Guard\AuthenticatorInterface;
+ use Symfony\Component\Security\Guard\Firewall\GuardAuthenticationListener;
+ use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;
+@@ -211,6 +214,54 @@ class GuardAuthenticationListenerTest extends TestCase
+         $listener($this->event);
+     }
+ 
++    /**
++     * @dataProvider exceptionsToHide
++     */
++    public function testHandleHidesInvalidUserExceptions(AuthenticationException $exceptionToHide)
++    {
++        $authenticator = $this->createMock(AuthenticatorInterface::class);
++        $providerKey = 'my_firewall2';
++
++        $authenticator
++            ->expects($this->once())
++            ->method('supports')
++            ->willReturn(true);
++        $authenticator
++            ->expects($this->once())
++            ->method('getCredentials')
++            ->willReturn(['username' => 'robin', 'password' => 'hood']);
++
++        $this->authenticationManager
++            ->expects($this->once())
++            ->method('authenticate')
++            ->willThrowException($exceptionToHide);
++
++        $this->guardAuthenticatorHandler
++            ->expects($this->once())
++            ->method('handleAuthenticationFailure')
++            ->with($this->callback(function ($e) use ($exceptionToHide) {
++                return $e instanceof BadCredentialsException && $exceptionToHide === $e->getPrevious();
++            }), $this->request, $authenticator, $providerKey);
++
++        $listener = new GuardAuthenticationListener(
++            $this->guardAuthenticatorHandler,
++            $this->authenticationManager,
++            $providerKey,
++            [$authenticator],
++            $this->logger
++        );
++
++        $listener($this->event);
++    }
++
++    public function exceptionsToHide()
++    {
++        return [
++            [new UsernameNotFoundException()],
++            [new LockedException()],
++        ];
++    }
++
+     public function testSupportsReturnFalseSkipAuth()
+     {
+         $authenticator = $this->createMock(AuthenticatorInterface::class);
diff --git a/debian/patches/series b/debian/patches/series
index 7272d07179..de2ecb771a 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -18,3 +18,4 @@ ErrorHandler-Drop-currently-broken-assertions.patch
 Config-Drop-currently-broken-assertions.patch
 Workaround-failing-tests-with-php7.4.patch
 HttpClient-group-network-for-test-failing-without-vulcain.patch
+Merge-branch-3.4-into-4.4.patch

Attachment: signature.asc
Description: PGP signature


Reply to: