Throughout our assessments, we get the opportunity to work with a wide variety of clients and see a ton of different web applications. When performing web application penetration testing in particular, there are a number of issues that we notice over and over again, regardless of the development language, application architecture, etc. If we see these types of patterns, we like to write about them to help spread some awareness to the issues and open some dialog to hopefully reduce the prevalence of these types of thematic problems over time. One of those issues, is username enumeration.
Why Should We Care?
Yes, I know this isn’t a super critical or sexy vulnerability that results in remote code execution. But it is an easily avoidable problem that can lead to an attacker gaining unauthorized access to an application. When targeting an application during any type of penetration test (external, web app, internal, etc.), we need to know at least two things to gain access: a username and a password.
Potential usernames are easy enough to find using open source intelligence techniques. Through tools like TheHarvester, which comes pre-installed on Kali Linux distributions, the format of email addresses can be scraped from Google/Bing searches. Many times, username formats are going to match email formats for the simplicity of users. Then if we know the format, custom scripts can be used to scrape employee names from LinkedIn and craft customer user lists using the most common first names/last names (thanks SecLists!). So if it’s so easy to gather this information, why do we care about username enumeration, smart guy?
The answer is because of the way password attacks work online. Simply put, they are slow. So if I have to run a password spraying attack against 40,000 potential users, a single run could take a long time (e.g. over 24 hours). This slows down the attack considerably, meaning an attacker has to be much more dedicated to spend this amount of time on a single target and their chances of getting caught are increased because of sheer traffic volume. This is where username enumeration comes in. If a target is vulnerable to username enumeration, a single run can be used to determine the validity of usernames, whittling down the list of potential users exponentially. This decreases time and traffic required to execute the attack while increasing chances of success.
What is Username Enumeration?
Username enumeration is the ability to confirm the existence of a potential username based on differences in responses from a target application. This can be error messages displayed through the GUI, differences in response codes (200 vs. 401/403/500), differences in response length due to hidden parameters, or even differences in response time (a la Microsoft OWA). And this issue doesn’t just affect the login form. Many times, forgot password functionality or new user registration functionality will contain username enumeration vulnerabilities as well. On a forgot password submission, anything besides a generic success message (e.g. “If this username exists in our records, you will receive instructions to reset your password to your registered email address in the next 5 minutes.”) can be used by an attacker to automatically harvest valid users. On new user registration forms, if a user can select their own username or has to put in a unique email address, error messages can disclose valid usernames.
Preventing These Issues
The first and easiest solution is to prevent these kind of weaknesses are to make sure you and your developers are using consistent HTTP responses with the same error messages. If a natural timing delay is occurring because of your authentication process, time can be added to pad quicker responses in order to make every response consistent.
Beyond the obvious solutions, there are several mitigating controls that can help reduce the effectiveness of exploits on username enumeration vulnerabilities or the subsequent password attacks, including:
- Strong Password Policy
- CAPTCHAs to prevent automated exploitation
- Support for MFA so successful username enumeration has less of an impact
- IP blacklisting based on number of unsuccessful login events during a period of time
- Increased monitoring/alerting on exposed login interfaces