1
0
mirror of https://github.com/bitwarden/server.git synced 2024-12-27 17:47:37 +01:00

[Captcha] BUG Add null checks | Make ceiling default to zero (#1903)

* [Captcha] BUG Add null checks | Make ceiling default to zero

* Formatting
This commit is contained in:
Vincent Salucci 2022-03-09 12:07:06 -06:00 committed by GitHub
parent 7620433d7e
commit 7046aecfd5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 15 additions and 10 deletions

View File

@ -515,7 +515,7 @@ namespace Bit.Core.IdentityServer
private async Task ResetFailedAuthDetailsAsync(User user) private async Task ResetFailedAuthDetailsAsync(User user)
{ {
// Early escape if db hit not necessary // Early escape if db hit not necessary
if (user.FailedLoginCount == 0) if (user == null || user.FailedLoginCount == 0)
{ {
return; return;
} }
@ -527,6 +527,11 @@ namespace Bit.Core.IdentityServer
private async Task UpdateFailedAuthDetailsAsync(User user, bool twoFactorInvalid, bool unknownDevice) private async Task UpdateFailedAuthDetailsAsync(User user, bool twoFactorInvalid, bool unknownDevice)
{ {
if (user == null)
{
return;
}
var utcNow = DateTime.UtcNow; var utcNow = DateTime.UtcNow;
user.FailedLoginCount = ++user.FailedLoginCount; user.FailedLoginCount = ++user.FailedLoginCount;
user.LastFailedLoginDate = user.RevisionDate = utcNow; user.LastFailedLoginDate = user.RevisionDate = utcNow;

View File

@ -62,7 +62,7 @@ namespace Bit.Core.IdentityServer
string bypassToken = null; string bypassToken = null;
var user = await _userManager.FindByEmailAsync(context.UserName.ToLowerInvariant()); var user = await _userManager.FindByEmailAsync(context.UserName.ToLowerInvariant());
var unknownDevice = !await KnownDeviceAsync(user, context.Request); var unknownDevice = !await KnownDeviceAsync(user, context.Request);
if (unknownDevice && _captchaValidationService.RequireCaptchaValidation(_currentContext, user.FailedLoginCount)) if (unknownDevice && _captchaValidationService.RequireCaptchaValidation(_currentContext, user?.FailedLoginCount ?? 0))
{ {
var captchaResponse = context.Request.Raw["captchaResponse"]?.ToString(); var captchaResponse = context.Request.Raw["captchaResponse"]?.ToString();

View File

@ -8,7 +8,7 @@ namespace Bit.Core.Services
{ {
string SiteKey { get; } string SiteKey { get; }
string SiteKeyResponseKeyName { get; } string SiteKeyResponseKeyName { get; }
bool RequireCaptchaValidation(ICurrentContext currentContext, int? failedLoginCount = null); bool RequireCaptchaValidation(ICurrentContext currentContext, int failedLoginCount = 0);
Task<bool> ValidateCaptchaResponseAsync(string captchResponse, string clientIpAddress); Task<bool> ValidateCaptchaResponseAsync(string captchResponse, string clientIpAddress);
string GenerateCaptchaBypassToken(User user); string GenerateCaptchaBypassToken(User user);
bool ValidateCaptchaBypassToken(string encryptedToken, User user); bool ValidateCaptchaBypassToken(string encryptedToken, User user);

View File

@ -83,17 +83,17 @@ namespace Bit.Core.Services
return root.GetProperty("success").GetBoolean(); return root.GetProperty("success").GetBoolean();
} }
public bool RequireCaptchaValidation(ICurrentContext currentContext, int? failedLoginCount = null) public bool RequireCaptchaValidation(ICurrentContext currentContext, int failedLoginCount = 0)
{ {
var failedLoginCeiling = _globalSettings.Captcha.MaximumFailedLoginAttempts.GetValueOrDefault(); var failedLoginCeiling = _globalSettings.Captcha.MaximumFailedLoginAttempts;
return currentContext.IsBot || return currentContext.IsBot ||
_globalSettings.Captcha.ForceCaptchaRequired || _globalSettings.Captcha.ForceCaptchaRequired ||
failedLoginCeiling > 0 && failedLoginCount.GetValueOrDefault() >= failedLoginCeiling; failedLoginCeiling > 0 && failedLoginCount >= failedLoginCeiling;
} }
public bool ValidateFailedAuthEmailConditions(bool unknownDevice, int failedLoginCount) public bool ValidateFailedAuthEmailConditions(bool unknownDevice, int failedLoginCount)
{ {
var failedLoginCeiling = _globalSettings.Captcha.MaximumFailedLoginAttempts.GetValueOrDefault(); var failedLoginCeiling = _globalSettings.Captcha.MaximumFailedLoginAttempts;
return unknownDevice && failedLoginCeiling > 0 && failedLoginCount == failedLoginCeiling; return unknownDevice && failedLoginCeiling > 0 && failedLoginCount == failedLoginCeiling;
} }

View File

@ -8,7 +8,7 @@ namespace Bit.Core.Services
{ {
public string SiteKeyResponseKeyName => null; public string SiteKeyResponseKeyName => null;
public string SiteKey => null; public string SiteKey => null;
public bool RequireCaptchaValidation(ICurrentContext currentContext, int? failedLoginCount) => false; public bool RequireCaptchaValidation(ICurrentContext currentContext, int failedLoginCount = 0) => false;
public bool ValidateFailedAuthEmailConditions(bool unknownDevice, int failedLoginCount) => false; public bool ValidateFailedAuthEmailConditions(bool unknownDevice, int failedLoginCount) => false;
public string GenerateCaptchaBypassToken(User user) => ""; public string GenerateCaptchaBypassToken(User user) => "";
public bool ValidateCaptchaBypassToken(string encryptedToken, User user) => false; public bool ValidateCaptchaBypassToken(string encryptedToken, User user) => false;

View File

@ -463,7 +463,7 @@ namespace Bit.Core.Settings
public bool ForceCaptchaRequired { get; set; } = false; public bool ForceCaptchaRequired { get; set; } = false;
public string HCaptchaSecretKey { get; set; } public string HCaptchaSecretKey { get; set; }
public string HCaptchaSiteKey { get; set; } public string HCaptchaSiteKey { get; set; }
public int? MaximumFailedLoginAttempts { get; set; } public int MaximumFailedLoginAttempts { get; set; }
} }
public class StripeSettings public class StripeSettings

View File

@ -15,7 +15,7 @@
"internalSso": null "internalSso": null
}, },
"captcha": { "captcha": {
"maximumFailedLoginAttempts": null "maximumFailedLoginAttempts": 0
} }
} }
} }