Avoid revealing whether login or password was in error

176 views
Skip to first unread message

Bo Jeanes

unread,
Aug 26, 2020, 4:13:07 AM8/26/20
to Rodauth
Hello,

In Rodauth's login forms (or perhaps just rodauth-rails?), a failed login will reveal whether it was the password or the login/email which was incorrect.

This would allow a potential attacker or cred stuffer to determine whether a specific user had an account on the site, which is a pretty big issue for our project in particular.

I can customise this error message, but I don't know if it is possible (and if it is, how) to remove the field_error for this field. I'd rather just have the flash message saying that the combined credentials were not a match.

Am I missing something that would allow me to do this today?

I can override the form templates for login and not use the general field renderer for those two fields, but I'd be weary of a future developer re-consolidating the templates in a refactor and missing this subtlety.

Cheers,
Bo

Bo Jeanes

unread,
Aug 26, 2020, 4:17:46 AM8/26/20
to Rodauth
Ah I'd like to add that the password reset request form (and I imagine the verify account re-send form) also has this issue of revealing whether or not an account exists in the system.

Ideally, this would be a unilateral configuration option to mask this leakage on all forms and in all messages. I believe this would be a common requirement for others...

Jeremy Evans

unread,
Aug 26, 2020, 10:42:53 AM8/26/20
to Rodauth
On Wednesday, August 26, 2020 at 1:17:46 AM UTC-7, Bo Jeanes wrote:
Ah I'd like to add that the password reset request form (and I imagine the verify account re-send form) also has this issue of revealing whether or not an account exists in the system.

Ideally, this would be a unilateral configuration option to mask this leakage on all forms and in all messages. I believe this would be a common requirement for others...

In general, it's a fools errand to try to hide if it is a login or password problem.  Even if you make the UI the same for all possible cases, it is very likely there is trivial timing attack that will allow an attacker to tell the difference.  Additionally, showing whether the issue is a missing login or a wrong password is a huge win for usability. Also, environments that need to support multiple authentication methods for logging in require you input the login before figuring out which authentication methods are appropriate for it.  For these reasons, Rodauth by design does not offer a configuration method to hide whether the problem is login or password based.  You would have to override all templates that have a login field.

Thanks,
Jeremy

Bo Jeanes

unread,
Aug 26, 2020, 7:37:25 PM8/26/20
to Rodauth
Thanks for your response,

I don't suppose there is anyway to persuade you that this should be an option? Are you opposed to it in principle or it just hasn't been a priority.

In my case, the site is of a sensitive nature and it is an absolute necessity that this information is not so trivially leaked. I agree that timing attacks can reveal this information anyway but these are not the only type of attacker to be concerned with.

For instance, a hypothetical situation (adjacent example to mine, but not the same), is a website which provides resources to victims of ongoing domestic abuse. It is a very different thing for an average Joe (say the partner of this victim, in my hypothetical) to check if their victim is using the site than it is for an advanced attacker trying to gain access to sensitive information. Not revealing information in the login and password reset forms makes an immense difference to the users of that site in protecting their safety from people in their actual lives. That aspect of the scenario is relevant to my specific use-case, where our customers are regularly the targets of doxxing and harassment.

Cheers,
Bo

Jeremy Evans

unread,
Aug 26, 2020, 10:51:16 PM8/26/20
to Rodauth
On Wednesday, August 26, 2020 at 4:37:25 PM UTC-7, Bo Jeanes wrote:
Thanks for your response,

I don't suppose there is anyway to persuade you that this should be an option? Are you opposed to it in principle or it just hasn't been a priority.

My point is that every other authentication that tries to do this fails to do it correctly (e.g. be timing attack resistant) in all cases, so the main security difference between Rodauth and other authentication systems is that Rodauth does not give you a false sense of security.  It's extremely difficult to do this correctly in all cases, and for the vast majority of applications using Rodauth, it shouldn't matter as the default Rodauth behavior makes more sense.

