[BUGFIX] Streamline cookie options / remove cookieHttpOnly 08/50808/18
authorBenni Mack <benni@typo3.org>
Wed, 1 Feb 2017 05:51:17 +0000 (06:51 +0100)
committerBenni Mack <benni@typo3.org>
Wed, 1 Mar 2017 05:34:49 +0000 (06:34 +0100)
The TYPO3_CONF_VARS[SYS][cookieHttpOnly] option is removed
as all cookies set by the TYPO3 Core are HttpOnly by default
in order to avoid client side script access.

This option was previously turned on by default but configurable
as old browser did not support this option all the time (see
https://www.owasp.org/index.php/HttpOnly#Browsers_Supporting_HttpOnly
for more details).

The be_lastLoginProvider and workspaces cookies now
set the httpOnly flag properly as well.

Resolves: #78835
Releases: master
Change-Id: I12538508a6f97888d7ad0b2f5f028bcde2844d6d
Reviewed-on: https://review.typo3.org/50808
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Tested-by: Wouter Wolters <typo3@wouterwolters.nl>
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Tested-by: Markus Klein <markus.klein@typo3.org>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Benni Mack <benni@typo3.org>
Tested-by: Benni Mack <benni@typo3.org>
typo3/sysext/backend/Classes/Controller/LoginController.php
typo3/sysext/core/Classes/Authentication/AbstractUserAuthentication.php
typo3/sysext/core/Configuration/DefaultConfiguration.php
typo3/sysext/core/Configuration/DefaultConfigurationDescription.php
typo3/sysext/install/Classes/Service/SilentConfigurationUpgradeService.php
typo3/sysext/workspaces/Classes/Hook/PreviewHook.php

index 234ba47..0b40f23 100644 (file)
@@ -493,7 +493,9 @@ class LoginController
             reset($this->loginProviders);
             $loginProvider = key($this->loginProviders);
         }
-        setcookie('be_lastLoginProvider', $loginProvider, $GLOBALS['EXEC_TIME'] + 7776000); // 90 days
+        // Use the secure option when the current request is served by a secure connection:
+        $cookieSecure = (bool)$GLOBALS['TYPO3_CONF_VARS']['SYS']['cookieSecure'] && GeneralUtility::getIndpEnv('TYPO3_SSL');
+        setcookie('be_lastLoginProvider', $loginProvider, $GLOBALS['EXEC_TIME'] + 7776000, null, null, $cookieSecure, true); // 90 days
         return $loginProvider;
     }
 
index ac48e29..878337d 100644 (file)
@@ -486,11 +486,9 @@ abstract class AbstractUserAuthentication
             $cookieExpire = $isRefreshTimeBasedCookie ? $GLOBALS['EXEC_TIME'] + $this->lifetime : 0;
             // Use the secure option when the current request is served by a secure connection:
             $cookieSecure = (bool)$settings['cookieSecure'] && GeneralUtility::getIndpEnv('TYPO3_SSL');
