diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php index 96a4b83..66615fb 100644 --- a/core/lib/Drupal/Core/DrupalKernel.php +++ b/core/lib/Drupal/Core/DrupalKernel.php @@ -226,11 +226,10 @@ public static function createFromRequest(Request $request, $class_loader, $envir Settings::initialize(dirname($core_root), $site_path, $class_loader); // Initialize our list of trusted HTTP Host headers to protect against - // header attacks. This can be bypassed by setting - // $settings['bypass_trusted_hosts'] = TRUE; - $bypass_trusted_hosts = Settings::get('bypass_trusted_hosts', FALSE); - if (PHP_SAPI !== 'cli' && !$bypass_trusted_hosts) { - if (static::setupTrustedHosts($request) === FALSE) { + // header attacks + $hostPatterns = Settings::get('trusted_host_patterns', array()); + if (PHP_SAPI !== 'cli' && !empty($hostPatterns)) { + if (static::setupTrustedHosts($request, $hostPatterns) === FALSE) { throw new BadRequestHttpException(); } } @@ -1333,18 +1332,10 @@ public static function validateHostname(Request $request) { * is possible to create an attack vectors against a site by overriding this. * Symfony provides a mechanism for creating a list of trusted Host values. * - * The default list of trusted hosts is set to - * - localhost - * - locahost.* - * - *.local - * - the value of $_SERVER['SERVER_NAME'], which is set by the system - * administrator. - * - * The default list should be sufficient for installations running a single - * site off of a canonical domain name. Additional host patterns (as - * regular expressions) can be configured throught settings.php for multisite - * installations, sites using ServerAlias without canonical redirection, or - * configurations where the site responds to default requests. For example, + * Host patterns (as regular expressions) can be configured throught + * settings.php for multisite installations, sites using ServerAlias without + * canonical redirection, or configurations where the site responds to default + * requests. For example, * * @code * $settings['trusted_host_patterns'] = array( @@ -1355,28 +1346,15 @@ public static function validateHostname(Request $request) { * * @param \Symfony\Component\HttpFoundation\Request $request * The request object + * @param array $hostPatterns + * The array of trusted host patterns * * @return boolean * TRUE if the Host header is trusted, FALSE otherwise * * @see https://www.drupal.org/node/1992030 */ - protected static function setupTrustedHosts(Request $request) { - $hostPatterns = Settings::get('trusted_host_patterns', array()); - - // Trust local hostnames to account for misconfigured local development - // environments. - $hostPatterns = array_merge($hostPatterns, array( - '^localhost$', - '^localhost\.*', - '\.local$', - )); - - $server_name = $request->server->get('SERVER_NAME'); - if (!empty($server_name)) { - $hostPatterns[] = '^' . preg_quote($server_name) . '$'; - } - + protected static function setupTrustedHosts(Request $request, $hostPatterns) { $request->setTrustedHosts($hostPatterns); // Get the host, which will validate the current request. diff --git a/core/tests/Drupal/Tests/Core/DrupalKernel/DrupalKernelTrustedHostsTest.php b/core/tests/Drupal/Tests/Core/DrupalKernel/DrupalKernelTrustedHostsTest.php index d91665c..150a724 100644 --- a/core/tests/Drupal/Tests/Core/DrupalKernel/DrupalKernelTrustedHostsTest.php +++ b/core/tests/Drupal/Tests/Core/DrupalKernel/DrupalKernelTrustedHostsTest.php @@ -19,7 +19,7 @@ class DrupalKernelTrustedHostsTest extends UnitTestCase { /** - * Tests hostname validation. + * Tests hostname validation with settings. * * @covers ::setupTrustedHosts() * @@ -28,53 +28,6 @@ class DrupalKernelTrustedHostsTest extends UnitTestCase { public function testTrustedHosts($host, $server_name, $message, $expected = FALSE) { $request = new Request(); - $request->headers->set('HOST', $host); - $request->server->set('SERVER_NAME', $server_name); - - $method = new \ReflectionMethod('Drupal\Core\DrupalKernel', 'setupTrustedHosts'); - $method->setAccessible(TRUE); - $valid_host = $method->invoke(null, $request); - - $this->assertSame($expected, $valid_host, $message); - } - - /** - * Provides test data for testTrustedHosts(). - */ - public function providerTestTrustedHosts() { - $data = []; - - // Test our hardcoded defaults for local development with non-production - // server configurations. - $data[] = ['localhost', '', 'localhost is trusted', TRUE]; - $data[] = ['localhost.d8', '', 'localhost.d8 is trusted', TRUE]; - $data[] = ['d8.local', '', 'd8.local is trusted', TRUE]; - - // Tests canonical URL - $data[] = ['www.example.com', 'www.example.com', 'canonical URL is trusted', TRUE]; - - // Tests missing hostname for HTTP/1.0 compatability where the Host - // header is optional - $data[] = [NULL, 'www.example.com', 'empty Host is valid', TRUE]; - - // Tests mismatches - $data[] = ['example.com', 'www.example.com', 'non-canonical host is not trusted', FALSE]; - $data[] = ['subdomain.example.com', 'www.example.com', 'host with subdomain is not trusted', FALSE]; - $data[] = ['www.example.org', 'www.example.com', 'host with different TLD is not trusted', FALSE]; - $data[] = ['example.org', 'www.example.com', 'host with different TLD is not trusted', FALSE]; - $data[] = ['www.blackhat.com', 'www.example.com', 'unspecified host is untrusted', FALSE]; - - return $data; - } - - /** - * Tests hostname validation with settings. - * - * @covers ::setupTrustedHosts() - * - * @dataProvider providerTestTrustedHostsWithSettings - */ - public function testTrustedHostsWithSettings($host, $server_name, $message, $expected = FALSE) { $settings = new Settings(array( 'trusted_host_patterns' => array( '^example\.com$', @@ -84,8 +37,6 @@ public function testTrustedHostsWithSettings($host, $server_name, $message, $exp ) )); - $request = new Request(); - if (!empty($host)) { $request->headers->set('HOST', $host); } @@ -94,23 +45,17 @@ public function testTrustedHostsWithSettings($host, $server_name, $message, $exp $method = new \ReflectionMethod('Drupal\Core\DrupalKernel', 'setupTrustedHosts'); $method->setAccessible(TRUE); - $valid_host = $method->invoke(null, $request); + $valid_host = $method->invoke(null, $request, $settings->get('trusted_host_patterns', array())); $this->assertSame($expected, $valid_host, $message); } /** - * Provides test data for testTrustedHostsWithSettings(). + * Provides test data for testTrustedHosts(). */ - public function providerTestTrustedHostsWithSettings() { + public function providerTestTrustedHosts() { $data = []; - // Test our hardcoded defaults for local development with non-production - // server configurations. - $data[] = ['localhost', '', 'localhost is trusted', TRUE]; - $data[] = ['localhost.d8', '', 'localhost.d8 is trusted', TRUE]; - $data[] = ['d8.local', '', 'd8.local is trusted', TRUE]; - // Tests canonical URL $data[] = ['www.example.com', 'www.example.com', 'canonical URL is trusted', TRUE]; diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php index 3e10e30..23bfea5 100644 --- a/sites/default/default.settings.php +++ b/sites/default/default.settings.php @@ -635,16 +635,26 @@ /** * Trusted host configuration. * - * Drupal core uses the Symfony trusted host mechanism to prevent HTTP Host - * header spoofing. To full enable this, your webserver must be configured to - * report the canonical name in $_SERVER['SERVER_NAME']. + * Drupal core can use the Symfony trusted host mechanism to prevent HTTP Host + * header spoofing. + * + * To enable the trusted host mechanism, you enable your allowable hosts + * in $settings['trusted_host_patterns']. This should be an array of regular + * expression paterns, without delimiters, representing the hosts you would like + * to allow. + * + * For example: + * @code + * $settings['trusted_host_patterns'] = array( + * '^www\.example\.com$', + * ); + * @endcode + * will allow the site to only run from www.example.com. * * If you are running multisite, or if you are running your site from * different domain names (eg, you don't redirect http://www.example.com to - * http://example.com), you can configure additional trusted host patterns - * with $settings['trusted_host_patterns']. This should be an array of - * regular expression paterns, without delimiters, representing the hosts you - * would like to allow. + * http://example.com), you should specify all of the host patterns that are + * allowed by your site. * * For example: * @code @@ -655,12 +665,6 @@ * '^.+\.example\.org', * ); * @endcode - * will allow the site to run off of all variantes of example.com and + * will allow the site to run off of all variants of example.com and * example.org, with all subdomains included. - * - * @see http://httpd.apache.org/docs/current/mod/core.html#usecanonicalname - * @see http://stackoverflow.com/questions/2297403/http-host-vs-server-name/2297421#2297421 - * - * Remove the leading hash sign if you would like to disable this functionality. */ -# $settings['bypass_trusted_hosts'] = TRUE;