-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SECURITY] Enable Delay for First Factor Post #971
Conversation
ArtifactsThese changes are published for testing on Buildkite and DockerHub. Docker Container
|
* add config item to disable (for tests)
cd05dba
to
1a10e92
Compare
* check for '{CRYPT}' prefix on load instead of during a password check * return const error instead * remove temporary username enumeration measures * fix tests for both the enumeration checks and crypt prefix adjustments * move salt checks to their own function * move argon2id checks to their own function
d5c9bd6
to
695e38d
Compare
…logins # Conflicts: # config.template.yml # go.mod # internal/authentication/ldap_user_provider.go # internal/configuration/schema/authentication.go # internal/configuration/validator/const.go # internal/handlers/handler_firstfactor.go # internal/handlers/handler_firstfactor_test.go
@@ -79,6 +79,10 @@ authentication_backend: | |||
# Disable both the HTML element and the API for reset password functionality | |||
disable_reset_password: false | |||
|
|||
# Disable delaying authentication to prevent username enumeration. | |||
# Enabling this could allow attackers to find valid usernames. It's highly discouraged to change this to true. | |||
disable_delay_auth: false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure we really want to leave the option to admins.
} | ||
} | ||
|
||
func checkPasswordHashes(database *DatabaseModel) error { | ||
for u, v := range database.Users { | ||
v.HashedPassword = strings.ReplaceAll(v.HashedPassword, "{CRYPT}", "") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good idea!
@@ -35,6 +35,7 @@ type PasswordConfiguration struct { | |||
// AuthenticationBackendConfiguration represents the configuration related to the authentication backend. | |||
type AuthenticationBackendConfiguration struct { | |||
DisableResetPassword bool `mapstructure:"disable_reset_password"` | |||
DisableDelayAuth bool `mapstructure:"disable_delay_auth"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I said, I think we don't want to leave admins with a gun and let them shoot in their feet.
…logins # Conflicts: # internal/authentication/file_user_provider.go # internal/authentication/password_hash.go # internal/handlers/handler_firstfactor.go # internal/suites/http.go # internal/suites/scenario_backend_protection_test.go
d3f325b
to
acb9d27
Compare
else | ||
if [ -z "$GOPATH" ] ; then | ||
export GOPATH=$(go env GOPATH) | ||
else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This else can just be dropped.
@@ -20,24 +20,29 @@ fi | |||
if [[ $(id -g) = 0 ]]; then | |||
echo "Cannot run as root, defaulting to GID 1000" | |||
export GROUP_ID=1000 | |||
elif [[ $(uname) == "Darwin" ]]; then | |||
elif [[ $(uname) == "Darwin" ]] ; then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we change this to not normalise for Darwin and instead spit an error suggesting that the Development workflow does not work for macOS?
algorithm, config.File.Password.Iterations, | ||
config.File.Password.Memory*1024, config.File.Password.Parallelism, | ||
config.File.Password.KeyLength, config.File.Password.SaltLength) | ||
duration = time.Since(start) + (time.Duration(rand.Int31n(50) + 150)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the random number should be computed on each request to randomize the delay otherwise it would not bring any value imo, we can just remove it.
} | ||
|
||
if duration < 450*time.Millisecond { | ||
duration = time.Duration(rand.Intn(50)+450) * time.Millisecond |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same thing as above, the random number should be generated at each request.
// Automatically grow to the largest detected successful login. | ||
if successful { | ||
delay := time.Since(receivedTime) | ||
if delay > *duration { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
duration will never decrease back after an incident in which latency has raised drastically. It increases security overtime but decreases user experience though.
duration = time.Since(start) + (time.Duration(rand.Int31n(50) + 150)) | ||
} | ||
|
||
if duration < 450*time.Millisecond { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem I see with the constant at 450ms is that if the app network is overloaded for instance the latencies of LDAP queries will increase and therefore there will be no delay anymore. If there is no delay the mitigation does not work anymore. It's pretty much the same issue as in my proposal with the threshold being exceeded.
Will close #949 if merged.
TODO: