From a8cccfce62a5433a7c310ef50ad641db41b4bfe4 Mon Sep 17 00:00:00 2001 From: Alex Pott <alex.a.pott@googlemail.com> Date: Wed, 21 Jan 2015 10:03:23 +0000 Subject: [PATCH] Revert "Issue #2221699 by mpdonadio, mikey_p, kim.pepper, arlinsandbulte: HTTP_HOST header cannot be trusted" This reverts commit 2c9eddf3ac07969341afaa144b7b3f9bd06cc0c4. --- core/lib/Drupal/Core/DrupalKernel.php | 54 ------------- .../Core/Installer/Form/SiteSettingsForm.php | 7 -- .../system/src/PathBasedBreadcrumbBuilder.php | 13 ++-- .../src/Tests/System/TrustedHostsTest.php | 62 --------------- core/modules/system/system.install | 22 ------ .../PathBasedBreadcrumbBuilderTest.php | 4 +- core/modules/views_ui/src/ViewUI.php | 5 +- .../DrupalKernelTrustedHostsTest.php | 78 ------------------- index.php | 2 +- sites/default/default.settings.php | 37 --------- sites/example.settings.local.php | 12 --- 11 files changed, 12 insertions(+), 284 deletions(-) delete mode 100644 core/modules/system/src/Tests/System/TrustedHostsTest.php delete mode 100644 core/tests/Drupal/Tests/Core/DrupalKernel/DrupalKernelTrustedHostsTest.php diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php index 67ac3b411d12..69717181c319 100644 --- a/core/lib/Drupal/Core/DrupalKernel.php +++ b/core/lib/Drupal/Core/DrupalKernel.php @@ -201,9 +201,6 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface { * from disk. Defaults to TRUE. * * @return static - * - * @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException - * In case the host name in the request is not trusted. */ public static function createFromRequest(Request $request, $class_loader, $environment, $allow_dumping = TRUE) { // Include our bootstrap file. @@ -220,15 +217,6 @@ public static function createFromRequest(Request $request, $class_loader, $envir $kernel->setSitePath($site_path); Settings::initialize(dirname($core_root), $site_path, $class_loader); - // Initialize our list of trusted HTTP Host headers to protect against - // header attacks. - $hostPatterns = Settings::get('trusted_host_patterns', array()); - if (PHP_SAPI !== 'cli' && !empty($hostPatterns)) { - if (static::setupTrustedHosts($request, $hostPatterns) === FALSE) { - throw new BadRequestHttpException('The provided host name is not valid for this server.'); - } - } - // Redirect the user to the installation script if Drupal has not been // installed yet (i.e., if no $databases array has been defined in the // settings.php file) and we are not already installing. @@ -1266,46 +1254,4 @@ public static function validateHostname(Request $request) { return TRUE; } - /** - * Sets up the lists of trusted HTTP Host headers. - * - * Since the HTTP Host header can be set by the user making the request, it - * 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. - * - * 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( - * '^example\.com$', - * '^*.example\.com$', - * ); - * @endcode - * - * @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) { - $request->setTrustedHosts($hostPatterns); - - // Get the host, which will validate the current request. - try { - $request->getHost(); - } - catch (\UnexpectedValueException $e) { - return FALSE; - } - - return TRUE; - } } diff --git a/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php b/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php index 6feaa457c1d2..8cf65c9c6ce8 100644 --- a/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php +++ b/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php @@ -155,13 +155,6 @@ public function submitForm(array &$form, FormStateInterface $form_state) { 'value' => $install_state['parameters']['profile'], 'required' => TRUE, ); - // Set the initial trusted host value if this isn't a command line install. - if (PHP_SAPI !== 'cli') { - $settings['settings']['trusted_host_patterns'] = (object) array( - 'value' => array('^' . preg_quote(\Drupal::request()->getHost()) . '$'), - 'required' => TRUE, - ); - } drupal_rewrite_settings($settings); diff --git a/core/modules/system/src/PathBasedBreadcrumbBuilder.php b/core/modules/system/src/PathBasedBreadcrumbBuilder.php index 6080d6b8f2a8..05693312e109 100644 --- a/core/modules/system/src/PathBasedBreadcrumbBuilder.php +++ b/core/modules/system/src/PathBasedBreadcrumbBuilder.php @@ -7,7 +7,6 @@ namespace Drupal\system; -use Drupal\Component\Utility\Unicode; use Drupal\Core\Access\AccessManagerInterface; use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface; use Drupal\Core\Config\ConfigFactoryInterface; @@ -15,17 +14,19 @@ use Drupal\Core\Link; use Drupal\Core\ParamConverter\ParamNotConvertedException; use Drupal\Core\PathProcessor\InboundPathProcessorInterface; -use Drupal\Core\Routing\RequestContext; use Drupal\Core\Routing\RouteMatch; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\Component\Utility\Unicode; use Drupal\Core\Url; use Symfony\Component\HttpFoundation\Request; +use Symfony\Cmf\Component\Routing\RouteObjectInterface; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; +use Symfony\Component\Routing\Matcher\RequestMatcherInterface; +use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\Exception\MethodNotAllowedException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; -use Symfony\Component\Routing\Matcher\RequestMatcherInterface; /** * Class to define the menu_link breadcrumb builder. @@ -36,7 +37,7 @@ class PathBasedBreadcrumbBuilder implements BreadcrumbBuilderInterface { /** * The router request context. * - * @var \Drupal\Core\Routing\RequestContext + * @var \Symfony\Component\Routing\RequestContext */ protected $context; @@ -85,7 +86,7 @@ class PathBasedBreadcrumbBuilder implements BreadcrumbBuilderInterface { /** * Constructs the PathBasedBreadcrumbBuilder. * - * @param \Drupal\Core\Routing\RequestContext $context + * @param \Symfony\Component\Routing\RequestContext $context * The router request context. * @param \Drupal\Core\Access\AccessManagerInterface $access_manager * The menu link access service. @@ -181,7 +182,7 @@ protected function getRequestForPath($path, array $exclude) { } // @todo Use the RequestHelper once https://drupal.org/node/2090293 is // fixed. - $request = Request::create($this->context->getCompleteBaseUrl() . '/' . $path); + $request = Request::create($this->context->getBaseUrl() . '/' . $path); // Performance optimization: set a short accept header to reduce overhead in // AcceptHeaderMatcher when matching the request. $request->headers->set('Accept', 'text/html'); diff --git a/core/modules/system/src/Tests/System/TrustedHostsTest.php b/core/modules/system/src/Tests/System/TrustedHostsTest.php deleted file mode 100644 index 2be2c8b70fe5..000000000000 --- a/core/modules/system/src/Tests/System/TrustedHostsTest.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php - -/** - * @file - * Contains \Drupal\system\Tests\System\TrustedHostsTest. - */ - -namespace Drupal\system\Tests\System; - -use Drupal\Core\Site\Settings; -use Drupal\simpletest\WebTestBase; - -/** - * Tests output on the status overview page. - * - * @group system - */ -class TrustedHostsTest extends WebTestBase { - - /** - * {@inheritdoc} - */ - protected function setUp() { - parent::setUp(); - - $admin_user = $this->drupalCreateUser(array( - 'administer site configuration', - )); - $this->drupalLogin($admin_user); - } - - /** - * Tests that the status page shows an error when the trusted host setting - * is missing from settings.php - */ - public function testStatusPageWithoutConfiguration() { - $this->drupalGet('admin/reports/status'); - $this->assertResponse(200, 'The status page is reachable.'); - - $this->assertRaw(t('Trusted Host Settings')); - $this->assertRaw(t('The trusted_host_patterns setting is not configured in settings.php.')); - } - - /** - * Tests that the status page shows the trusted patterns from settings.php. - */ - public function testStatusPageWithConfiguration() { - $settings['settings']['trusted_host_patterns'] = (object) array( - 'value' => array('^' . preg_quote(\Drupal::request()->getHost()) . '$'), - 'required' => TRUE, - ); - - $this->writeSettings($settings); - - $this->drupalGet('admin/reports/status'); - $this->assertResponse(200, 'The status page is reachable.'); - - $this->assertRaw(t('Trusted Host Settings')); - $this->assertRaw(t('The trusted_host_patterns setting is set to allow')); - } - -} diff --git a/core/modules/system/system.install b/core/modules/system/system.install index 4a8683eaae8a..08e7865983fd 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -611,28 +611,6 @@ function system_requirements($phase) { ); } } - - // See if trusted hostnames have been configured, and warn the user if they - // are not set. - if ($phase == 'runtime') { - $trusted_host_patterns = Settings::get('trusted_host_patterns'); - if (empty($trusted_host_patterns)) { - $requirements['trusted_host_patterns'] = array( - 'title' => t('Trusted Host Settings'), - 'value' => t('Not enabled'), - 'description' => t('The trusted_host_patterns setting is not configured in settings.php. This can lead to security vulnerabilities. It is <strong>highly recommended</strong> that you configure this. See <a href="@url">Protecting against HTTP HOST Header attacks</a> for more information.', array('@url' => 'https://www.drupal.org/node/1992030')), - 'severity' => REQUIREMENT_ERROR, - ); - } - else { - $requirements['trusted_host_patterns'] = array( - 'title' => t('Trusted Host Settings'), - 'value' => t('Enabled'), - 'description' => t('The trusted_host_patterns setting is set to allow %trusted_host_patterns', array('%trusted_host_patterns' => join(', ', $trusted_host_patterns))), - ); - } - } - return $requirements; } diff --git a/core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php b/core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php index fb530299c40f..7daf8c2fa9c2 100644 --- a/core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php +++ b/core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php @@ -58,7 +58,7 @@ class PathBasedBreadcrumbBuilderTest extends UnitTestCase { /** * The mocked route request context. * - * @var \Drupal\Core\Routing\RequestContext|\PHPUnit_Framework_MockObject_MockObject + * @var \Symfony\Component\Routing\RequestContext|\PHPUnit_Framework_MockObject_MockObject */ protected $context; @@ -89,7 +89,7 @@ protected function setUp() { $config_factory = $this->getConfigFactoryStub(array('system.site' => array('front' => 'test_frontpage'))); $this->pathProcessor = $this->getMock('\Drupal\Core\PathProcessor\InboundPathProcessorInterface'); - $this->context = $this->getMock('\Drupal\Core\Routing\RequestContext'); + $this->context = $this->getMock('\Symfony\Component\Routing\RequestContext'); $this->accessManager = $this->getMock('\Drupal\Core\Access\AccessManagerInterface'); $this->titleResolver = $this->getMock('\Drupal\Core\Controller\TitleResolverInterface'); diff --git a/core/modules/views_ui/src/ViewUI.php b/core/modules/views_ui/src/ViewUI.php index e8464fa31ecb..2f3e417d4252 100644 --- a/core/modules/views_ui/src/ViewUI.php +++ b/core/modules/views_ui/src/ViewUI.php @@ -611,9 +611,8 @@ public function renderPreview($display_id, $args = array()) { // Make view links come back to preview. - // Also override the current path so we get the pager, and make sure the - // Request object gets all of the proper values from $_SERVER. - $request = Request::createFromGlobals(); + // Also override the current path so we get the pager. + $request = new Request(); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, 'entity.view.preview_form'); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, \Drupal::service('router.route_provider')->getRouteByName('entity.view.preview_form')); $request->attributes->set('view', $this->storage); diff --git a/core/tests/Drupal/Tests/Core/DrupalKernel/DrupalKernelTrustedHostsTest.php b/core/tests/Drupal/Tests/Core/DrupalKernel/DrupalKernelTrustedHostsTest.php deleted file mode 100644 index 53a030513c5e..000000000000 --- a/core/tests/Drupal/Tests/Core/DrupalKernel/DrupalKernelTrustedHostsTest.php +++ /dev/null @@ -1,78 +0,0 @@ -<?php - -/** - * @file - * Contains \Drupal\Tests\Core\DrupalKernel\DrupalKernelTrustedHostsTest. - */ - -namespace Drupal\Tests\Core\DrupalKernel; - -use Drupal\Core\DrupalKernel; -use Drupal\Core\Site\Settings; -use Drupal\Tests\UnitTestCase; -use Symfony\Component\HttpFoundation\Request; - -/** - * @coversDefaultClass \Drupal\Core\DrupalKernel - * @group DrupalKernel - */ -class DrupalKernelTrustedHostsTest extends UnitTestCase { - - /** - * Tests hostname validation with settings. - * - * @covers ::setupTrustedHosts() - * - * @dataProvider providerTestTrustedHosts - */ - public function testTrustedHosts($host, $server_name, $message, $expected = FALSE) { - $request = new Request(); - - $settings = new Settings(array( - 'trusted_host_patterns' => array( - '^example\.com$', - '^.+\.example\.com$', - '^example\.org', - '^.+\.example\.org', - ) - )); - - if (!empty($host)) { - $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, $settings->get('trusted_host_patterns', array())); - - $this->assertSame($expected, $valid_host, $message); - } - - /** - * Provides test data for testTrustedHosts(). - */ - public function providerTestTrustedHosts() { - $data = []; - - // 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 the additional paterns from the settings. - $data[] = ['example.com', 'www.example.com', 'host from settings is trusted', TRUE]; - $data[] = ['subdomain.example.com', 'www.example.com', 'host from settings is trusted', TRUE]; - $data[] = ['www.example.org', 'www.example.com', 'host from settings is trusted', TRUE]; - $data[] = ['example.org', 'www.example.com', 'host from settings is trusted', TRUE]; - - // Tests mismatch. - $data[] = ['www.blackhat.com', 'www.example.com', 'unspecified host is untrusted', FALSE]; - - return $data; - } - -} diff --git a/index.php b/index.php index 867f0e09215a..55fc9474985a 100644 --- a/index.php +++ b/index.php @@ -27,7 +27,7 @@ $kernel->terminate($request, $response); } catch (HttpExceptionInterface $e) { - $response = new Response($e->getMessage(), $e->getStatusCode()); + $response = new Response('', $e->getStatusCode()); $response->prepare($request)->send(); } catch (Exception $e) { diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php index 7cc10be7260c..76d26fcfdf3c 100644 --- a/sites/default/default.settings.php +++ b/sites/default/default.settings.php @@ -607,40 +607,3 @@ # if (file_exists(__DIR__ . '/settings.local.php')) { # include __DIR__ . '/settings.local.php'; # } - -/** - * Trusted host configuration. - * - * 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 patterns, 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 should specify all of the host patterns that are - * allowed by your site. - * - * For example: - * @code - * $settings['trusted_host_patterns'] = array( - * '^example\.com$', - * '^.+\.example\.com$', - * '^example\.org', - * '^.+\.example\.org', - * ); - * @endcode - * will allow the site to run off of all variants of example.com and - * example.org, with all subdomains included. - */ diff --git a/sites/example.settings.local.php b/sites/example.settings.local.php index 3d5857a306b3..7859fe502195 100644 --- a/sites/example.settings.local.php +++ b/sites/example.settings.local.php @@ -55,15 +55,3 @@ * using these parameters in a request to rebuild.php. */ $settings['rebuild_access'] = TRUE; - -/** - * Trust localhost. - * - * This will configure several common hostnames used for local development to - * be trusted hosts. - */ -$settings['trusted_host_patterns'] = array( - '^localhost$', - '^localhost\.*', - '\.local$', -); -- GitLab