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