In my case, the site is of a sensitive nature and it is an absolute necessity that this information is not so trivially leaked. I agree that timing attacks can reveal this information anyway but these are not the only type of attacker to be concerned with. 
 
For instance, a hypothetical situation (adjacent example to mine, but not the same), is a website which provides resources to victims of ongoing domestic abuse. It is a very different thing for an average Joe (say the partner of this victim, in my hypothetical) to check if their victim is using the site than it is for an advanced attacker trying to gain access to sensitive information. Not revealing information in the login and password reset forms makes an immense difference to the users of that site in protecting their safety from people in their actual lives. That aspect of the scenario is relevant to my specific use-case, where our customers are regularly the targets of doxxing and harassment. 

I can appreciate this use case.  FWIW, users that care about this should be using custom email addresses not tied to any online identity, but that's an unrealistic expectation for the average user.

Your current best bet is to override Rodauth's templates and use the existing configuration methods to make sure the same messages are used in both cases.

I think one possible way to solve this so you could avoid overriding the templates would be to introduce a configuration method for the parameter name to use for the field error if the password is incorrect (this would default to the password parameter).  Then you could set that to the login parameter, and use the existing configuration method for the incorrect password message to be generic.  I would be open to such a pull request.

Thanks,
Jeremy

Bo Jeanes

unread,
Aug 26, 2020, 11:13:11 PM8/26/20
to rod...@googlegroups.com
My point is that every other authentication that tries to do this fails to do it correctly (e.g. be timing attack resistant) in all cases, so the main security difference between Rodauth and other authentication systems is that Rodauth does not give you a false sense of security.  It's extremely difficult to do this correctly in all cases, and for the vast majority of applications using Rodauth, it shouldn't matter as the default Rodauth behavior makes more sense.

I very much agree that the majority of solutions (esp in Ruby) are not resistant to timing attacks. As my point below attempts to show, hiding this information is still useful in protecting online accounts from other types of attackers. There will always be a more sophisticated attacker than any system is hardened against, but any software can still make a best effort to reduce the pool of eligible attackers.

I sincerely agree that this needs to be documented and messaged correctly so as to minimise the false sense of security, though. That is indisputably true.

I can appreciate this use case.  FWIW, users that care about this should be using custom email addresses not tied to any online identity, but that's an unrealistic expectation for the average user.

Agreed. And agreed. However in the case I am dealing with (not domestic abuse, but still at risk people) that expectation does not hold as the email address they would use on this service would often necessarily be one that the would-be abuser knows about.

Your current best bet is to override Rodauth's templates and use the existing configuration methods to make sure the same messages are used in both cases.

Yeah, this is what I had planned pending these discussions, so I'll continue down that route.

I think one possible way to solve this so you could avoid overriding the templates would be to introduce a configuration method for the parameter name to use for the field error if the password is incorrect (this would default to the password parameter).  Then you could set that to the login parameter, and use the existing configuration method for the incorrect password message to be generic.  I would be open to such a pull request.

That's certainly an interesting idea. It could be used by integrators like myself who wish to obscure the failure mode without the risk you are weary about of over-promising on the security front.

Thanks. I will likely go the template route for now, but since I am writing a few `features` for this integration (Yubikey TOTP, Devise migration "feature", a CAPTCHA on login (from certain IPs) feature, and a haveibeenpwned.com password check feature), I may prototype that idea in that way and see where it leads.

This does make me wonder if you could point me in the direction of an externally-implemented Rodauth feature which you see as robustly tested, should one exist, so that I might study it to eventually make some of these features I'll work on publicly available for others? I think the HIBP password check is a natural extension of the existing "common" passwords check and might be useful to others, as would the Yubikey TOTP (as an alternative to the existing TOTP and Webauthn features).

Thanks as always for your responsiveness!

Cheers,
Bo

Bo Jeanes

unread,
Aug 27, 2020, 2:28:02 AM8/27/20
to rod...@googlegroups.com
I think one possible way to solve this so you could avoid overriding the templates would be to introduce a configuration method for the parameter name to use for the field error if the password is incorrect (this would default to the password parameter).  Then you could set that to the login parameter, and use the existing configuration method for the incorrect password message to be generic.  I would be open to such a pull request.

