5 * Contains \Drupal\security_review\Checks\TrustedHosts.
8 namespace Drupal\security_review\Checks;
11 use Drupal\security_review\Check;
12 use Drupal\security_review\CheckResult;
13 use Drupal\security_review\CheckSettings\TrustedHostSettings;
16 * Checks for base_url and trusted_host_patterns settings in settings.php.
18 class TrustedHosts extends Check {
23 public function __construct() {
24 parent::__construct();
25 $this->settings = new TrustedHostSettings($this, $this->config);
31 public function getNamespace() {
32 return 'Security Review';
38 public function getTitle() {
39 return 'Trusted hosts';
45 public function run() {
46 $result = CheckResult::FAIL;
47 $base_url_set = FALSE;
48 $trusted_host_patterns_set = FALSE;
50 $settings_php = $this->security()->sitePath() . '/settings.php';
52 if (!file_exists($settings_php)) {
53 return $this->createResult(CheckResult::INFO, [], FALSE);
56 if ($this->settings()->get('method', 'token') === 'token') {
58 $content = file_get_contents($settings_php);
59 $tokens = token_get_all($content);
61 $prev_settings_line = -1;
62 foreach ($tokens as $token) {
63 if (is_array($token)) {
64 // Get information about the current token.
66 $is_variable = $token[0] === T_VARIABLE;
67 $is_string = $token[0] === T_CONSTANT_ENCAPSED_STRING;
68 $is_settings = $is_variable ? $token[1] == '$settings' : FALSE;
69 $is_base_url = $token[1] == '$base_url';
70 $is_thp = trim($token[1], "\"'") == 'trusted_host_patterns';
71 $is_after_settings = $line == $prev_settings_line;
73 // Check for $base_url.
74 if ($is_variable && $is_base_url) {
76 $result = CheckResult::SUCCESS;
79 // Check for $settings['trusted_host_patterns'].
80 if ($is_after_settings && $is_string && $is_thp) {
81 $trusted_host_patterns_set = TRUE;
82 $result = CheckResult::SUCCESS;
85 // If found both settings stop the review.
86 if ($base_url_set && $trusted_host_patterns_set) {
87 // Got everything we need.
91 // Store last $settings line.
93 $prev_settings_line = $line;
100 include $settings_php;
101 $base_url_set = isset($base_url);
102 $trusted_host_patterns_set = isset($settings['trusted_host_patterns']);
105 if ($result === CheckResult::FAIL) {
106 // Provide information if the check failed.
108 $findings['base_url'] = $base_url;
109 $findings['settings'] = $settings_php;
110 $findings['base_url_set'] = $base_url_set;
111 $findings['trusted_host_patterns_set'] = $trusted_host_patterns_set;
114 return $this->createResult($result, $findings);
120 public function help() {
122 $paragraphs[] = $this->t('Often Drupal needs to know the URL(s) it is responding from in order to build full links back to itself (e.g. password reset links sent via email). Until you explicitly tell Drupal what full or partial URL(s) it should respond for it must dynamically detect it based on the incoming request, something that can be malicously spoofed in order to trick someone into unknowningly visiting an attacker\'s site (known as a HTTP host header attack).');
125 '#theme' => 'check_help',
126 '#title' => $this->t('Drupal trusted hosts'),
127 '#paragraphs' => $paragraphs,
134 public function evaluate(CheckResult $result) {
136 if ($result->result() !== CheckResult::FAIL) {
140 $settings_php = $this->security()->sitePath() . '/settings.php';
143 $paragraphs[] = $this->t('This site is responding from the URL: :url.', [':url' => $base_url]);
144 $paragraphs[] = $this->t('If the site should be available only at that URL it is recommended that you set it as the $base_url variable in the settings.php file at @file.', ['@file' => $settings_php]);
145 $paragraphs[] = $this->t('If the site has multiple URLs it can respond from you should whitelist host patterns with trusted_host_patterns in settings.php.');
146 $paragraphs[] = $this->l($this->t('Read more about HTTP Host Header attacks and setting trusted_host_patterns.'), Url::fromUri('https://www.drupal.org/node/1992030'));
149 '#theme' => 'check_evaluation',
150 '#paragraphs' => $paragraphs,
158 public function getMessage($result_const) {
159 switch ($result_const) {
160 case CheckResult::SUCCESS:
161 return $this->t('Either $base_url or trusted_host_patterns is set.');
163 case CheckResult::FAIL:
164 return $this->t('Neither $base_url nor trusted_host_patterns is set.');
167 return $this->t('Unexpected result.');