You are here

class InputFormats in Security Review 8

Checks for vulnerabilities related to input formats.

Checks for formats that either do not have HTML filter that can be used by untrusted users, or if they do check if unsafe tags are allowed.

Hierarchy

Expanded class hierarchy of InputFormats

1 file declares its use of InputFormats
security_review.module in ./security_review.module
Site security review and reporting Drupal module.

File

src/Checks/InputFormats.php, line 16

Namespace

Drupal\security_review\Checks
View source
class InputFormats extends Check {

  /**
   * {@inheritdoc}
   */
  public function getNamespace() {
    return 'Security Review';
  }

  /**
   * {@inheritdoc}
   */
  public function getTitle() {
    return 'Text formats';
  }

  /**
   * {@inheritdoc}
   */
  public function getMachineTitle() {
    return 'input_formats';
  }

  /**
   * {@inheritdoc}
   */
  public function run() {

    // If filter is not enabled return with INFO.
    if (!$this
      ->moduleHandler()
      ->moduleExists('filter')) {
      return $this
        ->createResult(CheckResult::INFO);
    }
    $result = CheckResult::SUCCESS;
    $findings = [];
    $formats = filter_formats();
    $untrusted_roles = $this
      ->security()
      ->untrustedRoles();
    $unsafe_tags = $this
      ->security()
      ->unsafeTags();
    foreach ($formats as $format) {
      $format_roles = array_keys(filter_get_roles_by_format($format));
      $intersect = array_intersect($format_roles, $untrusted_roles);
      if (!empty($intersect)) {

        // Untrusted users can use this format.
        // Check format for enabled HTML filter.
        $filter_html_enabled = FALSE;
        if ($format
          ->filters()
          ->has('filter_html')) {
          $filter_html_enabled = $format
            ->filters('filter_html')
            ->getConfiguration()['status'];
        }
        $filter_html_escape_enabled = FALSE;
        if ($format
          ->filters()
          ->has('filter_html_escape')) {
          $filter_html_escape_enabled = $format
            ->filters('filter_html_escape')
            ->getConfiguration()['status'];
        }
        if ($filter_html_enabled) {
          $filter = $format
            ->filters('filter_html');

          // Check for unsafe tags in allowed tags.
          $allowed_tags = array_keys($filter
            ->getHTMLRestrictions()['allowed']);
          foreach (array_intersect($allowed_tags, $unsafe_tags) as $tag) {

            // Found an unsafe tag.
            $findings['tags'][$format
              ->id()] = $tag;
          }
        }
        elseif (!$filter_html_escape_enabled) {

          // Format is usable by untrusted users but does not contain the HTML
          // Filter or the HTML escape.
          $findings['formats'][$format
            ->id()] = $format
            ->label();
        }
      }
    }
    if (!empty($findings)) {
      $result = CheckResult::FAIL;
    }
    return $this
      ->createResult($result, $findings);
  }

