From 78a259ef3b0451f36bd323a20da15a06d9ad683d Mon Sep 17 00:00:00 2001 From: Nicolas Thumann Date: Wed, 10 May 2023 08:26:08 +0200 Subject: [PATCH] Fix IPv6 address in cookie domain (#1137) * Implement getCookieHost to extract cookie host from HTTP_HOST --- lib/Froxlor/UI/Panel/UI.php | 26 ++++++++++++++++++++++++-- lib/init.php | 3 +-- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/lib/Froxlor/UI/Panel/UI.php b/lib/Froxlor/UI/Panel/UI.php index 6a2c100e..7440d70b 100644 --- a/lib/Froxlor/UI/Panel/UI.php +++ b/lib/Froxlor/UI/Panel/UI.php @@ -87,16 +87,38 @@ class UI return $isHttps && (strcasecmp('on', $isHttps) == 0 || strcasecmp('https', $isHttps) == 0); } + + /** + * Extract the cookie host from HTTP_HOST, stripping the port. + */ + public static function getCookieHost(): ?string + { + if (empty($_SERVER['HTTP_HOST'])) + return null; + + $colonPosition = strrpos($_SERVER['HTTP_HOST'], ':'); + // There's no port in the host + if ($colonPosition === false) + return $_SERVER['HTTP_HOST']; + + $closingSquareBracketPosition = strrpos($_SERVER['HTTP_HOST'], ']'); + // The host is an IPv4 address or hostname with port + if ($closingSquareBracketPosition === false) + return substr($_SERVER['HTTP_HOST'], 0, $colonPosition); + + // The host is an IPv6 address with port + return substr($_SERVER['HTTP_HOST'], 0, $closingSquareBracketPosition + 1); + } + /** * send various security related headers */ public static function sendHeaders() { - $cookie_host = empty($_SERVER['HTTP_HOST']) ? null : explode (':', $_SERVER['HTTP_HOST'])[0]; session_set_cookie_params([ 'lifetime' => self::$install_mode ? 7200 : 600, // will be renewed based on settings in lib/init.php 'path' => '/', - 'domain' => $cookie_host, + 'domain' => self::getCookieHost(), 'secure' => self::requestIsHttps(), 'httponly' => true, 'samesite' => 'Strict' diff --git a/lib/init.php b/lib/init.php index 2b5909bc..254d0726 100644 --- a/lib/init.php +++ b/lib/init.php @@ -331,11 +331,10 @@ if (CurrentUser::hasSession()) { } } // update cookie lifetime - $cookie_host = empty($_SERVER['HTTP_HOST']) ? null : explode (':', $_SERVER['HTTP_HOST'])[0]; $cookie_params = [ 'expires' => time() + Settings::Get('session.sessiontimeout'), 'path' => '/', - 'domain' => $cookie_host, + 'domain' => UI::getCookieHost(), 'secure' => UI::requestIsHttps(), 'httponly' => true, 'samesite' => 'Strict'