Not clear CSRF tokens upon login…

Summary

  • CVE ID: CVE-2023-25170
  • Published at: 2023-03-13
  • Advisory source: PrestaShop
  • Platform: PrestaShop
  • Product: PrestaShop
  • Impacted release: >=1.7.0.0, 8.0.1
  • Product author: PrestaShop
  • Weakness: CWE-352
  • Severity: moderate (5.0)

Description

When authenticating users PrestaShop preserves session attributes because this does not clear CSRF tokens upon login.

CVSS base metrics

  • Attack vector: network
  • Attack complexity: high
  • Privilege required: none
  • User interaction: required
  • Scope: unchanged
  • Confidentiality: low
  • Integrity: low
  • Availability: low

Vector string: CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:L

Possible malicious usage

This issue might enables same-site attackers to bypass the CSRF protection mechanism by performing an attack similar to a session-fixation.

Patch

This is generated between 8.0.1 and 8.0.2.

diff --git a/classes/Employee.php b/classes/Employee.php
index 556f63401433..8116da0aeffe 100644
--- a/classes/Employee.php
+++ b/classes/Employee.php
@@ -25,7 +25,9 @@
  */
 use PrestaShop\PrestaShop\Adapter\CoreException;
 use PrestaShop\PrestaShop\Adapter\ServiceLocator;
+use PrestaShop\PrestaShop\Adapter\SymfonyContainer;
 use PrestaShop\PrestaShop\Core\Crypto\Hashing;
+use PrestaShopBundle\Security\Admin\SessionRenewer;
 
 /**
  * Class EmployeeCore.
@@ -488,6 +490,11 @@ public function logout()
             Context::getContext()->cookie->write();
         }
 
+        $sfContainer = SymfonyContainer::getInstance();
+        if ($sfContainer !== null) {
+            $sfContainer->get(SessionRenewer::class)->renew();
+        }
+
         $this->id = null;
     }
 
diff --git a/controllers/admin/AdminLoginController.php b/controllers/admin/AdminLoginController.php
index 8b30e26173b7..9d49cf6fe2b2 100644
--- a/controllers/admin/AdminLoginController.php
+++ b/controllers/admin/AdminLoginController.php
@@ -24,6 +24,7 @@
  * @license   https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
  */
 use PrestaShop\PrestaShop\Core\Util\InternationalizedDomainNameConverter;
+use PrestaShopBundle\Security\Admin\SessionRenewer;
 use Symfony\Component\HttpFoundation\IpUtils;
 
 class AdminLoginControllerCore extends AdminController
@@ -269,6 +270,8 @@ public function processLogin()
                     $url = $this->context->link->getAdminLink($tab->class_name);
                 }
 
+                $this->get(SessionRenewer::class)->renew();
+
                 Hook::exec(
                     'actionAdminLoginControllerLoginAfter',
                     [
diff --git a/src/PrestaShopBundle/Resources/config/services/bundle/services.yml b/src/PrestaShopBundle/Resources/config/services/bundle/services.yml
index bf57009c5810..0679d4ba8547 100644
--- a/src/PrestaShopBundle/Resources/config/services/bundle/services.yml
+++ b/src/PrestaShopBundle/Resources/config/services/bundle/services.yml
@@ -95,3 +95,8 @@ services:
   PrestaShopBundle\DependencyInjection\RuntimeConstEnvVarProcessor:
     public: false
     tags: [ 'container.env_var_processor' ]
+
+  PrestaShopBundle\Security\Admin\SessionRenewer:
+    arguments:
+      $storage: "@security.csrf.token_storage"
+    autowire: true
diff --git a/src/PrestaShopBundle/Security/Admin/SessionRenewer.php b/src/PrestaShopBundle/Security/Admin/SessionRenewer.php
new file mode 100644
index 000000000000..28de6d63f213
--- /dev/null
+++ b/src/PrestaShopBundle/Security/Admin/SessionRenewer.php
@@ -0,0 +1,76 @@
+<?php
+/**
+ * Copyright since 2007 PrestaShop SA and Contributors
+ * PrestaShop is an International Registered Trademark & Property of PrestaShop SA
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.md.
+ * It is also available through the world-wide-web at this URL:
+ * https://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@prestashop.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
+ * versions in the future. If you wish to customize PrestaShop for your
+ * needs please refer to https://devdocs.prestashop.com/ for more information.
+ *
+ * @author    PrestaShop SA and Contributors <contact@prestashop.com>
+ * @copyright Since 2007 PrestaShop SA and Contributors
+ * @license   https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ */
+
+declare(strict_types=1);
+
+namespace PrestaShopBundle\Security\Admin;
+
+use Symfony\Component\HttpFoundation\Session\SessionInterface;
+use Symfony\Component\Security\Csrf\TokenStorage\ClearableTokenStorageInterface;
+
+/**
+ * Because PS don't use Symfony login feature, we use this service to fix CVE-2022-24895. This class will be deprecated
+ * when BO login/logout will use full Symfony process
+ *
+ * @internal
+ */
+final class SessionRenewer
+{
+    /**
+     * @var ClearableTokenStorageInterface
+     */
+    private $storage;
+
+    /**
+     * @var SessionInterface
+     */
+    private $session;
+
+    /**
+     * @param ClearableTokenStorageInterface $storage
+     * @param SessionInterface $session
+     */
+    public function __construct(ClearableTokenStorageInterface $storage, SessionInterface $session)
+    {
+        $this->storage = $storage;
+        $this->session = $session;
+    }
+
+    /**
+     * Change PHPSESSID and clear tokens registered in session
+     *
+     * @return void
+     */
+    public function renew(): void
+    {
+        if (!$this->session->isStarted()) {
+            $this->session->start();
+        }
+
+        $this->session->migrate(true);
+        $this->storage->clear();
+    }
+}

Other recommendations

  • Upgrade PrestaShop beyong 8.0.2