  /**
   * {@inheritdoc}
   */
  public function help() {
    $paragraphs = [];
    $paragraphs[] = $this
      ->t("Certain HTML tags can allow an attacker to take control of your site. Drupal's input format system makes use of a set filters to run on incoming text. The 'HTML Filter' strips out harmful tags and Javascript events and should be used on all formats accessible by untrusted users.");
    $paragraphs[] = new Link($this
      ->t("Read more about Drupal's input formats in the handbooks."), Url::fromUri('http://drupal.org/node/224921'));
    return [
      '#theme' => 'check_help',
      '#title' => $this
        ->t('Allowed HTML tags in text formats'),
      '#paragraphs' => $paragraphs,
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function evaluate(CheckResult $result) {
    $output = [];
    if (!empty($result
      ->findings()['tags'])) {
      $paragraphs = [];
      $paragraphs[] = Link::createFromRoute($this
        ->t('Review your text formats.'), 'filter.admin_overview');
      $paragraphs[] = $this
        ->t('It is recommended you remove the following tags from roles accessible by untrusted users.');
      $output[] = [
        '#theme' => 'check_evaluation',
        '#paragraphs' => $paragraphs,
        '#items' => $result
          ->findings()['tags'],
      ];
    }
    if (!empty($result
      ->findings()['formats'])) {
      $paragraphs = [];
      $paragraphs[] = $this
        ->t('The following formats are usable by untrusted roles and do not filter or escape allowed HTML tags.');
      $output[] = [
        '#theme' => 'check_evaluation',
        '#paragraphs' => $paragraphs,
        '#items' => $result
          ->findings()['formats'],
      ];
    }
    return $output;
  }

  /**
   * {@inheritdoc}
   */
  public function evaluatePlain(CheckResult $result) {
    $output = '';
    if (!empty($result
      ->findings()['tags'])) {
      $output .= $this
        ->t('Tags') . "\n";
      foreach ($result
        ->findings()['tags'] as $tag) {
        $output .= "\t{$tag}\n";
      }
    }
    if (!empty($result
      ->findings()['formats'])) {
      $output .= $this
        ->t('Formats') . "\n";
      foreach ($result
        ->findings()['formats'] as $format) {
        $output .= "\t{$format}\n";
      }
    }
    return $output;
  }

  /**
   * {@inheritdoc}
   */
  public function getMessage($result_const) {
    switch ($result_const) {
      case CheckResult::SUCCESS:
        return $this
          ->t('Untrusted users are not allowed to input dangerous HTML tags.');
      case CheckResult::FAIL:
        return $this
          ->t('Untrusted users are allowed to input dangerous HTML tags.');
      case CheckResult::INFO:
        return $this
          ->t('Module filter is not enabled.');
      default:
        return $this
          ->t('Unexpected result.');
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
Check::$config protected property The configuration storage for this check.
Check::$container protected property The service container.
Check::$settings protected property Settings handler for this check.
Check::$state protected property The State system.
Check::$statePrefix protected property The check's prefix in the State system.
Check::checklist protected function Returns the Security Review Checklist service.
Check::configFactory protected function Returns the Config factory.
Check::container protected function Returns the service container.
Check::createResult public function Creates a new CheckResult for this Check.
Check::currentUser protected function Returns the current Drupal user.
Check::database protected function Returns the database connection.
Check::enable public function Enables the check. Has no effect if the check was not skipped.
Check::entityTypeManager protected function Returns the entity type manager.
Check::getMachineNamespace public function Returns the namespace of the check.
Check::id final public function Returns the identifier constructed using the namespace and title values.
Check::isSkipped public function Returns whether the check is skipped. Checks are not skipped by default.
Check::kernel protected function Returns the Drupal Kernel.
Check::lastResult public function Returns the last stored result of the check.
Check::lastRun public function Returns the timestamp the check was last run.
Check::moduleHandler protected function Returns the module handler.
Check::runCli public function Same as run(), but used in CLI context such as Drush. 2
Check::security protected function Returns the Security Review Security service.
Check::securityReview protected function Returns the Security Review service.
Check::settings public function Returns the check-specific settings' handler.
Check::skip public function Marks the check as skipped.
Check::skippedBy public function Returns the user the check was skipped by.
Check::skippedOn public function Returns the timestamp the check was last skipped on.
Check::storeResult public function Stores a result in the state system.
Check::storesFindings public function Returns whether the findings should be stored or reproduced when needed. 2
Check::__construct public function Initializes the configuration storage and the settings handler. 2
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
InputFormats::evaluate public function Returns the evaluation page of a result. Overrides Check::evaluate
InputFormats::evaluatePlain public function Evaluates a CheckResult and returns a plaintext output. Overrides Check::evaluatePlain
InputFormats::getMachineTitle public function Returns the machine name of the check. Overrides Check::getMachineTitle
InputFormats::getMessage public function Converts a result integer to a human-readable result message. Overrides Check::getMessage
InputFormats::getNamespace public function Returns the namespace of the check. Overrides Check::getNamespace
InputFormats::getTitle public function Returns the human-readable title of the check. Overrides Check::getTitle
InputFormats::help public function Returns the check-specific help page. Overrides Check::help
InputFormats::run public function The actual procedure of carrying out the check. Overrides Check::run
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.