Skip to content
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

Closed
wants to merge 17 commits into from

Conversation

james-d-elliott
Copy link
Member

@james-d-elliott james-d-elliott commented May 4, 2020

Will close #949 if merged.

  1. On startup:
  2. If file provider: hash a randomly generated password of 20 characters with the hash password settings, we time this, plus add a random interval of time between 150-200ms. If this delay isn't above 450ms we randomly assign it a value from the next step. This is handled in FirstFactorPost() which now returns a func with the values calculated prior to that.
  3. Otherwise: set the startup delay to 450-500ms.
  4. When the post comes in we record the time we received it. After the authentication passes or fails, we check the authentication attempt will not be returned early and if it would be, we sleep until it should be returned.

TODO:

  • figure out why the tests failed when not disabling the delay and fix it, it's likely this is causing other issues
  • design some tests for this
  • documentation

@authelia
Copy link

authelia bot commented May 4, 2020

Artifacts

These changes are published for testing on Buildkite and DockerHub.

Docker Container

  • docker pull authelia/authelia:security-delay-1fa-logins

* add config item to disable (for tests)
* 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
…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
nightah added a commit that referenced this pull request May 5, 2020
The outstanding recommendations are due to be addressed in #959 and #971 respectively.
@nightah nightah mentioned this pull request May 5, 2020
@@ -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
Copy link
Member

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}", "")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea!

internal/authentication/password_hash.go Show resolved Hide resolved
@@ -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"`
Copy link
Member

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.

nightah added a commit that referenced this pull request May 6, 2020
* [CI] Add gocritic linter

* Implement gocritic recommendations
The outstanding recommendations are due to be addressed in #959 and #971 respectively.

* Fix implementation tests

* Fix remaining linting issues.

* Fix tests.

Co-authored-by: Clément Michaud <clement.michaud34@gmail.com>
…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
internal/handlers/handler_firstfactor.go Show resolved Hide resolved
internal/handlers/handler_firstfactor.go Show resolved Hide resolved
internal/handlers/handler_firstfactor.go Show resolved Hide resolved
internal/handlers/handler_firstfactor.go Show resolved Hide resolved
internal/handlers/handler_firstfactor.go Show resolved Hide resolved
internal/authentication/password_hash.go Show resolved Hide resolved
internal/authentication/password_hash.go Show resolved Hide resolved
internal/authentication/password_hash.go Show resolved Hide resolved
internal/authentication/password_hash.go Show resolved Hide resolved
internal/authentication/password_hash.go Show resolved Hide resolved
else
if [ -z "$GOPATH" ] ; then
export GOPATH=$(go env GOPATH)
else
Copy link
Member

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
Copy link
Member

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))
Copy link
Member

@clems4ever clems4ever May 6, 2020

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
Copy link
Member

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 {
Copy link
Member

@clems4ever clems4ever May 6, 2020

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 {
Copy link
Member

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.

@nightah nightah deleted the security-delay-1fa-logins branch May 21, 2020 02:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[FIXED v4.19] User enumeration of file-based backend based on timing attack
4 participants