CVE-2021-46876 (published 2023-03-12T05:15Z)

An issue was discovered in eZ Publish Ibexa Kernel before 7.5.15.1. The /user/sessions endpoint can be abused to determine account existence.

CVSS v3 base score: 5.3, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N)

Weakness information:
cwe_id: NVD-CWE-noinfo
cwe_name: Insufficient Information
description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
extended_description: Insufficient Information

Fix information:
repo_url: https://github.com/ezsystems/ezpublish-kernel
commit_details: repo_url: https://github.com/ezsystems/ezpublish-kernel
author: Gunnstein Lye
author_date: 2021-03-09 13:43:42+01:00
msg: Merge pull request from GHSA-gmrf-99gw-vvwj

Co-authored-by: Bartek Wajda <bartlomiej.wajda@ibexa.co>
repository: repo_url: https://github.com/ezsystems/ezpublish-kernel
repo_name: ezsystems/ezpublish-kernel
description: Kernel (Repository, MVC layer, REST) for eZ Platform
repo_language: PHP
owner: ezsystems
file_changes: filename: default_settings.yml
change_type: ModificationType.MODIFY
diff: @@ -84,3 +84,7 @@ parameters:
         refreshSession:
             mediaType: 'UserSession'
             href: 'templateRouter.generate("ezpublish_rest_refreshSession", {sessionId: "{sessionId}"})'
+
+    # Boundary times in microseconds which the authentication check will be delayed by.
+    ezpublish_rest.authentication_min_delay_time: 30000
+    ezpublish_rest.authentication_max_delay_time: 500000
\ No newline at end of file

programming_language: CoffeeScript
filename: security.yml
change_type: ModificationType.MODIFY
diff: @@ -15,6 +15,8 @@ services:
             - "@ezpublish.config.resolver"
             - "@session.storage"
             - "@?logger"
+            - "%ezpublish_rest.authentication_min_delay_time%"
+            - "%ezpublish_rest.authentication_max_delay_time%"
         abstract: true
 
     ezpublish_rest.security.authentication.logout_handler:

programming_language: Ruby
filename: SessionController.php
change_type: ModificationType.MODIFY
diff: @@ -59,7 +59,7 @@ class SessionController extends Controller
             )
         );
         $request->attributes->set('username', $sessionInput->login);
-        $request->attributes->set('password', $sessionInput->password);
+        $request->attributes->set('password', (string) $sessionInput->password);
 
         try {
             $session = $request->getSession();

programming_language: PHP
filename: RestAuthenticator.php
change_type: ModificationType.MODIFY
diff: @@ -36,6 +36,10 @@ use Symfony\Component\Security\Http\SecurityEvents;
  */
 class RestAuthenticator implements ListenerInterface, AuthenticatorInterface
 {
+    const DEFAULT_MIN_SLEEP_VALUE = 30000;
+
+    const DEFAULT_MAX_SLEEP_VALUE = 500000;
+
     /** @var \Psr\Log\LoggerInterface */
     private $logger;
 
@@ -59,6 +63,16 @@ class RestAuthenticator implements ListenerInterface, AuthenticatorInterface
     /** @var \Symfony\Component\Security\Http\Logout\LogoutHandlerInterface[] */
     private $logoutHandlers = [];
 
+    /**
+     * @var int|null
+     */
+    private $minSleepTime;
+
+    /**
+     * @var int|null
+     */
+    private $maxSleepTime;
+
     public function __construct(
         TokenStorageInterface $tokenStorage,
         AuthenticationManagerInterface $authenticationManager,
@@ -66,7 +80,9 @@ class RestAuthenticator implements ListenerInterface, AuthenticatorInterface
         EventDispatcherInterface $dispatcher,
         ConfigResolverInterface $configResolver,
         SessionStorageInterface $sessionStorage,
-        LoggerInterface $logger = null
+        LoggerInterface $logger = null,
+        $minSleepTime = self::DEFAULT_MIN_SLEEP_VALUE,
+        $maxSleepTime = self::DEFAULT_MAX_SLEEP_VALUE
     ) {
         $this->tokenStorage = $tokenStorage;
         $this->authenticationManager = $authenticationManager;
@@ -75,6 +91,8 @@ class RestAuthenticator implements ListenerInterface, AuthenticatorInterface
         $this->configResolver = $configResolver;
         $this->sessionStorage = $sessionStorage;
         $this->logger = $logger;
+        $this->minSleepTime = !is_int($minSleepTime) ? self::DEFAULT_MIN_SLEEP_VALUE : $minSleepTime;
+        $this->maxSleepTime = !is_int($maxSleepTime) ? self::DEFAULT_MAX_SLEEP_VALUE : $maxSleepTime;
     }
 
     /**
@@ -89,6 +107,8 @@ class RestAuthenticator implements ListenerInterface, AuthenticatorInterface
 
     public function authenticate(Request $request)
     {
+        usleep(random_int($this->minSleepTime, $this->maxSleepTime));
+
         // If a token already exists and username is the same as the one we request authentication for,
         // then return it and mark it as coming from session.
         $previousToken = $this->tokenStorage->getToken();

programming_language: PHP