Skip to the main content.
Contact
Contact

4 min read

How to protect against username enumeration on log in, registration, and password reset forms

Username enumeration (sometimes called account enumeration) is when it is possible for a hacker to confirm whether a given username is valid for a system. If a malicious actor can gather valid usernames on a platform, they can then use brute force attacks such as credential stuffing or guessing to compromise associated accounts. The collected usernames can also be sold to other spammers and hackers or used in social engineering attacks against the users themselves.

Sometimes, just knowing if an account exists can also be an issue. For example, in an application where a user might want discretion, it could be possible for someone to confirm the existence of an account using their email, since most platforms use emails as usernames. Learning that an email is valid also makes that email account and the accounts registered on other platforms with the same email vulnerable to attacks. Therefore, it is crucial to prevent bots and real users from discovering registered usernames in our applications.

This article will explore ways in which username enumeration occurs and how can we protect the user data on Log In, Registration, and Password Reset forms. We will also see some good and bad examples of how big tech companies are handling these forms.

Our goal is to prevent username enumeration and further misuse of the collected data. We can accomplish this by 1. Carefully crafting our in-app messaging, 2. Designing our user flows with security in mind, and 3. Relying on only the verified means of communication such as private email.

Now let’s discuss some forms.

Log In FormS

What do you imagine a log in form to look like when you close your eyes? Does it have username/email and password fields with a log in button? Does it also have a “Forgot password?” link to help with password recovery? What about a “Register” button to help users create an account? I am guessing most log in forms are a variation of the form below:

EmailHarvest-login

Figure 1 - Basic Log In Form

Based on this form, what kind of error message do you think we should show when someone enters an incorrect password? A fair guess would be to tell the user to enter the correct password. This way, they can quickly correct their mistake. But let’s discuss that a little more with some real-life examples.

EmailHarvest-twitter

Figure 2 - Twitter Log In Form

In the example above, by telling the user to enter a correct password, Twitter is telling them that the username/email they entered is correct, and they can get the password right if they try hard enough. This approach would be okay if everyone visiting Twitter had good intentions, but this is a big win for a malicious actor.

So what should we do when the user enters the wrong password? We should tell the user that their log in credentials are incorrect. There’s no need to specify whether the password or the username/email is wrong.

EmailHarvest-reddit

Figure 3 - Reddit Log In Form

If the user still cannot get the credentials right, they can try resetting their password. If users are unsure if they even have an account, they can try registering instead. Let us explore those two options next.

Password Reset FormS

Alright, so now a user is on the Password Reset page. What should we do when a user enters a registered username/email? Should we take them to the next step in the recovery process? Do we tell them that a password recovery email is waiting in their inbox?

EmailHarvest-SSO

Figure 4 - Notion Password Reset Form

If we take either of those steps, we let the user know that the username/email they entered is valid. We do not want to do that because of the security concerns explained earlier. The best practice, in this case, is to tell the user that an email with further instructions will be sent to them if an account exists.

EmailHarvest-coinbase

Figure 5 - Coinbase Password Reset Form

This way, we do not disclose the information regarding the existence of that username/email in our system. And if we do not have an account with that username/email registered on our platform, we do not send an email.

Okay, so now the log in and password reset forms are protected. Next, let’s discuss how to protect usernames/emails on registration pages.

Registration FormS

What should we NOT do when someone tries to create an account with an already registered username/email? You guessed it; we should NOT tell them, “This username/email already exists. Please log in instead!”

EmailHarvest-trello

Figure 6 - Trello Registration Form

In our registration process, it’s best to confirm the email address before creating an account. This 1. Ensures that we get legitimate email addresses assigned to registered accounts 2. Allows us to help the users via email if an account with that email already exists, and 3. Helps us break down the registration process into easy-to-follow steps, which is proven to improve the user experience.

EmailHarvest-aws

Figure 6 - AWS Registration Form

When an email isn’t registered, we email a verification code to the user. They then enter the code to confirm their identity and move forward in the registration process. If a user is already registered, we inform them about their existing account in the email and add a password reset link in the end in case they need help. 

This way, we give away no information on whether an account exists on our platform and handle the registration securely with ease.

Conclusion

We should never tell the users of our platform that the username/email they entered is valid. It avoids giving feedback that can lead a bad actor down an undesirable path.

There are more things that we should do on top of preventingusername enumeration in order to provide secure environments to our users, such as implementing Multi-factor Authentication, Security Questions, Captcha, Account Lockouts, etc. Hopefully we will get to discuss those in future.

If you enjoyed this article, then please give it some love! I had a great time writing this piece, and your support will motivate me to write even more.

Thank you for reading this one, and make sure to check out the next.

Until then, take care!

Learn More

Control Gap Vulnerability Roundup: August 6th to August 12th

This week saw the publication of 576 new CVE IDs. Of those, 80 have not yet been assigned official CVSS scores, however, of the ones that were,...

Read More

This Week's [in]Security - Issue 280

Welcome to This Week’s [in]Security. PCI FAQs. Crypto-research: the PQC demo derby, more SIDH attacks. New breaches: Twillo, Cisco, Shanghai, ipay88,...

Read More

Control Gap Vulnerability Roundup: July 30th to August 5th

This week saw the publication of 449 new CVE IDs. Of those, 315 have not yet been assigned official CVSS scores, however, of the ones that were,...

Read More