Email enumeration vulnerability on "Password Reset" dialogue

OWASP Vulnerability ID: WSTG-IDNT-04

Reproduction steps:

  1. Try using a bad email on the “forgot my email” dialogue:
    2023_07_31_23_59_10_Install_Discourse_on_Synology_directly_installation_Discourse_Meta_Brave
  2. Try using a good email on the “forgot my email” dialogue:

Vulnerability description (from OWASP):

  • It is possible to collect a set of valid usernames by interacting with the authentication mechanism of the application. This test will be useful for brute force testing, in which the tester verifies if, given a valid username, it is possible to find the corresponding password.

  • Often, web applications reveal when a username exists on system, either as a consequence of mis-configuration or as a design decision. For example, sometimes, when we submit wrong credentials, we receive a message that states that either the username is present on the system or the provided password is wrong. The information obtained can be used by an attacker to gain a list of users on system. This information can be used to attack the web application, for example, through a brute force or default username and password attack.

Suggested fix:

  1. The “forgot my email” dialogue should behave the same whether the email is good or bad.

We do have the hide email address taken admin setting which does change the behaviour of that screen:

Perhaps it would be good to have that as a default? :thinking:

9 Likes

Enable Admin - Settings - Login - hide email address taken

hide email address taken

Don’t inform users that an account exists with a given email address during signup or during forgot password flow. Require full email for ‘forgotten password’ requests.

See also Different password reset for wrong username/email (2014 :wink: )

Edit @JammyDodger was 40 seconds faster

7 Likes

Having a read around, this has cropped up a few times before. I think one of the other important points is that we have rate-limiting on trying to log in:

3 Likes

Thanks to you both. I bumped into this bug organically on meta.discourse.org and didn’t know about that setting, but it is good to know that the fix is already coded and the patch should be very straightforward. In order to satisfy OWASP best practices, that setting should always be enabled. I do not know why any administrator would wish to have this disabled, as doing so represents a totally unnecessary security and privacy vulnerability that explicitly violates industry best practice standards. If there is some reason to preserve this option for legacy installations which I cannot fathom, then a warning should be added to indicate that the current configuration violates industry standard best practices and recommending the compliant configuration instead.

2 Likes

Thanks for linking this thread. @awesomerobot is entitled to their opinion, but they are also brazenly defying the industry standard best practices and insisting that a well-known, oft-reported and explicitly codified bug is somehow “not a bug”, and I don’t find their opinion to be very convincing compared to published industry standard best practices.

If nothing else the default value should reflect the more-safe configuration, and there should be some indication to tell novice administrators that disabling this option constitutes a deliberate and unnecessary security and privacy vulnerability on their forum. A link to the OWASP entry or something.

Can someone clue me into the scenario when it might be preferable to have this option disabled? I genuinely do not know why this is a contentious issue and would like to know if I am missing some use-case that obviates the opt-in security model being implemented with this setting. If such a scenario cannot be suggested, then this setting should always be enabled and therefore shouldn’t be a setting at all.

1 Like

I think, currently, everything is working as expected so we can’t truly class this as a bug. However, we do routinely re-evaluate our defaults and you’ve made some interesting points that are worth considering.

I’ll slide this over to ux so the conversation can continue there. :+1:

11 Likes

Simply… people are bad at remembering which email address they used to create an account, and will contact admins to troubleshoot.

This is similar to enforce second factor or min password length — I think the general recommendation is to always require a second factor, and password minimum length recommendations now seem to be higher than our current default for regular users… but there’s also a gap between security recommendations and average computer skills.

I’m not strongly against changing the defaults, but it’s worth noting that they can impact usability.

10 Likes

This does seem to me like Discourse defaults should follow best practices - like almost every other site does.

It looks like I have the appropriate setting set on my instance:

If an account matches x@example.com, you should receive an email with instructions on how to reset your password shortly.

3 Likes

I like this feedback, but I would prefer if was backed up a bit more data:

What do the following sites do?

  • Facebook
  • Twitter
  • Amazon
  • Reddit
  • Yahoo
3 Likes

Thank you all for your valuable input and perspectives on this bug. For me, this is very straightforward and not complicated at all: there’s a well-known bug present in Discourse which has been repeatedly surfaced by administrators and security professionals like myself, and it is being treated as a feature instead of as a security vulnerability: NIST: CWE-200: Exposure of Senitive Information to an Unauthorized Actor.

