fix: prevent error reason leakage in case of IgnoreUnknownUsernames (#8372)

# Which Problems Are Solved

ZITADEL administrators can enable a setting called "Ignoring unknown
usernames" which helps mitigate attacks that try to guess/enumerate
usernames. If enabled, ZITADEL will show the password prompt even if the
user doesn't exist and report "Username or Password invalid".
Due to a implementation change to prevent deadlocks calling the
database, the flag would not be correctly respected in all cases and an
attacker would gain information if an account exist within ZITADEL,
since the error message shows "object not found" instead of the generic
error message.

# How the Problems Are Solved

- Proper check of the error using an error function / type and
`errors.Is`

# Additional Changes

None.

# Additional Context

- raised in a support request

Co-authored-by: Silvan <silvan.reusser@gmail.com>
This commit is contained in:
Livio Spring
2024-07-31 14:23:57 +02:00
committed by GitHub
parent 189505c80f
commit a1d24353db
6 changed files with 207 additions and 22 deletions

View File

@@ -16,8 +16,8 @@ const (
userTable = "auth.users3"
)
func (v *View) UserByID(userID, instanceID string) (*model.UserView, error) {
return view.UserByID(v.Db, userTable, userID, instanceID)
func (v *View) UserByID(ctx context.Context, userID, instanceID string) (*model.UserView, error) {
return view.UserByID(ctx, v.Db, userID, instanceID)
}
func (v *View) UserByLoginName(ctx context.Context, loginName, instanceID string) (*model.UserView, error) {
@@ -27,7 +27,7 @@ func (v *View) UserByLoginName(ctx context.Context, loginName, instanceID string
}
//nolint: contextcheck // no lint was added because refactor would change too much code
return view.UserByID(v.Db, userTable, queriedUser.ID, instanceID)
return view.UserByID(ctx, v.Db, queriedUser.ID, instanceID)
}
func (v *View) UserByLoginNameAndResourceOwner(ctx context.Context, loginName, resourceOwner, instanceID string) (*model.UserView, error) {
@@ -37,7 +37,7 @@ func (v *View) UserByLoginNameAndResourceOwner(ctx context.Context, loginName, r
}
//nolint: contextcheck // no lint was added because refactor would change too much code
user, err := view.UserByID(v.Db, userTable, queriedUser.ID, instanceID)
user, err := view.UserByID(ctx, v.Db, queriedUser.ID, instanceID)
if err != nil {
return nil, err
}
@@ -103,7 +103,7 @@ func (v *View) userByID(ctx context.Context, instanceID string, queries ...query
OnError(err).
Errorf("could not get current sequence for userByID")
user, err := view.UserByID(v.Db, userTable, queriedUser.ID, instanceID)
user, err := view.UserByID(ctx, v.Db, queriedUser.ID, instanceID)
if err != nil && !zerrors.IsNotFound(err) {
return nil, err
}