You are here

class FailedLogins in Security Review 8

Checks for abundant failed logins.

Hierarchy

Expanded class hierarchy of FailedLogins

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

File

src/Checks/FailedLogins.php, line 12

Namespace

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

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

  /**
   * {@inheritdoc}
   */
  public function getTitle() {
    return 'Failed logins';
  }

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

    // If dblog is not enabled return with hidden INFO.
    if (!$this
      ->moduleHandler()
      ->moduleExists('dblog')) {
      return $this
        ->createResult(CheckResult::INFO, [], FALSE);
    }
    $result = CheckResult::SUCCESS;
    $findings = [];
    $last_result = $this
      ->lastResult();
    $visible = FALSE;

    // Prepare the query.
    $query = $this
      ->database()
      ->select('watchdog', 'w');
    $query
      ->fields('w', [
      'severity',
      'type',
      'timestamp',
      'message',
      'variables',
      'hostname',
    ]);
    $query
      ->condition('type', 'user')
      ->condition('severity', RfcLogLevel::NOTICE)
      ->condition('message', 'Login attempt failed from %ip.');
    if ($last_result instanceof CheckResult) {

      // Only check entries that got recorded since the last run of the check.
      $query
        ->condition('timestamp', $last_result
        ->time(), '>=');
    }

    // Execute the query.
    $db_result = $query
      ->execute();

    // Count the number of failed logins per IP.
    $entries = [];
    foreach ($db_result as $row) {
      $ip = unserialize($row->variables)['%ip'];
      $entry_for_ip =& $entries[$ip];
      if (!isset($entry_for_ip)) {
        $entry_for_ip = 0;
      }
      $entry_for_ip++;
    }

    // Filter the IPs with more than 10 failed logins.
    if (!empty($entries)) {
      foreach ($entries as $ip => $count) {
        if ($count > 10) {
          $findings[] = $ip;
        }
      }
    }
    if (!empty($findings)) {
      $result = CheckResult::FAIL;
      $visible = TRUE;
    }
    return $this
      ->createResult($result, $findings, $visible);
  }

  /**
   * {@inheritdoc}
   */
  public function help() {
    $paragraphs = [];
    $paragraphs[] = $this
      ->t('Failed login attempts from the same IP may be an artifact of a malicious user attempting to brute-force their way onto your site as an authenticated user to carry out nefarious deeds.');
    return [
      '#theme' => 'check_help',
      '#title' => $this
        ->t('Abundant failed logins from the same IP'),
      '#paragraphs' => $paragraphs,
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function evaluate(CheckResult $result) {
    $findings = $result
      ->findings();
    if (empty($findings)) {
      return [];
    }
    $paragraphs = [];
    $paragraphs[] = $this
      ->t('The following IPs were observed with an abundance of failed login attempts.');
    return [
      '#theme' => 'check_evaluation',
      '#paragraphs' => $paragraphs,
      '#items' => $result
        ->findings(),
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function evaluatePlain(CheckResult $result) {
    $findings = $result
      ->findings();
    if (empty($findings)) {
      return '';
    }
    $output = $this
      ->t('Suspicious IP addresses:') . ":\n";
    foreach ($findings as $ip) {
      $output .= "\t" . $ip . "\n";
    }
    return $output;
  }

  /**
   * {@inheritdoc}
   */
  public function getMessage($result_const) {
    switch ($result_const) {
      case CheckResult::FAIL:
        return $this
          ->t('Failed login attempts from the same IP. These may be a brute-force attack to gain access to your site.');
      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::getMachineTitle public function Returns the machine name of the check. 5
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
FailedLogins::evaluate public function Returns the evaluation page of a result. Overrides Check::evaluate
FailedLogins::evaluatePlain public function Evaluates a CheckResult and returns a plaintext output. Overrides Check::evaluatePlain
FailedLogins::getMessage public function Converts a result integer to a human-readable result message. Overrides Check::getMessage
FailedLogins::getNamespace public function Returns the namespace of the check. Overrides Check::getNamespace
FailedLogins::getTitle public function Returns the human-readable title of the check. Overrides Check::getTitle
FailedLogins::help public function Returns the check-specific help page. Overrides Check::help
FailedLogins::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.