[!!!][SECURITY] Disallow session data transfer on frontend user logout 44/61144/2
authorOliver Hader <oliver@typo3.org>
Tue, 25 Jun 2019 06:41:55 +0000 (08:41 +0200)
committerOliver Hader <oliver.hader@typo3.org>
Tue, 25 Jun 2019 06:42:01 +0000 (08:42 +0200)
When frontend users logged out their session data (e.g. shopping cart)
was transfered into an anonymous session. This session could have been
reused by a different user working with the very same browser.

In order to enhance security aspects on this topic session data is
purged when an according frontend user is logging out. Since this might
be breaking for some scenarios a new feature toggle has been introduced
which allows to keep the previous behavior:

boolean 'security.frontend.keepSessionDataOnLogout'
in $GLOBALS['TYPO3_CONF_VARS']['SYS']['features']

Resolves: #88139
Releases: master, 9.5, 8.7
Security-Commit: 89c45f80388f24f08f827c474daa5ab8fda63da2
Security-Bulletin: TYPO3-CORE-SA-2019-018
Change-Id: I869f3bee7c6bf6e2ae51bcd86273b6abc15f09c5
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/61144
Tested-by: Oliver Hader <oliver.hader@typo3.org>
Reviewed-by: Oliver Hader <oliver.hader@typo3.org>
typo3/sysext/core/Classes/Authentication/AbstractUserAuthentication.php
typo3/sysext/core/Configuration/DefaultConfiguration.php
typo3/sysext/core/Configuration/DefaultConfigurationDescription.yaml
typo3/sysext/frontend/Classes/Authentication/FrontendUserAuthentication.php

index 5e5dbc4..7ccabd1 100644 (file)
@@ -1003,6 +1003,7 @@ abstract class AbstractUserAuthentication implements LoggerAwareInterface
         if ($this->id) {
             $this->getSessionBackend()->remove($this->id);
         }
+        $this->sessionData = [];
         $this->user = null;
     }
 
index 83eadbe..346f6e0 100644 (file)
@@ -74,6 +74,7 @@ return [
         'features' => [
             'redirects.hitCount' => false,
             'unifiedPageTranslationHandling' => false,
+            'security.frontend.keepSessionDataOnLogout' => false,
         ],
         'createGroup' => '',
         'sitename' => 'TYPO3',
index 7772a40..f65dfac 100644 (file)
@@ -215,6 +215,9 @@ SYS:
               redirects.hitCount:
                 type: bool
                 description: 'If on, and if extension "redirects" is loaded, each performed redirect is counted and last hit time is logged to the database.'
+              security.frontend.keepSessionDataOnLogout:
+                type: bool
+                description: 'If on, session data is kept in an anonymous session after frontend user logged out. As this is a potential security risk, it is recommended to disable this option if not specifically needed.'
         availablePasswordHashAlgorithms:
             type: array
             description: 'A list of available password hash mechanisms. Extensions may register additional mechanisms here. This is usually not extended in LocalConfiguration.php.'
index 93706c3..25a4cd9 100644 (file)
@@ -15,6 +15,7 @@ namespace TYPO3\CMS\Frontend\Authentication;
  */
 
 use TYPO3\CMS\Core\Authentication\AbstractUserAuthentication;
+use TYPO3\CMS\Core\Configuration\Features;
 use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Session\Backend\Exception\SessionNotFoundException;
 use TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser;
@@ -483,7 +484,8 @@ class FrontendUserAuthentication extends AbstractUserAuthentication
      * Thereby the current user (if any) is effectively logged out!
      * Additionally the cookie is removed, but only if there is no session data.
      * If session data exists, only the user information is removed and the session
-     * gets converted into an anonymous session.
+     * gets converted into an anonymous session if the feature toggle
+     * "security.frontend.keepSessionDataOnLogout" is set to true (default: false).
      */
     protected function performLogoff()
     {
@@ -496,12 +498,15 @@ class FrontendUserAuthentication extends AbstractUserAuthentication
             // Leave uncaught, will unset cookie later in this method
         }
 
-        if (!empty($sessionData)) {
+        $keepSessionDataOnLogout = GeneralUtility::makeInstance(Features::class)
+            ->isFeatureEnabled('security.frontend.keepSessionDataOnLogout');
+
+        if ($keepSessionDataOnLogout && !empty($sessionData)) {
             // Regenerate session as anonymous
             $this->regenerateSessionId($oldSession, true);
-        } else {
             $this->user = null;
-            $this->getSessionBackend()->remove($this->id);
+        } else {
+            parent::performLogoff();
             if ($this->isCookieSet()) {
                 $this->removeCookie($this->name);
             }