Justifying this unsafe default configuration that is in violation of industry standard best practices by citing a hypothetical situation where a forum administrator is inundated with user inquiries about which emails they used for sign-up doesn’t make sense as using the ‘forgot my password’ page would not necessitate this administrator interaction regardless of the configuration of this setting: if the more secure and standards compliant setting is enabled then the user would simply check their email(s) on the forgot my email dialogue and see whether or not that address received a password reset email, exactly as explained by the dialogue, and as is common across all modern, privacy-respecting, standards compliant web apps. Further, justifying this violation based on the premise that other sites might also be violating best practices is not a logical or compelling argument from a security and data protection perspective. I struggle to understand why we are giving administrators the ‘feature’ of making their Discourse installation marginally less secure and standards compliant for no clear benefit.

Nevertheless, I’ve done the work you’ve prescribed @sam:
‌1. Google: does not allow user enumeration.
2. YouTube: does not allow user enumeration (because it uses Google login, and Google doesn’t allow user enumeration).
3. Facebook: officially allows user enumeration via their ‘find an account’/‘forgot my password’ page only if the user has deliberately marked their email/phone number as public, and yet has famously leaked 500M users’ data through this type of vulnerability, and has paid out thousands of dollars to security auditors who have found that their rate limiting and ‘only if explicitly marked as public’ rules were not being followed internally.
4. Instagram: allows user enumeration (and got burned because of it). This is a different hack than the one I mentioned for Facebook.
5. X (please be respectful about dead-naming on this forum): allows user enumeration via their forgot password page, but implements rate limiting and a few other easily circumvented hurdles and still famously compromised their users’ phone numbers through an bug in their implementation of rate limiting and data privacy protections.
6. Baidu: allows user enumeration on forgot email page, and implements captcha (and maybe rate limiting? My chinese is bad). Interestingly, the recovery process requires opening an appeal with the administration team, rather than a simple recovery email. Very typical of CCP central control.
7. Wikipedia: does not allow user enumeration.
8. Yahoo: Allows user enumeration via their forgot password page, but implements rate limiting and captcha. I could not find examples of Yahoo getting caught in controversy or paying out hackers who exploit this bug, but it is really hard to search for Yahoo on any search engine for obvious reasons.
9. Yandex: allows user enumeration on login page, implements captcha and challenge question on forgot email page.
10. Whatsapp: does not allow user enumeration. PC login is via mobile credentials. Mobile credentials are bound to your phone number. There is no logout button, nor a login page/forgot my email page.
11. XVideos: does not allow user enumeration.
12. PornHub: does not allow user enumeration.
13. Amazon (e-commerce site): allows user enumeration via their forgot password page, in direct violation of their own best practices recommendations for Amazon Web Services’ Cognito user pools product. I could not find examples of Amazon getting caught in controversy or paying out hackers who exploit this bug, but it is really hard to search for Amazon on any search engine for obvious reasons.
14. Xnxx: does not allow user enumeration. The main site doesn’t really have a login page, and the ‘gold’ site doesn’t allow user enumeration. I found a defunct login page on the mobile version of the regular site, and it simply doesn’t have ‘forgot my email’ functionality at all (and is also apparently defunct, in favor of their ‘gold’ website).
15. Tik Tok: does not allow user enumeration. Enforces MFA on forgot password page.
(21. Reddit: Does not allow user enumeration. They are compliant with industry standard best practices.)

Of the top 15 sites on that list, 8/15 DO NOT allow user enumeration (or 9/16 if you include Reddit, and arguably add 0.5 for Facebook since it is only allowing enumeration of information the user deliberately approved making public), and at least 3/7 of the sites from that list that DO allow user enumeration have faced critical security events as a result of that decision.

2 Likes

This is somewhat disingenuous as the arguably main Google product (gmail) allows enumeration.

It’s otherwise trivial to test for the existence of accounts on email identity providers, so there’s not much point in even including them in the list.

None of the other platforms in that list are (potentially) self-hosted software.

There is no Central Discourse Platform - site administrators are free to choose for themselves.

That said I would agree with giving a nudge to site admins to choose good settings by default.

Maybe a knob admins can turn (I hesitate to suggest adding this to the wizard) to tighten down settings like this easily.

4 Likes

