Implement occ command security:bruteforceattemps:reset-for-ip

Signed-off-by: Johannes Riedel <joeried@users.noreply.github.com>
This commit is contained in:
Johannes Riedel 2020-03-17 17:06:52 +01:00
parent 25ce3c434b
commit 0c38569c83
5 changed files with 94 additions and 6 deletions

View File

@ -0,0 +1,62 @@
<?php
/**
* @copyright Copyright (c) 2020, Johannes Riedel (johannes@johannes-riedel.de)
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OC\Core\Command\Security;
use OC\Core\Command\Base;
use OC\Security\Bruteforce\Throttler;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class ResetBruteforceAttempts extends Base {
/** @var Throttler */
protected $throttler;
public function __construct(Throttler $throttler) {
$this->throttler = $throttler;
parent::__construct();
}
protected function configure() {
$this
->setName('security:bruteforce:reset')
->setDescription('resets bruteforce attemps for given IP address')
->addArgument(
'ipaddress',
InputArgument::REQUIRED,
'IP address for which the attempts are to be reset'
);
}
protected function execute(InputInterface $input, OutputInterface $output) {
$ip = $input->getArgument('ipaddress');
if (!filter_var($ip, FILTER_VALIDATE_IP)) {
$output->writeln('<error>"' . $ip . '" is not a valid IP address</error>');
return 1;
}
$this->throttler->resetDelayForIP($ip);
}
}

View File

@ -174,6 +174,7 @@ if (\OC::$server->getConfig()->getSystemValue('installed', false)) {
$application->add(new OC\Core\Command\Security\ListCertificates(\OC::$server->getCertificateManager(null), \OC::$server->getL10N('core')));
$application->add(new OC\Core\Command\Security\ImportCertificate(\OC::$server->getCertificateManager(null)));
$application->add(new OC\Core\Command\Security\RemoveCertificate(\OC::$server->getCertificateManager(null)));
$application->add(new OC\Core\Command\Security\ResetBruteforceAttempts(\OC::$server->getBruteForceThrottler()));
} else {
$application->add(new OC\Core\Command\Maintenance\Install(\OC::$server->getSystemConfig()));
}

View File

@ -770,6 +770,7 @@ return array(
'OC\\Core\\Command\\Security\\ImportCertificate' => $baseDir . '/core/Command/Security/ImportCertificate.php',
'OC\\Core\\Command\\Security\\ListCertificates' => $baseDir . '/core/Command/Security/ListCertificates.php',
'OC\\Core\\Command\\Security\\RemoveCertificate' => $baseDir . '/core/Command/Security/RemoveCertificate.php',
'OC\\Core\\Command\\Security\\ResetBruteforceAttempts' => $baseDir . '/core/Command/Security/ResetBruteforceAttempts.php',
'OC\\Core\\Command\\Status' => $baseDir . '/core/Command/Status.php',
'OC\\Core\\Command\\TwoFactorAuth\\Base' => $baseDir . '/core/Command/TwoFactorAuth/Base.php',
'OC\\Core\\Command\\TwoFactorAuth\\Cleanup' => $baseDir . '/core/Command/TwoFactorAuth/Cleanup.php',

View File

@ -799,6 +799,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Core\\Command\\Security\\ImportCertificate' => __DIR__ . '/../../..' . '/core/Command/Security/ImportCertificate.php',
'OC\\Core\\Command\\Security\\ListCertificates' => __DIR__ . '/../../..' . '/core/Command/Security/ListCertificates.php',
'OC\\Core\\Command\\Security\\RemoveCertificate' => __DIR__ . '/../../..' . '/core/Command/Security/RemoveCertificate.php',
'OC\\Core\\Command\\Security\\ResetBruteforceAttempts' => __DIR__ . '/../../..' . '/core/Command/Security/ResetBruteforceAttempts.php',
'OC\\Core\\Command\\Status' => __DIR__ . '/../../..' . '/core/Command/Status.php',
'OC\\Core\\Command\\TwoFactorAuth\\Base' => __DIR__ . '/../../..' . '/core/Command/TwoFactorAuth/Base.php',
'OC\\Core\\Command\\TwoFactorAuth\\Cleanup' => __DIR__ . '/../../..' . '/core/Command/TwoFactorAuth/Cleanup.php',

View File

@ -88,6 +88,17 @@ class Throttler {
return $d2->diff($d1);
}
/**
* Calculate the cut off timestamp
*
* @return int
*/
private function getCutoffTimestamp(): int {
return (new \DateTime())
->sub($this->getCutoff(43200))
->getTimestamp();
}
/**
* Register a failed attempt to bruteforce a security control
*
@ -212,9 +223,7 @@ class Throttler {
return 0;
}
$cutoffTime = (new \DateTime())
->sub($this->getCutoff(43200))
->getTimestamp();
$cutoffTime = $this->getCutoffTimestamp();
$qb = $this->db->getQueryBuilder();
$qb->select('*')
@ -259,9 +268,7 @@ class Throttler {
return;
}
$cutoffTime = (new \DateTime())
->sub($this->getCutoff(43200))
->getTimestamp();
$cutoffTime = $this->getCutoffTimestamp();
$qb = $this->db->getQueryBuilder();
$qb->delete('bruteforce_attempts')
@ -273,6 +280,22 @@ class Throttler {
$qb->execute();
}
/**
* Reset the throttling delay for an IP address
*
* @param string $ip
*/
public function resetDelayForIP($ip){
$cutoffTime = $this->getCutoffTimestamp();
$qb = $this->db->getQueryBuilder();
$qb->delete('bruteforce_attempts')
->where($qb->expr()->gt('occurred', $qb->createNamedParameter($cutoffTime)))
->andWhere($qb->expr()->eq('ip', $qb->createNamedParameter($ip)));
$qb->execute();
}
/**
* Will sleep for the defined amount of time
*