From ee661a686a7039ff99e3c5e038faa5e122dd4a4a Mon Sep 17 00:00:00 2001
From: Oliver Hader <oliver@typo3.org>
Date: Wed, 14 Dec 2022 14:27:58 +0100
Subject: [PATCH] [BUGFIX] Catch any transfer exception in HTTP host header
 check

ServerResponseCheck triggers a HTTP host header check which is
expected to fail. The more generic TransferException is used to
catch any other failed request, not only those with 4xx or 5xx
HTTP status codes. Besides that, TLS certificates shall not be
verified, and HTTP location redirects not be followed.

Resolves: #99368
Releases: main, 12.1, 11.5, 10.4
Change-Id: Id40457d4408c74d9229d4e6dcdedc0b69ffe9667
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/77153
Reviewed-by: Oliver Hader <oliver.hader@typo3.org>
Tested-by: Oliver Hader <oliver.hader@typo3.org>
Tested-by: core-ci <typo3@b13.com>
---
 .../ServerResponse/ServerResponseCheck.php         | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/typo3/sysext/install/Classes/SystemEnvironment/ServerResponse/ServerResponseCheck.php b/typo3/sysext/install/Classes/SystemEnvironment/ServerResponse/ServerResponseCheck.php
index 6aa216f55f78..d252a420a582 100644
--- a/typo3/sysext/install/Classes/SystemEnvironment/ServerResponse/ServerResponseCheck.php
+++ b/typo3/sysext/install/Classes/SystemEnvironment/ServerResponse/ServerResponseCheck.php
@@ -19,12 +19,14 @@ namespace TYPO3\CMS\Install\SystemEnvironment\ServerResponse;
 
 use GuzzleHttp\Client;
 use GuzzleHttp\Exception\BadResponseException;
+use GuzzleHttp\Exception\TransferException;
 
 use function GuzzleHttp\Promise\settle;
 
 use Psr\Http\Message\ResponseInterface;
 use TYPO3\CMS\Backend\Routing\UriBuilder;
 use TYPO3\CMS\Core\Crypto\Random;
+use TYPO3\CMS\Core\Http\Uri;
 use TYPO3\CMS\Core\Messaging\FlashMessage;
 use TYPO3\CMS\Core\Messaging\FlashMessageQueue;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
@@ -223,13 +225,21 @@ class ServerResponseCheck implements CheckInterface
         );
         try {
             $client = new Client(['timeout' => 10]);
-            $response = $client->request('GET', (string)$url, ['headers' => ['Host' => $randomHost]]);
-        } catch (BadResponseException $exception) {
+            $response = $client->request('GET', (string)$url, [
+                'headers' => ['Host' => $randomHost],
+                'allow_redirects' => false,
+                'verify' => false,
+            ]);
+        } catch (TransferException $exception) {
             // it is expected that the previous request fails
             return;
         }
         // in case we end up here, the server processed an HTTP request with invalid HTTP host header
         $messageParts = [];
+        $locationHeader = $response->getHeaderLine('location');
+        if (!empty($locationHeader) && (new Uri($locationHeader))->getHost() === $randomHost) {
+            $messageParts[] = sprintf('HTTP Location header contained unexpected "%s"', $randomHost);
+        }
         $data = json_decode((string)$response->getBody(), true);
         $serverHttpHost = $data['server.HTTP_HOST'] ?? null;
         $serverServerName = $data['server.SERVER_NAME'] ?? null;
-- 
GitLab