From cced87da7f36ce6d2e57eef06f1126ef8ef72e0a Mon Sep 17 00:00:00 2001 From: dakkar Date: Fri, 12 Jul 2024 11:15:58 +0100 Subject: [PATCH] rate limit all password checks - fixes #540 all of these endpoints require the caller to already be logged in, so it's not really much of a security problem, but it's still safer to limit any endpoints that can be used to guess the current password --- .../backend/src/server/api/endpoints/i/2fa/key-done.ts | 7 +++++++ .../backend/src/server/api/endpoints/i/2fa/register-key.ts | 7 +++++++ .../backend/src/server/api/endpoints/i/2fa/register.ts | 7 +++++++ .../backend/src/server/api/endpoints/i/2fa/remove-key.ts | 7 +++++++ .../backend/src/server/api/endpoints/i/2fa/unregister.ts | 7 +++++++ .../backend/src/server/api/endpoints/i/change-password.ts | 7 +++++++ .../backend/src/server/api/endpoints/i/delete-account.ts | 7 +++++++ .../backend/src/server/api/endpoints/i/regenerate-token.ts | 7 +++++++ 8 files changed, 56 insertions(+) diff --git a/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts b/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts index a4e61a0e8f..084d4af658 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts @@ -14,12 +14,19 @@ import type { UserProfilesRepository, UserSecurityKeysRepository } from '@/model import { WebAuthnService } from '@/core/WebAuthnService.js'; import { ApiError } from '@/server/api/error.js'; import { UserAuthService } from '@/core/UserAuthService.js'; +import ms from 'ms'; export const meta = { requireCredential: true, secure: true, + limit: { + duration: ms('1hour'), + max: 10, + minInterval: ms('1sec'), + }, + errors: { incorrectPassword: { message: 'Incorrect password.', diff --git a/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts b/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts index cc6e9ee42d..6ab50a57c9 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts @@ -12,12 +12,19 @@ import { DI } from '@/di-symbols.js'; import { WebAuthnService } from '@/core/WebAuthnService.js'; import { ApiError } from '@/server/api/error.js'; import { UserAuthService } from '@/core/UserAuthService.js'; +import ms from 'ms'; export const meta = { requireCredential: true, secure: true, + limit: { + duration: ms('1hour'), + max: 10, + minInterval: ms('1sec'), + }, + errors: { userNotFound: { message: 'User not found.', diff --git a/packages/backend/src/server/api/endpoints/i/2fa/register.ts b/packages/backend/src/server/api/endpoints/i/2fa/register.ts index 7283159f87..888d0fc6ef 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/register.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/register.ts @@ -14,12 +14,19 @@ import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; import { ApiError } from '@/server/api/error.js'; import { UserAuthService } from '@/core/UserAuthService.js'; +import ms from 'ms'; export const meta = { requireCredential: true, secure: true, + limit: { + duration: ms('1hour'), + max: 10, + minInterval: ms('1sec'), + }, + errors: { incorrectPassword: { message: 'Incorrect password.', diff --git a/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts b/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts index 098fd59303..614fd0c498 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts @@ -13,10 +13,17 @@ import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '@/server/api/error.js'; import { UserAuthService } from '@/core/UserAuthService.js'; +import ms from 'ms'; export const meta = { requireCredential: true, + limit: { + duration: ms('1hour'), + max: 10, + minInterval: ms('1sec'), + }, + secure: true, errors: { diff --git a/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts b/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts index 8da331505b..2773825373 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts @@ -13,12 +13,19 @@ import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '@/server/api/error.js'; import { UserAuthService } from '@/core/UserAuthService.js'; +import ms from 'ms'; export const meta = { requireCredential: true, secure: true, + limit: { + duration: ms('1hour'), + max: 10, + minInterval: ms('1sec'), + }, + errors: { incorrectPassword: { message: 'Incorrect password.', diff --git a/packages/backend/src/server/api/endpoints/i/change-password.ts b/packages/backend/src/server/api/endpoints/i/change-password.ts index 6aedde717c..f131c7e9d1 100644 --- a/packages/backend/src/server/api/endpoints/i/change-password.ts +++ b/packages/backend/src/server/api/endpoints/i/change-password.ts @@ -10,10 +10,17 @@ import { Endpoint } from '@/server/api/endpoint-base.js'; import type { UserProfilesRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { UserAuthService } from '@/core/UserAuthService.js'; +import ms from 'ms'; export const meta = { requireCredential: true, + limit: { + duration: ms('1hour'), + max: 10, + minInterval: ms('1sec'), + }, + secure: true, } as const; diff --git a/packages/backend/src/server/api/endpoints/i/delete-account.ts b/packages/backend/src/server/api/endpoints/i/delete-account.ts index af4d601ad6..565eaaafc0 100644 --- a/packages/backend/src/server/api/endpoints/i/delete-account.ts +++ b/packages/backend/src/server/api/endpoints/i/delete-account.ts @@ -11,10 +11,17 @@ import { Endpoint } from '@/server/api/endpoint-base.js'; import { DeleteAccountService } from '@/core/DeleteAccountService.js'; import { DI } from '@/di-symbols.js'; import { UserAuthService } from '@/core/UserAuthService.js'; +import ms from 'ms'; export const meta = { requireCredential: true, + limit: { + duration: ms('1hour'), + max: 10, + minInterval: ms('1sec'), + }, + secure: true, } as const; diff --git a/packages/backend/src/server/api/endpoints/i/regenerate-token.ts b/packages/backend/src/server/api/endpoints/i/regenerate-token.ts index e1cdfdc185..814ffb5488 100644 --- a/packages/backend/src/server/api/endpoints/i/regenerate-token.ts +++ b/packages/backend/src/server/api/endpoints/i/regenerate-token.ts @@ -11,10 +11,17 @@ import type { UsersRepository, UserProfilesRepository } from '@/models/_.js'; import generateUserToken from '@/misc/generate-native-user-token.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; +import ms from 'ms'; export const meta = { requireCredential: true, + limit: { + duration: ms('1hour'), + max: 10, + minInterval: ms('1sec'), + }, + secure: true, } as const;