From 7d5986a30d88e8dfb380b24383845b8ff6b4e9af Mon Sep 17 00:00:00 2001
From: Torben Hansen <derhansen@gmail.com>
Date: Sat, 25 Feb 2023 14:29:20 +0100
Subject: [PATCH] [TASK] Add HTTP security headers for backend by default

The TYPO3 backend currently adds a `X-Frame-Options: SAMEORIGIN`
HTTP security header to prevent clickjacking attacks. It is however
possible to use several other HTTP security headers for TYPO3 backend
requests as well.

This change adds the following HTTP security headers by default
for TYPO3 backend requests:

* `Strict-Transport-Security: max-age=31536000` (only if
  :php:`$GLOBALS[TYPO3_CONF_VARS][BE][lockSSL]` is active)
* `X-Content-Type-Options: nosniff`
* `Referrer-Policy: strict-origin-when-cross-origin`

Resolves: #100032
Releases: main
Signed-off-by: Torben Hansen <derhansen@gmail.com>
Change-Id: Icee3ecb92659e665440ff7a1505efa5f7033d6b5
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/77946
Tested-by: core-ci <typo3@b13.com>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Georg Ringer <georg.ringer@gmail.com>
Reviewed-by: Oliver Hader <oliver.hader@typo3.org>
Tested-by: Georg Ringer <georg.ringer@gmail.com>
Reviewed-by: Oliver Klee <typo3-coding@oliverklee.de>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
---
 .../Middleware/AdditionalResponseHeaders.php  |  6 ++++
 .../Configuration/DefaultConfiguration.php    |  3 ++
 ...HTTPSecurityHeadersForBackendByDefault.rst | 33 +++++++++++++++++++
 3 files changed, 42 insertions(+)
 create mode 100644 typo3/sysext/core/Documentation/Changelog/12.3/Important-100032-AddHTTPSecurityHeadersForBackendByDefault.rst

diff --git a/typo3/sysext/backend/Classes/Middleware/AdditionalResponseHeaders.php b/typo3/sysext/backend/Classes/Middleware/AdditionalResponseHeaders.php
index dbc2fa5693c1..156d9d900d91 100644
--- a/typo3/sysext/backend/Classes/Middleware/AdditionalResponseHeaders.php
+++ b/typo3/sysext/backend/Classes/Middleware/AdditionalResponseHeaders.php
@@ -35,6 +35,12 @@ class AdditionalResponseHeaders implements MiddlewareInterface
     public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
     {
         $response = $handler->handle($request);
+
+        // Remove HSTS header, if [BE][lockSSL] is not configured to use SSL
+        if ((bool)$GLOBALS['TYPO3_CONF_VARS']['BE']['lockSSL'] === false) {
+            unset($GLOBALS['TYPO3_CONF_VARS']['BE']['HTTP']['Response']['Headers']['strictTransportSecurity']);
+        }
+
         foreach ($GLOBALS['TYPO3_CONF_VARS']['BE']['HTTP']['Response']['Headers'] ?? [] as $header) {
             [$headerName, $value] = explode(':', $header, 2);
             $response = $response->withAddedHeader($headerName, trim($value));
diff --git a/typo3/sysext/core/Configuration/DefaultConfiguration.php b/typo3/sysext/core/Configuration/DefaultConfiguration.php
index 94d9993c2b6b..e73ed8e7b6f2 100644
--- a/typo3/sysext/core/Configuration/DefaultConfiguration.php
+++ b/typo3/sysext/core/Configuration/DefaultConfiguration.php
@@ -1331,6 +1331,9 @@ return [
             'Response' => [
                 'Headers' => [
                     'clickJackingProtection' => 'X-Frame-Options: SAMEORIGIN',
+                    'strictTransportSecurity' => 'Strict-Transport-Security: max-age=31536000',
+                    'avoidMimeTypeSniffing' => 'X-Content-Type-Options: nosniff',
+                    'referrerPolicy' => 'Referrer-Policy: strict-origin-when-cross-origin',
                     // 'csp-report' => "Content-Security-Policy-Report-Only: default-src 'self'; style-src-attr 'unsafe-inline'; img-src 'self' data:",
                     // @todo laterâ„¢: muuri.js is creating workers from `blob:` (?!?), <style> tags declare inline styles (?!?)
                     // 'csp-report' => "Content-Security-Policy-Report-Only: default-src 'self'; style-src-attr 'unsafe-inline'; style-src-elem 'self' 'unsafe-inline'; img-src 'self' data:; worker-src 'self' blob:;",
diff --git a/typo3/sysext/core/Documentation/Changelog/12.3/Important-100032-AddHTTPSecurityHeadersForBackendByDefault.rst b/typo3/sysext/core/Documentation/Changelog/12.3/Important-100032-AddHTTPSecurityHeadersForBackendByDefault.rst
new file mode 100644
index 000000000000..b8fbb55701b3
--- /dev/null
+++ b/typo3/sysext/core/Documentation/Changelog/12.3/Important-100032-AddHTTPSecurityHeadersForBackendByDefault.rst
@@ -0,0 +1,33 @@
+.. include:: /Includes.rst.txt
+
+.. _important-100032-1677331239:
+
+=====================================================================
+Important: #100032 - Add HTTP security headers for backend by default
+=====================================================================
+
+See :issue:`100032`
+
+Description
+===========
+
+The following HTTP security headers are now added by default for the TYPO3
+backend:
+
+* `Strict-Transport-Security: max-age=31536000` (only if
+  :php:`$GLOBALS[TYPO3_CONF_VARS][BE][lockSSL]` is active)
+* `X-Content-Type-Options: nosniff`
+* `Referrer-Policy: strict-origin-when-cross-origin`
+
+The default HTTP security headers are globally configured in
+`$GLOBALS['TYPO3_CONF_VARS']['BE']['HTTP']['Response']['Headers']` and include
+a unique array key, so it is possible to individually unset/remove unwanted
+headers.
+
+.. important::
+
+   TYPO3 websites, which already use custom HTTP headers for the TYPO3 backend,
+   must ensure that individual HTTP security headers are not sent multiple
+   times.
+
+.. index:: Backend, ext:backend
-- 
GitLab