Doesn’t that apply to any site with a sign-up page, not just email service providers? I can see your point about how sign-up pages are a potential vector for similar privacy and data vulnerabilities and therefore must be protected, but that’s a different part of the user authentication flow than we are discussing in this topic. In this topic, we are specifically looking at leaks from the “forgot my password” dialogue. Don’t get me wrong: both are absolutely important, demand careful attention, and require mitigations in order to prevent privacy and data vulnerabilites. Usually for sign-up forms you require a captcha, and for ‘forgot my password’ endpoints you want to have the same response regardless of whether the email is good or bad. Many sites also secure the ‘forgot my password’ endpoint with a captcha. Both endpoints should be rate-limited.

I certainly wasn’t trying to be disingenuous. I don’t think that its okay to be non-compliant because some other sites are also non-compliant is a logically sound conclusion anyway, I was just fulfilling Sam’s request and to ease any concerns he may have by fulfilling the ‘proof’ he sought using the link he provided.

The MediaWiki software is used by tens of thousands of websites and thousands of companies and organizations. It powers Wikipedia and is very much self-hosted software.

I certainly encourage administrator freedom, and I don’t like making the lives of administrators or users more difficult, but I don’t think that the ‘pros’ of this setting outweigh the ‘cons’ in any scenario, and there’s no case where an administrator would actually WANT this ‘feature’. Just as we don’t allow an administrator to enforce a maximum password length, we shouldn’t allow them to unnecessarily marginally degrade their forum’s security by allowing this enumeration vulnerability on the forgot my password dialogue. I think we should just remove the option entirely and force everyone to follow the standards compliant way. I honestly don’t think most administrators would notice or care, but it would make a public-internet facing endpoint somewhat safer on all Discourse installs. If we must include the setting, then it should be in the more-safe position by default, and the less-safe position should be clearly demarcated so that novice administrators understand why it is not recommended. I think that simply refactoring this setting out of existence is the best option though. I’d be happy to submit a PR for that.

1 Like

I don’t think you can look at either in a vacuum. In Discourse’s signup process there is an “Email has already been taken” message and it’s hard to see how to to that differently. For as long as that exists, it’s hard to see what the big problem is with the “We found an account that matches” message specifically.

I suppose it would make a difference in a forum only allowing external authentication.

Having got over the urge to disagree with you just because of your style, I think on the substance you are right to the extent that your position is that the default should be the more secure option, at least when external authentication is used. I still don’t agree that there is no place for the less secure option (my forum has Discourse’s default signup process so I don’t plan to change the reset password option).

Incidentally, I laughed at the fact that you left the reader to guess from context that XVideos and Xnxx (though not X) are pornographic, but took the trouble to explain that Amazon is an “e-commerce site”.

1 Like

It was to distinguish Amazon.com from AWS. And since you asked: AWS doesn’t allow user enumeration. :slightly_smiling_face:

I agree that you must consider all steps of a user authentication flow and how they work together. That’s extremely important and one of the most common sources of security vulnerabilities. If that similar email enumeration bug on the sign-up page that you’ve mentioned isn’t properly mitigated then that should absolutely be patched regardless of the outcome of this topic. It would be a bug with the implementation of hide_email_address_taken. Discussion of that potential bug/oversight should probably take place in a different topic though (and probably with a bug tag).

1 Like

Just to note, with hide email address taken enabled it doesn’t give that message on sign-up either (it also changes the invite message as well when an existing email is input there). :+1:

I think one of the possible complications for just flipping the default is that it also has the ‘require full email for password reset’ built-in, which may overcomplicate things (though is likely not a complete blocker).

2 Likes

Thanks. I likely will change the setting then. I think something in this topic gave me the wrong impression.

What does this one mean? Does it mean you can’t get a password reset with username only?

1 Like

That’s the one. :+1: With hide email address taken enabled you need to enter the account email itself for the password reset, and can’t just use a username.

1 Like

I suggest that we rename the hide_email_address_taken SiteSetting so that it is instead prevent_password_recovery_by_username, and then we refactor the non-compliant behavior out of the app for all users. This would preserve the password reset functionality without change for all installs while also addressing the email enumeration vulnerability. I’m a skilled RoR + javascript developer and would be happy to implement this pull request; I’ve taken a quick look through the codebase and can see that it would not be a hugely sprawling PR.

If refactoring this ‘feature’ out of existence is really not in the cards, then I still think it makes sense to decouple these two related concepts into separate SiteSetting entries.

1 Like
1 Like