Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Host detection: use HTTP_HOST as default, but provide a setting to use SERVER_NAME instead #16899

Merged
merged 4 commits into from
Dec 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ These are only recommendations (because we will keep backward compatibility for

* When embedding reports (widgets) into a different site, it is no longer possible to use authentication tokens of users with at least write access, unless the `[General] enable_framed_allow_write_admin_token_auth` is set. This means if you currently rely on this functionality, you will need to update your matomo config when updating to Matomo 4. Alternatively, create a user with `view` access and use the token of this user to embed the report.
* The log importer in `misc/log-analytics` now supports Python 3 (3.5, 3.6, 3.7 or 3.8), it will no longer run with Python 2. If you have any automated scripts that run the importer, you will have to change them to use the Python 3 executable instead.
* Matomo now uses the SERVER_NAME for host validation and no longer the HOST header. If you're running Matomo behind a load balancer or a proxy you need to ensure that SERVER_NAME is set correctly.
* Deprecated `piwik` font was removed. Use `matomo` font instead
* The JavaScript AjaxHelper does not longer support synchronous requests. All requests will be sent async instead.
* The console option `--piwik-domain` has been removed. Use `--matomo-domain` instead
Expand All @@ -159,6 +158,11 @@ These are only recommendations (because we will keep backward compatibility for
* The Method `\DI\link()` has been removed. Use `\DI\get()` instead.
* Defining global observer functions in config now requires the functions to be wrapped in `\DI\value()`, unless they are a factory.

### New config.ini.php settings

* `host_validation_use_server_name = 0`, if set to 1, Matomo will prefer using SERVER_NAME variable over HTTP_HOST. This can add an additional layer of security, as SERVER_NAME can't be manipulated by sending custom host headers when configured correctly.


## Matomo 3.14.0

### New API
Expand Down
4 changes: 4 additions & 0 deletions config/global.ini.php
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,10 @@
; it is recommended for security reasons to always use Matomo over https
force_ssl = 0

; If set to 1 Matomo will prefer using SERVER_NAME variable over HTTP_HOST.
; This can add an additional layer of security as SERVER_NAME can not be manipulated by sending custom host headers when configure correctly.
host_validation_use_server_name = 0

; Session garbage collection on (as on some operating systems, i.e. Debian, it may be off by default)
session_gc_probability = 1

Expand Down
7 changes: 1 addition & 6 deletions core/Plugin/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -821,12 +821,7 @@ public static function setHostValidationVariablesView($view)
// invalid host, so display warning to user
$validHosts = Url::getTrustedHostsFromConfig();
$validHost = $validHosts[0];

if (!empty($_SERVER['SERVER_NAME'])) {
$invalidHost = Common::sanitizeInputValue(Url::getHostFromServerNameVar());
} else {
$invalidHost = Common::sanitizeInputValue($_SERVER['HTTP_HOST']);
}
$invalidHost = Common::sanitizeInputValue(Url::getHost(false));

$emailSubject = rawurlencode(Piwik::translate('CoreHome_InjectedHostEmailSubject', $invalidHost));
$emailBody = rawurlencode(Piwik::translate('CoreHome_InjectedHostEmailBody'));
Expand Down
43 changes: 25 additions & 18 deletions core/Url.php
Original file line number Diff line number Diff line change
Expand Up @@ -208,14 +208,10 @@ public static function isValidHost($host = false)
}

if ($host === false) {
$host = self::getHostFromServerNameVar();
$host = self::getHostFromServerVariable();
if (empty($host)) {
// fallback to old behaviour
$host = @$_SERVER['HTTP_HOST'];
if (empty($host)) {
// if no current host, assume valid
return true;
}
// if no current host, assume valid
return true;
}
}

Expand Down Expand Up @@ -301,18 +297,9 @@ protected static function saveHostsnameInConfig($host, $domain, $key)
*/
public static function getHost($checkIfTrusted = true)
{
if (strlen($host = self::getHostFromServerNameVar())) {
// if server_name is set we don't want to look at HTTP_HOST
$host = self::getHostFromServerVariable();

if (!$checkIfTrusted || self::isValidHost($host)) {
return $host;
}
} elseif (isset($_SERVER['HTTP_HOST'])
&& strlen($host = $_SERVER['HTTP_HOST'])
&& (!$checkIfTrusted
|| self::isValidHost($host))
) {
// HTTP/1.1 request
if (strlen($host) && (!$checkIfTrusted || self::isValidHost($host))) {
return $host;
}

Expand All @@ -324,6 +311,26 @@ public static function getHost($checkIfTrusted = true)
return false;
}

protected static function getHostFromServerVariable()
{
try {
// this fails when trying to get the hostname before the config was initialized
// e.g. for loading the domain specific configuration file
// in such a case we always use HTTP_HOST
$preferServerName = Config::getInstance()->General['host_validation_use_server_name'];
} catch (\Exception $e) {
$preferServerName = false;
}

if ($preferServerName && strlen($host = self::getHostFromServerNameVar())) {
return $host;
} elseif (isset($_SERVER['HTTP_HOST']) && strlen($host = $_SERVER['HTTP_HOST'])) {
return $host;
}

return false;
}

/**
* Sets the host. Useful for CLI scripts, eg. core:archive command
*
Expand Down
17 changes: 6 additions & 11 deletions plugins/ScheduledReports/config/tcpdf_config.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,16 @@
if (!defined('K_PATH_URL')) {
// Automatic calculation for the following K_PATH_URL constant
$k_path_url = K_PATH_MAIN; // default value for console mode
if (isset($_SERVER['SERVER_NAME']) AND (!empty($_SERVER['SERVER_NAME']))) {
if (isset($_SERVER['HTTPS']) AND (!empty($_SERVER['HTTPS'])) AND strtolower($_SERVER['HTTPS']) != 'off') {
$k_path_url = 'https://';
} else {
$k_path_url = 'http://';
}
$k_path_url .= \Piwik\Url::getHostFromServerNameVar();
$k_path_url .= str_replace('\\', '/', substr(K_PATH_MAIN, (strlen($_SERVER['DOCUMENT_ROOT']) - 1)));
} elseif (isset($_SERVER['HTTP_HOST']) AND (!empty($_SERVER['HTTP_HOST']))) {
if (isset($_SERVER['HTTPS']) AND (!empty($_SERVER['HTTPS'])) AND strtolower($_SERVER['HTTPS']) != 'off') {

$host = \Piwik\Url::getHost(false);

if ($host) {
if (isset($_SERVER['HTTPS']) and (!empty($_SERVER['HTTPS'])) and strtolower($_SERVER['HTTPS']) != 'off') {
$k_path_url = 'https://';
} else {
$k_path_url = 'http://';
}
$k_path_url .= $_SERVER['HTTP_HOST'];
$k_path_url .= $host;
$k_path_url .= str_replace('\\', '/', substr(K_PATH_MAIN, (strlen($_SERVER['DOCUMENT_ROOT']) - 1)));
}

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.