The following configuration has mostly got me the behaviour I am looking for (there are probably a few other forms to address):

    # Do our best to mask whether or not an account exists
    reset_password_request_error_flash do
      set_notice_flash reset_password_email_sent_notice_flash
      redirect reset_password_email_sent_redirect
    end

    no_matching_login_message do
      nil # this will avoid marking that field as an error
    end

    invalid_password_message do
      if logged_in?
        super # for logged in users, notifying of an invalid password is fine
      else
        nil # this will avoid marking that field as an error
      end
    end

It's definitely on the hacky side, what with setting flash and redirecting inside a value method...

Jeremy Evans

unread,
Aug 27, 2020, 11:58:18 AM8/27/20
to Rodauth
On Wednesday, August 26, 2020 at 8:13:11 PM UTC-7, Bo Jeanes wrote:
I think one possible way to solve this so you could avoid overriding the templates would be to introduce a configuration method for the parameter name to use for the field error if the password is incorrect (this would default to the password parameter).  Then you could set that to the login parameter, and use the existing configuration method for the incorrect password message to be generic.  I would be open to such a pull request.

That's certainly an interesting idea. It could be used by integrators like myself who wish to obscure the failure mode without the risk you are weary about of over-promising on the security front.

Thanks. I will likely go the template route for now, but since I am writing a few `features` for this integration (Yubikey TOTP, Devise migration "feature", a CAPTCHA on login (from certain IPs) feature, and a haveibeenpwned.com password check feature), I may prototype that idea in that way and see where it leads.

Janko recently release the rodauth-pwned gem, so you can probably use that instead of writing one yourself: https://github.com/janko/rodauth-pwned

This does make me wonder if you could point me in the direction of an externally-implemented Rodauth feature which you see as robustly tested, should one exist, so that I might study it to eventually make some of these features I'll work on publicly available for others? I think the HIBP password check is a natural extension of the existing "common" passwords check and might be useful to others, as would the Yubikey TOTP (as an alternative to the existing TOTP and Webauthn features).

I haven't reviewed any of the external Rodauth gems.  However, they are functionally the same as the features that ship with Rodauth itself (by design).  So looking at the features that ship with Rodauth should give you ample examples.  All of the features that ship with Rodauth are robustly tested (100% line and branch coverage).

I thought of another approach with current Rodauth for doing what you want without overriding the templates, and that is using the *_view configuration methods, modifying the field errors, and calling super:

login_view do
  if field_error(login_param)
    set_field_error(login_param, nil)
    set_field_error(password_param, invalid_password_message)
  end
  super()
end

Thanks,
Jeremy

Bo Jeanes

unread,
Aug 27, 2020, 5:07:37 PM8/27/20
to rod...@googlegroups.com
Janko recently release the rodauth-pwned gem, so you can probably use that instead of writing one yourself: https://github.com/janko/rodauth-pwned

Oh perfect!

This does make me wonder if you could point me in the direction of an externally-implemented Rodauth feature which you see as robustly tested, should one exist, so that I might study it to eventually make some of these features I'll work on publicly available for others? I think the HIBP password check is a natural extension of the existing "common" passwords check and might be useful to others, as would the Yubikey TOTP (as an alternative to the existing TOTP and Webauthn features).

I haven't reviewed any of the external Rodauth gems.  However, they are functionally the same as the features that ship with Rodauth itself (by design).  So looking at the features that ship with Rodauth should give you ample examples.  All of the features that ship with Rodauth are robustly tested (100% line and branch coverage).

Ack

I thought of another approach with current Rodauth for doing what you want without overriding the templates, and that is using the *_view configuration methods, modifying the field errors, and calling super:

login_view do
  if field_error(login_param)
    set_field_error(login_param, nil)
    set_field_error(password_param, invalid_password_message)
  end
  super()
end

Ah this is nice. Thanks.
Reply all
Reply to author
Forward
0 new messages