LDAP user can reset password using secondary email and login using direct authentication
Even when password authentication is enabled, we do not allow direct/local password authentication for LDAP users.
There are two main mechanisms that (should) ensure this:
- Upon creation, LDAP users are given a max-length (255 character) randomly generated password.
- On sign in and password reset, in addition to checking the global
password_authentication_enabled_for_web?
setting, we also haveUser#allow_password_authentication?
which checks whether a user is an LDAP user, and if yes, disallow password authentication.
Turns out we only validate the second part before sending a password reset email for an LDAP user. If a user only has a primary email address, no problem. However, if a user enters a secondary email we fall back to only looking at the global setting. Thus a password reset email may be sent to an LDAP user if they have a confirmed secondary email. See https://gitlab.com/gitlab-org/gitlab/-/blob/a9c1e816424ade8b79a7df80d1a103f42dce2c96/app/controllers/passwords_controller.rb#L59.
Once the password reset email is sent, there's no further check to ensure password authentication is enabled for the user before allowing the reset to occur. Similarly, on sign in we only check the global setting not User#allow_password_authentication
.
This vulnerability is mitigated if https://docs.gitlab.com/ee/administration/settings/sign_in_restrictions.html#password-authentication-enabled is disabled.
In addition to all of this, we should not be passing the email
param directly to the finder method. In this case I don't think it's actually a security issue, but for safety we should .to_s
this param to ensure we're only looking up a user by a single email address.