aboutsummaryrefslogtreecommitdiffstats
path: root/lib/private/Security
diff options
context:
space:
mode:
Diffstat (limited to 'lib/private/Security')
-rw-r--r--lib/private/Security/Bruteforce/Throttler.php43
-rw-r--r--lib/private/Security/Hasher.php8
-rw-r--r--lib/private/Security/RateLimiting/Limiter.php7
-rw-r--r--lib/private/Security/Signature/Model/SignedRequest.php4
-rw-r--r--lib/private/Security/VerificationToken/VerificationToken.php6
5 files changed, 44 insertions, 24 deletions
diff --git a/lib/private/Security/Bruteforce/Throttler.php b/lib/private/Security/Bruteforce/Throttler.php
index 21d50848641..574f6c80c3f 100644
--- a/lib/private/Security/Bruteforce/Throttler.php
+++ b/lib/private/Security/Bruteforce/Throttler.php
@@ -127,6 +127,13 @@ class Throttler implements IThrottler {
*/
public function getDelay(string $ip, string $action = ''): int {
$attempts = $this->getAttempts($ip, $action);
+ return $this->calculateDelay($attempts);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function calculateDelay(int $attempts): int {
if ($attempts === 0) {
return 0;
}
@@ -199,25 +206,31 @@ class Throttler implements IThrottler {
* {@inheritDoc}
*/
public function sleepDelayOrThrowOnMax(string $ip, string $action = ''): int {
- $delay = $this->getDelay($ip, $action);
- if (($delay === self::MAX_DELAY_MS) && $this->getAttempts($ip, $action, 0.5) > $this->config->getSystemValueInt('auth.bruteforce.max-attempts', self::MAX_ATTEMPTS)) {
- $this->logger->info('IP address blocked because it reached the maximum failed attempts in the last 30 minutes [action: {action}, ip: {ip}]', [
- 'action' => $action,
- 'ip' => $ip,
- ]);
- // If the ip made too many attempts within the last 30 mins we don't execute anymore
- throw new MaxDelayReached('Reached maximum delay');
- }
- if ($delay > 100) {
- $this->logger->info('IP address throttled because it reached the attempts limit in the last 30 minutes [action: {action}, delay: {delay}, ip: {ip}]', [
+ $maxAttempts = $this->config->getSystemValueInt('auth.bruteforce.max-attempts', self::MAX_ATTEMPTS);
+ $attempts = $this->getAttempts($ip, $action);
+ if ($attempts > $maxAttempts) {
+ $attempts30mins = $this->getAttempts($ip, $action, 0.5);
+ if ($attempts30mins > $maxAttempts) {
+ $this->logger->info('IP address blocked because it reached the maximum failed attempts in the last 30 minutes [action: {action}, attempts: {attempts}, ip: {ip}]', [
+ 'action' => $action,
+ 'ip' => $ip,
+ 'attempts' => $attempts30mins,
+ ]);
+ // If the ip made too many attempts within the last 30 mins we don't execute anymore
+ throw new MaxDelayReached('Reached maximum delay');
+ }
+
+ $this->logger->info('IP address throttled because it reached the attempts limit in the last 12 hours [action: {action}, attempts: {attempts}, ip: {ip}]', [
'action' => $action,
'ip' => $ip,
- 'delay' => $delay,
+ 'attempts' => $attempts,
]);
}
- if (!$this->config->getSystemValueBool('auth.bruteforce.protection.testing')) {
- usleep($delay * 1000);
+
+ if ($attempts > 0) {
+ return $this->calculateDelay($attempts);
}
- return $delay;
+
+ return 0;
}
}
diff --git a/lib/private/Security/Hasher.php b/lib/private/Security/Hasher.php
index ba661f5a356..722fdab902f 100644
--- a/lib/private/Security/Hasher.php
+++ b/lib/private/Security/Hasher.php
@@ -106,8 +106,8 @@ class Hasher implements IHasher {
// Verify whether it matches a legacy PHPass or SHA1 string
$hashLength = \strlen($hash);
- if (($hashLength === 60 && password_verify($message . $this->legacySalt, $hash)) ||
- ($hashLength === 40 && hash_equals($hash, sha1($message)))) {
+ if (($hashLength === 60 && password_verify($message . $this->legacySalt, $hash))
+ || ($hashLength === 40 && hash_equals($hash, sha1($message)))) {
$newHash = $this->hash($message);
return true;
}
@@ -115,8 +115,8 @@ class Hasher implements IHasher {
// Verify whether it matches a legacy PHPass or SHA1 string
// Retry with empty passwordsalt for cases where it was not set
$hashLength = \strlen($hash);
- if (($hashLength === 60 && password_verify($message, $hash)) ||
- ($hashLength === 40 && hash_equals($hash, sha1($message)))) {
+ if (($hashLength === 60 && password_verify($message, $hash))
+ || ($hashLength === 40 && hash_equals($hash, sha1($message)))) {
$newHash = $this->hash($message);
return true;
}
diff --git a/lib/private/Security/RateLimiting/Limiter.php b/lib/private/Security/RateLimiting/Limiter.php
index b7ac26d9132..316becfa009 100644
--- a/lib/private/Security/RateLimiting/Limiter.php
+++ b/lib/private/Security/RateLimiting/Limiter.php
@@ -13,10 +13,12 @@ use OC\Security\RateLimiting\Backend\IBackend;
use OC\Security\RateLimiting\Exception\RateLimitExceededException;
use OCP\IUser;
use OCP\Security\RateLimiting\ILimiter;
+use Psr\Log\LoggerInterface;
class Limiter implements ILimiter {
public function __construct(
private IBackend $backend,
+ private LoggerInterface $logger,
) {
}
@@ -32,6 +34,11 @@ class Limiter implements ILimiter {
): void {
$existingAttempts = $this->backend->getAttempts($methodIdentifier, $userIdentifier);
if ($existingAttempts >= $limit) {
+ $this->logger->info('Request blocked because it exceeds the rate limit [method: {method}, limit: {limit}, period: {period}]', [
+ 'method' => $methodIdentifier,
+ 'limit' => $limit,
+ 'period' => $period,
+ ]);
throw new RateLimitExceededException();
}
diff --git a/lib/private/Security/Signature/Model/SignedRequest.php b/lib/private/Security/Signature/Model/SignedRequest.php
index f30935e83b1..12a43f32bcc 100644
--- a/lib/private/Security/Signature/Model/SignedRequest.php
+++ b/lib/private/Security/Signature/Model/SignedRequest.php
@@ -74,8 +74,8 @@ class SignedRequest implements ISignedRequest, JsonSerializable {
*/
public function getDigest(): string {
if ($this->digest === '') {
- $this->digest = $this->digestAlgorithm->value . '=' .
- base64_encode(hash($this->digestAlgorithm->getHashingAlgorithm(), $this->body, true));
+ $this->digest = $this->digestAlgorithm->value . '='
+ . base64_encode(hash($this->digestAlgorithm->getHashingAlgorithm(), $this->body, true));
}
return $this->digest;
}
diff --git a/lib/private/Security/VerificationToken/VerificationToken.php b/lib/private/Security/VerificationToken/VerificationToken.php
index 1995b482597..89f45180359 100644
--- a/lib/private/Security/VerificationToken/VerificationToken.php
+++ b/lib/private/Security/VerificationToken/VerificationToken.php
@@ -85,9 +85,9 @@ class VerificationToken implements IVerificationToken {
): string {
$token = $this->secureRandom->generate(
21,
- ISecureRandom::CHAR_DIGITS .
- ISecureRandom::CHAR_LOWER .
- ISecureRandom::CHAR_UPPER
+ ISecureRandom::CHAR_DIGITS
+ . ISecureRandom::CHAR_LOWER
+ . ISecureRandom::CHAR_UPPER
);
$tokenValue = $this->timeFactory->getTime() . ':' . $token;
$encryptedValue = $this->crypto->encrypt($tokenValue, $passwordPrefix . $this->config->getSystemValueString('secret'));