-            // Deliver cookies only via HTTP and prevent possible XSS by JavaScript:
-            $cookieHttpOnly = (bool)$settings['cookieHttpOnly'];
             // Do not set cookie if cookieSecure is set to "1" (force HTTPS) and no secure channel is used:
             if ((int)$settings['cookieSecure'] !== 1 || GeneralUtility::getIndpEnv('TYPO3_SSL')) {
-                setcookie($this->name, $this->id, $cookieExpire, $cookiePath, $cookieDomain, $cookieSecure, $cookieHttpOnly);
+                setcookie($this->name, $this->id, $cookieExpire, $cookiePath, $cookieDomain, $cookieSecure, true);
                 $this->cookieWasSetOnCurrentRequest = true;
             } else {
                 throw new Exception('Cookie was not set since HTTPS was forced in $TYPO3_CONF_VARS[SYS][cookieSecure].', 1254325546);
index d809421..fa91687 100644 (file)
@@ -73,7 +73,6 @@ return [
         'encryptionKey' => '',
         'cookieDomain' => '',
         'cookieSecure' => 0,
-        'cookieHttpOnly' => true,
         'doNotCheckReferer' => false,
         'recursiveDomainSearch' => false,
         'trustedHostsPattern' => 'SERVER_NAME',
index ff898d9..4b4b4e2 100644 (file)
@@ -42,7 +42,6 @@ return [
         'encryptionKey' => 'This is a "salt" used for various kinds of encryption, CRC checksums and validations. You can enter any rubbish string here but try to keep it secret. You should notice that a change to this value might invalidate temporary information, URLs etc. At least, clear all cache if you change this so any such information can be rebuild with the new key.',
         'cookieDomain' => 'Restricts the domain name for FE and BE session cookies. When setting the value to ".domain.com" (replace domain.com with your domain!), login sessions will be shared across subdomains. Alternatively, if you have more than one domain with sub-domains, you can set the value to a regular expression to match against the domain of the HTTP request. The result of the match is used as the domain for the cookie. eg. /\\.(example1|example2)\\.com$/ or /\\.(example1\\.com)|(example2\\.net)$/. Separate domains for FE and BE can be set using <a href="#FE-cookieDomain">$TYPO3_CONF_VARS[\'FE\'][\'cookieDomain\']</a> and <a href="#BE-cookieDomain">$TYPO3_CONF_VARS[\'BE\'][\'cookieDomain\']</a> respectively.',
         'cookieSecure' => '<p>Integer (0, 1, 2): Indicates that the cookie should only be transmitted over a secure HTTPS connection from the client.</p><dl><dt>0</dt><dd>always send cookie</dd><dt>1 (force HTTPS)</dt><dd>the cookie will only be set if a secure (HTTPS) connection exists - use this in combination with lockSSL since otherwise the application will fail and throw an exception</dd><dt>2</dt><dd>the cookie will be set in each case, but uses the secure flag if a secure (HTTPS) connection exists.</dd></dl>',
-        'cookieHttpOnly' => 'Boolean: When enabled the cookie will be made accessible only through the HTTP protocol. This means that the cookie won\'t be accessible by scripting languages, such as JavaScript. This setting can effectively help to reduce identity theft through XSS attacks (although it is not supported by all browsers).',
         'doNotCheckReferer' => 'Boolean: If set, it\'s NOT checked numerous places that the referring host is the same as the current. This is an option you should set if you have problems with proxies not passing the HTTP_REFERER variable.',
         'recursiveDomainSearch' => 'Boolean: If set, the search for domain records will be done recursively by stripping parts of the hostname off until a matching domain record is found.',
         'trustedHostsPattern' => 'String: Regular expression pattern that matches all allowed hostnames (including their ports) of this TYPO3 installation, or the string "SERVER_NAME" (default). The default value <code>SERVER_NAME</code> checks if the HTTP Host header equals the SERVER_NAME and SERVER_PORT. This is secure in correctly configured hosting environments and does not need further configuration. If you cannot change your hosting environment, you can enter a regular expression here. Examples: <code>.*\\.domain\\.com</code> matches all hosts that end with <code>.domain.com</code> with all corresponding subdomains. <code>(.*\\.domain|.*\\.otherdomain)\\.com</code> matches all hostnames with subdomains from <code>.domain.com</code> and <code>.otherdomain.com</code>. Be aware that HTTP Host header may also contain a port. If your installation runs on a specific port, you need to explicitly allow this in your pattern, e.g. <code>www\\.domain\\.com:88</code> allows only <code>www.domain.com:88</code>, <strong>not</strong> <code>www.domain.com</code>. To disable this check completely (not recommended because it is <strong>insecure</strong>) you can use ".*" as pattern.',
index 3eea9f4..20591fd 100644 (file)
@@ -87,7 +87,9 @@ class SilentConfigurationUpgradeService
         'SYS/caching/cacheConfigurations/extbase_typo3dbbackend_queries',
         // #79513
         'FE/lockHashKeyWords',
-        'BE/lockHashKeyWords'
+        'BE/lockHashKeyWords',
+        // #78835
+        'SYS/cookieHttpOnly'
     ];
 
     public function __construct(ConfigurationManager $configurationManager = null)
index fd5f004..2756189 100644 (file)
@@ -302,7 +302,7 @@ class PreviewHook implements \TYPO3\CMS\Core\SingletonInterface
                         if (GeneralUtility::_GP($this->previewKey)) {
                             // Lifetime is 1 hour, does it matter much?
                             // Requires the user to click the link from their email again if it expires.
-                            setcookie($this->previewKey, GeneralUtility::_GP($this->previewKey), 0, GeneralUtility::getIndpEnv('TYPO3_SITE_PATH'));
+                            setcookie($this->previewKey, GeneralUtility::_GP($this->previewKey), 0, GeneralUtility::getIndpEnv('TYPO3_SITE_PATH'), null, null, true);
                         }
                         return $previewConfig;
                     } elseif (GeneralUtility::getIndpEnv('TYPO3_SITE_URL') . 'index.php?' . $this->previewKey . '=' . $inputCode === GeneralUtility::getIndpEnv('TYPO3_REQUEST_URL')) {