Web App assessments are probably one of the most popular penetration tests performed today. These are so popular that public bug bounty sites such as Hacker One and Bug Crowd offer hundreds of programs for companies wanting to fix vulnerabilities such as XSS, SQL Injection, CSRF, etc. Many companies also host their own bounty programs for reporting web vulnerabilities to a security team. Follow us in our 4-part mini series of blog posts about web security:
In a continuation of our portal protections series, we’ll be discussing some of the methods that attacker’s can use to discover valid usernames on your applications. If you don’t think that the ability to discover valid usernames is a security concern, please read the article linked above (Login Portal Security 101). Almost every web application has the following three pages/functionality on their site, so we’ll be discussing how each of them can be used to discover valid usernames:
- Login Submissions
- Account Registration
- Password Reset/Password Retrieval
Attackers who use this method need to be careful because excessively attacking primary login portals usually causes account lockouts and can also trigger automated security protections like IP blacklisting. The upside for an attacker performing username discovery through login submissions is that sometimes they get lucky and guess the user’s password on the first try. When using this method, the simplest attempt of “password” has worked to log us in on more occasions than I’d care to admit. Surprisingly, it has even worked to log us in to applications that are (currently) using strong password enforcement policies because the affected user account created their password prior to the enforcement of strong passwords and hasn’t logged in since.
Blatantly Obvious Server Responses
Some of the applications we test suffer from the malady of being helpful to their users rather than being secure. In this example, the server lets the user to know whether their username, or password, was incorrect so that it’s easier for them to fix. This instantly gives the attacker a very easy method of discovering valid usernames because the server will tell them when the username is correct.
Account Lockout Server Responses
Some login portals take a little more work to obtain a valid username. If the application has implemented an account lockout security mechanism, an attacker can submit the same username multiple times and eventually receive a message stating that the user’s account has been locked.
This method of username enumeration is probably the second least preferred method (just behind the password reset method) for white-hat pentesters because it locks out all of the discovered accounts. If the application has implemented a temporary account lockout duration, this can practically be used during the middle of the night, say 2am, because (in theory) the accounts should automatically unlock the before users wake up.
The number of failed submissions prior to lockout varies from application to application, but is usually between 3 and 5. If an attacker submits a username like “thisusernamedoesnotexist12345” five times and gets the same “Your login information was invalid” server response message on the fifth attempt, but submitting a username like “jsmith” five times eventually results in a server response message that says “Your account has been locked, please check back in 20 minutes”, the attacker once again can confirm the validity of the username based upon the server response variations.
The first 4 login attempts with the username “itweb112” results in a server response that says “Your login information was invalid”
The fifth login attempt with the username “itweb112” results in a server response that says “Your account has been locked. Please check back in 20 minutes.”
Server Response Times
This method of username discovery is fairly tricky to perform and isn’t always an exact science, but we’ve tested several applications that are vulnerable to it. Basically, we analyze the time that it takes the server to respond to each login (or authentication) request. For a server vulnerable to this type of username discovery, the server response times will be split into two (or even three) very distinct lengths.
The screenshot below shows burp intruder being used to test an application using basic authentication for access to the requested page. The requested username is in the column labeled “comment” and is being base64 encoded with the password “password” and submitted as the payload in each request. The server’s response content was always the same (“length” column), but the time it took the server to respond to each request varied significantly (“Response completed” column). All of the usernames that resulted in a server response of more than 1070 milliseconds were invalid usernames, while all of the usernames that resulted in a server response of less than 600 milliseconds were identified as being valid usernames. Most of the valid usernames resulted in response times of less than 100 milliseconds, but there were also a small number of accounts that took between 300 and 600 milliseconds to respond. These were later identified as being administrative accounts with elevated privileges on the site, a great bonus for any website enumeration.
These response time variations are usually caused by server-side logic that is performed when a valid username is submitted, but not performed when an invalid username is submitted (or visa-versa).
Think of database queries that you’re performing on a some usernames that you’re not performing on others and make sure that the time it takes to perform these extra functions isn’t revealing usernames to attackers. While this might sound like heresy to some of you speed/efficiency gurus out there, you can also add random variations in your response times by making the code sleep for a randomized amount of time before responding to requests that check the validity of usernames.
For applications that use open enrollment, and even some that use closed enrollment, the registration form can be used to discover valid usernames and/or registered email addresses.
In some cases, as soon as a user enters their desired username, a request will be sent that validates it isn’t already taken before a user proceeds to sign their life away. Repeat that request pattern and we have our discovery point, easy enough. This configuration makes it simple for an attacker, but is pretty common in web applications today. Here is a real world example:
The first step in the registration process asks the user to choose a username for their new account. If the username is being used by an existing account, the application will helpfully tell the user that they need to choose a different one.
The request for a username that isn’t already in use returns
Burp Intruder being used to automate the submission of different usernames to discover which ones are currently in use on the application
email@example.com [Account Created]
username=david&email=bad [Username Taken = No account creation]
username=james&email=bad [Username is valid, but E-Mail is invalid = No account creation]
This can get complicated when you start to consider that parameter validation can occur in different orders on the server side, but should work in most cases. This would also be a great time to verify that client-side validation isn’t the only thing preventing an attacker from abusing the form 😉
CAPTCHAs should be required on the registration request that checks for existing username conflicts. CAPTCHAs help prevent an attacker from automating the username discovery process, but you need to watch out for a few common issues when implementing them. We discuss some common CAPTCHA issues in our post: Captchas Done Right?
Password Reset/Password Retrieval
Okay, this one is almost always the least preferred method of username discovery because usually the site will send out a password reset email to the user’s email address on file. This notifies the user that someone other than themselves has discovered their username/email and is attempting to reset their password. This can put the user on high-alert and they may potentially notify the application’s security team that someone has attempted a password reset on their account.
However, not all applications send out an email to the user when they request a password reset. Some sites will have the user answer their security questions and allow them to reset their password as soon as their security questions are answered correctly. These types of applications are good to use for username discovery because the user is never notified, and sometimes you can guess the answers to their security questions more easily than you can guess their password.
Here’s an example of an application that uses the user’s security question to reset their password instead of sending out an account reset email to the user. Notice that the application immediately notifies the user when they enter a username that’s not in use:
When they enter an existing username, the application proceeds to a second page that prompts the user to verify their identity:
Once again, CAPTCHAs should be required on password reset requests. CAPTCHAs help prevent an attacker from automating the username discovery process, but you need to watch out for a few common issues when implementing them. We discuss some common CAPTCHA issues in our post: Captchas Done Right?
Okay, where do the usernames come from?
Each of these attack vectors require a predefined list of usernames to test with, so now you’re wondering where to get them. You can obtain lists of usernames either by:
- Performing Open-source intelligence (OSINT) or
- Generating them
OSINT username gathering usually requires more work on the part of the attacker, but there are actually many automated methods of doing this research as well. Here are a couple of scripts you can use to gather up emails and possible usernames for a specific company:
- Lee Baird’s Discover script: https://github.com/leebaird/discover
- A Linkedin scraper I wrote and host here: https://github.com/wpentester/Linkedin_profiles
Brute-force guessing usernames takes a while, makes lots of noise in logs, and is generally less sophisticated than getting valid usernames through OSINT; however, brute-forcing is sometimes the only option and can often yield more results than targeted username discovery. Portswigger’s Burp Suite Free Edition has a pretty awesome extension called C02 that can be used to generate potential username lists for you using census data.
Adding the CO2 extension in Burp
Using the CO2 extension in Burp to generate username lists
All of these methods of discovering usernames are performed in an unauthenticated context on an application. There are also various ways to perform username discovery once you are authenticated into the application, but it is usually less risky to perform username discovery outside of an authenticated session. If you’re still questioning whether username discovery is a security concern, please read our original post on portal protections.
Interested in whether or not your portal is secure? Fill out the request form at the top of this page, or contact us at (801) 855-6599 for a quote on getting your application tested.