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:

  1. Login Submissions
  2. Account Registration
  3. Password Reset/Password Retrieval

Login Submissions

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.

Best Practices

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.

Account Registration

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

Single Step

In other cases, the entire registration request may need to be submitted first before the site will indicate a re-use situation. This is a problem for testing, as we don’t want to be creating tons of accounts when the username isn’t already taken. To get around this, most registration forms implement some type of validation on the form elements to prevent someone from registering without a valid email address syntax, first or last name, phone number etc. These validation controls are usually implemented both on the client-side in JavaScript, and on the server-side in the back-end code. Client side validation can be trivially bypassed through manual request modification, then the trick is to identify the validation being performed on the server-side and submit requests that will prevent an actual account registration request from being accepted, but will allow you to determine whether a requested username or email address is already registered in the application. For an example, let’s say a web application needs a username and email to register. For a valid request, the E-Mail address must have an ‘@’ sign in it. Here is how we might brute-force safely without accidental account creation:

Valid Request

username=david&email=dvahn@email.com    [Account Created]

Brute Force

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 

Best Practices

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:

Best Practices

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:

  1. Performing Open-source intelligence (OSINT) or
  2. 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:

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 bottom of this page.


Login Portal Security 101

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:

To begin, let’s start with some abstract thinking. When we think about attempts to discover web vulnerabilities, we like to think about attack surface. If you are looking for needles in haystacks, it helps if you have access to all of the hay first. This brings us to a common functionality that puts lots of needles in off-limit haystacks:


While vulnerabilities can be classified many different ways, for the purposes of this post let’s use the following two:

Unauthenticated – The vulnerability can be actively exploited without first needing to login or authenticate to the affected application. In other words, “public” areas of the web site/service.

Authenticated – An authenticated state is required for exploitation of the vulnerability.  This could come in the form of a username:password, logon token, session cookie, etc.

Normally, through the nature of “more functionality = more flaws”, most vulnerabilities for web applications are authenticated. Some vulnerabilities fall into one of these categories by definition, such as a cross-site request forgery (CSRF) or authentication bypass; but even these vulnerabilities are usually only found with an authenticated context in the first place. Unfortunately when we think about authentication, we commonly associate it with trust. A “hacker” isn’t one of your customers. They don’t login, or use profile pictures, or file uploads, or that hidden query form you built for a good friend. They don’t have a username/password, and you wouldn’t give them one anyways; all they do is break stuff. So if most of my vulnerabilities are only found/exploited by an authenticated user, how can an attacker gain authorized access into my application? This depends on whether the application has open registration or closed registration.


Open registration means that anyone can sign up for a free account (yay, we’re in!) and closed registration means that a user must either be registered by someone else or register using a predefined set of information in order to gain authorized access.

Open Registration

If your application uses an open registration model, an attacker can create a free account and start testing in an authenticated context immediately. We recently tested an application that had a host of high-risk vulnerabilities (including SQL injection) that couldn’t be identified by an unauthenticated user but were exploitable by a user with a free trial account.

Open registration applications should implement an authorization scheme by assigning registered users a low-privileged user “role” that has limited access to the site’s content. User roles are great, but you have to ensure that everything in your application abides by the security controls enforced in the user’s role. Do NOT try to protect content, functionality, or anything else on the application using what is commonly known as “security through obscurity”, because it usually doesn’t work. We’ll be posting an article or two soon that show how we’ve been able to see through the developer’s attempts at obscuring some pretty serious vulnerabilities.

If you have user roles within your application, this means that you probably have an administrative role that has access to much more of the site’s content than a normal user.  Attackers will try to determine which content they cannot access, and then try to figure out if the content is protected by access controls, or whether they are being protected simply by hiding it from the normal user’s default views. ALWAYS protect sensitive content through access controls instead of by hiding the content from the low-privileged user.

(Paypal.com is an example of an application that uses open registration, “sign up for free”)

Closed Registration

Sweet, my site has closed registration, so that means they have to verify their identity and be pre-registered in our system in order to create an account. This should prevent a lot of attackers from exploiting the vulnerabilities locked behind my login portal…right? Answer: Maybe. If the vast majority of your functionality, and associated vulnerabilities, are only found or exploitable in an authenticated context, then an attacker is going to try to gain authenticated access by the easiest means available. An attacker’s first order of business will be to test your anti-automation protections on the registration, password reset, and login pages. (You have those right?) This is used to determine whether a credential brute-force attack is possible. An attacker will take the path of least resistance when attacking an application, and guessing an existing user’s username and password is frequently much easier than guessing the specific information needed to register a new user’s account, phishing for credentials, or paying for a legitimate account.  If an attacker is able to guess an existing user’s account credentials, they not only get access to that user’s data but also gain anonymity by using the compromised user account to discover and exploit additional vulnerabilities within the application.

(bankofamerica.com is an example of an application using closed registration. It requires an applicant to obtain a Bank of America card or account prior to registration)

So an attacker is going to attempt to enumerate usernames, passwords, and other related information from my website. There are many common protections web developers implement to protect against these attacks, some better than others. let’s go through them and discuss effectiveness.

Common Portal Protections

  1. CAPTCHAs:
  2. Account Lockout
  3. IP blacklisting
  4. IP rate-limiting
  5. Username rate-limiting
  6. Session Control and CSRF embedded tokens
  7. Ambiguous server responses
  8. Strong Password Policy
  9. Dual-Factor Authentication

At the top of each protection section, we’ve provided a simple chart to show whether the type of protection is likely to prevent certain types of attackers from conducting either username discovery, or brute-force login attacks.  Here’s the Legend:

Checkbox Icon

The protection will most likely prevent a successful attack from the specified source.

Error Icon

The protection will most likely NOT prevent a successful attack from the specified source.

Warning Icon

The protection will most likely prevent a successful attack from the specified source, but there are exceptions/bypasses that could make this attack exploitable.

The protection will most likely NOT prevent a successful attack from the specified source and can potentially be used to perform additional attacks against the users or support personnel of the application.


VulnerabilityScannersScript KiddiesAmateursHacktivistsProfessionals
Username Discovery
Brute-Force Login

The chart may make it appear that CAPTCHAs are the silver bullet of portal protection, but everything depends of whether or not the application has implemented CAPTCHAs correctly.  The results of the chart also only apply when ALL aspects of your portal are protected by CAPTCHAs.  I wrote more about proper CAPTCHA implementation in this blog post.

If implemented correctly, an attacker will likely move on to another site that has less protections.

Account Lockout

VulnerabilityScannersScript KiddiesAmateursHacktivistsProfessionals
Username Discovery
Brute-Force Login

A very popular choice in many of the applications we test, but there are a couple of issues that you need to watch out for when implementing account lockouts:

Username Enumeration using account lockout response messages

If the server responds with a message indicating that the account has been locked, an attacker can leverage this to determine valid usernames.  One of the ways to implement account lockouts on an application is to never display an account lockout message to the user, but instead send an account lockout email to the user’s email address on file notifying them that their account has been locked due to excessive login attempts.  The server should still only display the message “Either your username or password was incorrect” when an account has been locked so that the attacker cannot determine if they have guessed a correct username.  The gotcha in this scenario is that you must rate-limit the account lockout emails being sent to the user’s email address or else you might end up sending several thousand lockout emails to your poor user if the attacker is trying several thousand passwords and doesn’t care (or doesn’t check) that the application says that the user’s account has been locked. Also be mindful of response times, if your application provides insight into whether extra actions are being performed for a specific request, this could tip an attacker off. More info about this in a later blog post.

In our opinion, the best protection is to lock out any username that is submitted for login more than 5 times even if the username is not registered in the system. Some of the best applications we test have implemented this protection and it makes it nearly impossible to determine if a username is valid or not.

Denial of Service using account lockout

The larger issue with account lockout protections is that a malicious attacker can cause targeted denial of service attacks against users of the application.  These types of targeted attacks can potentially cause a monetary hit, customer loss, or swamp their support personnel with requests from users.  Let’s discuss the impact on the “availability” of the application when an application enforces different types of account lockout:

Denial of Service against different types of account lockout:

  • Permanent Account Lockout with self-recovery (requires the user to reset their password)
    • An attacker can lockout the user’s account once every X hours forcing a user to reset their account. Brute-Force risk is reduced if the user is able to change their username to a new value unknown to the attacker during the unlock process.
  • Permanent Account Lockout without self-recovery (requires the user to contact a support agent to unlock their account)
    • An attacker can lockout the user’s account once every X hours and because there is no self-service recovery option available to the user, they have to contact a support representative of the company in order to unlock their account.  This could cause a denial of service situation on both the user and the company’s support staff. The impact is worse if the support staff have limited availability (Mon – Fri 8-5), or if they are suddenly swamped with calls from thousands of users who have had their accounts locked.
  • Temporary Account Lockout with self-recovery (1 – 30 minutes)
    • An attacker can lockout the user’s account every X minutes indefinitely to keep the user permanently locked out of their account.
    • The attacker can still guess a few passwords every time the account unlocks.  If it unlocks every 30 minutes, and the application allows 5 attempts before locking the account, an attacker can still try around 240 passwords a day in an attempt to maintain a lock on the account. If a correct password is guessed, the attacker can then access the user’s account and will likely be able to change the user’s password and email address to permanently lock the original owner out of their own account.
    • Risk is reduced if the user is able to reset their own password and unlock their account at the same time, but unless they are given the ability to change their username, an attacker will still be able to keep their account locked and they will be frustrated at needing to constantly reset their password.
  • Temporary Account Lockout without self-recovery (typically 1 – 30 minutes)
    • An attacker can lockout the user’s account every X minutes indefinitely (…)
    • The attacker can still guess a few passwords every time the account unlocks (…)
    • Because there is no self-service recovery option available to the user, they have to contact a support representative of the company in order to unlock their account.  If a company has instituted a temporary account lockout, they may not have the support necessary to unlock the user’s account because they are relying on the “temporary” nature of the account lockout to allow the user eventual access to their account. This situation would likely allow the attacker to maintain a permanent lock on the user’s account and allow them to continue guessing passwords until the the correct password is found.

We can’t write a section like that without showing an example of account lockout gone wrong can we?

Here’s an example of the response we received from a recent assessment when we locked out our test account using incorrect passwords. Notice that the server responds to the login request with an account lockout message and tells us to try again in 20 minutes.  Awesome, this means we know the username is valid, and that the application only locks out the account for 20 minutes.

Wait a minute, immediately after locking the account, we tried the account’s actual password and….received a different response from the server…

Didn’t we just lock the account? Why is the application now saying that our login information is invalid rather than saying that we’ve been locked out?

It turns out that the application only returned a message stating that the account had been locked if you attempted to login using an incorrect password.  If you tried the account’s correct password, the server would respond saying that the login information was invalid. Well, well, well…so even though we’ve locked the account, we can still guess the user’s correct password? Sounds too good to be true! I can lock the user’s account, keep them locked out until I’ve discovered their password, then wait the 20 minutes for the account to unlock and then login as them? Yeah.

Here’s the output from our custom script used to bypass the CSRF protections on the login page and obtain the server’s responses to each login request:

All of the above scenarios require an attacker to be able to identify valid usernames on the application, so that’s why it’s so important that you aren’t giving away usernames for free. Want to know how usernames are discovered? Check out this post: https://silentbreaksecurity.com/username-discovery/

IP Blacklisting

VulnerabilityScannersScript KiddiesAmateursHacktivistsProfessionals
Username Discovery
Brute-Force Login

This is a fun one.  We try to be stealthy, but being blacklisted does occasionally happen during an assessment.  When this happens, a simple program like hidemyass or torguard can switch our IP to another in just a few seconds and we’re right back on track.  Since we’ve been talking about denial of service in this post already, let’s consider the potential problems with IP Blacklisting:

Permanent Blacklisting

If the application permanently blacklists an IP address found to be conducting automated login attempts, a malicious attacker might decide to do some open source research about the company and find out who some of their biggest customers might be, do some more research and find out what IP addresses are used by their customers, and then start spoofing those IP addresses in automated login attempts. End result: the company can potentially blacklist the IPs for some of their biggest customers. This does end up being a blind attack since the IP address is spoofed and won’t ever return to the attacker, but it is a valid theoretical attack vector for targeted denial of service. Alternatively, the attacker could just start sending automated login attempts while spoofing whole IP ranges in the hopes of overloading the security device’s blacklist and cause the site to become inaccessible to large swathes of the internet at a time.

Temporary Blacklisting

If you are implementing IP blacklisting, a temporary enforcement will help prevent the long-term risks of spoofed IP Denial of Service attacks, but unfortunately you won’t be able to prevent a recurring attack from a determined attacker unless you also implement a whitelist for IPs that should never be blocked. In the whitelist scenario, if an attacker is able to gain access to an IP address in the whitelisted range, your blacklisting becomes immediately ineffective.

IP rate-limiting

VulnerabilityScannersScript KiddiesAmateursHacktivistsProfessionals
Username Discovery
Brute-Force Login

We’ve run across several sites that perform rate-limiting on login requests, but this protection is ultimately ineffective. The application may allow only 5 login attempts per minute, but an attacker can easily determine your rate limits and make the login script abide by the application’s rules. There are 1440 minutes in a day, so that means an attacker could attempt 7200 passwords every 24 hours against a single username. However, a competent attacker will be able to bypass the IP restrictions by multi-threading the login script and using multiple proxies to perform automated login requests. By using multiple proxies, an attacker can perform as many requests as they could in a non-rate-limited application. It does add an additional level of complexity for the attacker to circumvent, so it can still be useful when preventing script kiddies and amateur hackers from attacking your application.

Username rate-limiting

VulnerabilityScannersScript KiddiesAmateursHacktivistsProfessionals
Username Discovery
Brute-Force Login

We’ve also seen some applications that don’t rate-limit based upon the login submission’s IP address, but instead rate-limit on the username submitted in the login request. Assuming an attacker just wants access to one of many possible accounts, this can be bypassed by cycling through the hundreds/thousands of usernames and performing login requests in a different loop order:

Typical loop order for credential brute force guessing attacks:

# This sequence tries all of the passwords on a single username before moving on to the next username in the list
for username in usernames: # Switch the username
    for password in passwords:# Switch the password
        login(username, password)

username rate-limited loop order for credential brute force guessing attacks:

# This sequence tries all of the usernames with a single password before moving on to the next password in the list
for password in passwords: # Switch the password
    for username in usernames: # Switch the username 
        login(username, password)

Session Control and CSRF embedded tokens

VulnerabilityScannersScript KiddiesAmateursHacktivistsProfessionals
Username Discovery
Brute-Force Login

Some applications try to prevent automated login attempts by requiring the user to have multiple session cookies in place prior to submitting a login request, or to submit a one-time-use (CSRF) token embedded in the login page. If the submission does not contain the proper session cookie combination/tokens, or is trying to reuse the same session cookie combinations/tokens on multiple login attempts, the application causes the login attempt to fail. The ideology behind this type of protection stems from the flawed notion that automated attacks do not following the “proper” sequence of page loads when submitting a request, but instead will simply repeat the same request over and over again while changing the username/password. That thinking is true for script kiddies and amateurs, but will not prevent a knowledgeable attacker from figuring out your required sequence.

While it can be a PITA for an attacker to figure out the application’s required configuration, this type of protection is just an implementation of “security through obscurity”. If the attacker can determine which sequence of page loads will set the required session cookies, they can simply repeat the required sequence of requests in order to obtain the proper session cookies prior to each submission. Alternatively, they can get the login page and retrieve the one-time-use token embedded therein for the same purpose. This process can slow down an automated credential brute-forcing attack, but proper threading makes “slowing it down” a moot point.

Ambiguous Server Responses

VulnerabilityScannersScript KiddiesAmateursHacktivistsProfessionals
Username Discovery
Brute-Force Login

Server responses should NOT change based upon the validity of the submitted username or email address. If a user attempts to login with the username “jsmith”, but “jsmith” is not a registered username in the application, the server should respond in exactly the same way that it would respond if the user attempted to login with an incorrect password to the registered username of “jasonsmith”. The same goes for server responses on a password reset request, or a “forgot my username” request. Here are examples of some ambiguous server response messages:

  • Login Request:
    • “Invalid credentials”
    • “Username or password was incorrect”
  • Password Reset Request:
    • “If the username/email submitted is registered with our application, a password reset email will be sent to the account’s registered email address shortly”
    • “Check the submitted account’s email address for a password reset email”
  • Forgot username Request:
    • “If the submitted email address is registered in our system, you should receive an email containing your account’s username shortly”
    • “Check your email address for your registered username”

Example of an application that allows an attacker to identify a valid username when logging in:

When implementing ambiguous responses as a security control, you must also ensure that your sever response times are not allowing an attacker to infer valid usernames. See our Username Discovery post to see how server response times can be used to determine valid usernames even with ambiguous server response messages.

Strong Password Policy

VulnerabilityScannersScript KiddiesAmateursHacktivistsProfessionals
Username Discovery
Brute-Force Login

A strong password policy protects yourself just as much as protecting the user from their own stupidity. By allowing users to choose weak passwords, you are opening up an easy means for an attacker to gain authorized access into your application. Many users choose the path of least resistance when it comes to choosing passwords, so requiring them to choose good passwords can help prevent an attacker from gaining access to user’s accounts (and authorized access to your application) by guessing the user’s password of “password”.  Strong password policies will help some users to choose strong passwords, but if their “strong” password ends up being something like “P@ssword123”, then I’m afraid they’re still going to be compromised if other brute-force login preventions are not in place.

Dual-Factor Authentication

VulnerabilityScannersScript KiddiesAmateursHacktivistsProfessionals
Username Discovery
Brute-Force Login

Dual-Factor authentication is becoming more and more popular as a security control on login portals due to their effectiveness in preventing brute-force logins. An application that has implemented dual-factor authentication will prevent an attacker from gaining authenticated access to their application even if they can guess or obtain the user’s username and password.

Some applications perform this secondary check by requiring the user to answer security questions.  You must be careful when using this method because some users choose security questions that are easily discover-able through open source research.  Ensure that your server responses aren’t giving away the answers to these questions:

This application uses security questions as a method of dual-factor authentication, but has no anti-automation controls and also reveals when one question is correctly guessed.

Burp Intruder was used to brute-force guess the user’s security questions.  Notice that the user’s answers become conspicuous when viewing the error messages in the server responses

It is important to implement brute-force automation controls on these secondary auth checks.  We recently conducted an assessment on an application that had implemented a secondary PIN entry for a user’s account when their credentials were guessed correctly. The PIN was 4 digits and did not have any form of anti-automation controls in place for brute-forcing it. There are only 10,000 possible 4-digit combinations, so all of the accounts PINs were guessed in a matter of minutes. Actually, most of the accounts on this particular application were created prior to the dual-factor PIN implementation so when we correctly guessed their password of “password”, the application prompted us to set up the account’s security PIN in order to protect their account from being accessed by an attacker…wow 

Probably the best dual-factor implementation is through token generators (like facebook’s code generator, or authy, or duo, etc) that require the user to input a code generated from an app, or accept a push notification to their mobile device. These types of dual-factor authentication apps make it extremely difficult for an attacker to gain authenticated access to the application, but most companies don’t implement them because it makes the application too difficult to use for the average user.


So which protections are the best? The more the better!

Implement CAPTCHAs, dual factor authentication, strong password policies, ambiguous server responses, session controls, IP blacklisting/rate-limiting, and any other protections discussed here or elsewhere. The best applications we test use a combination of many of these controls to prevent an attacker from discovering usernames, guessing credentials, and brute-forcing any form of dual-factor authentication challenges. Just make sure that you implement these controls correctly. This post has highlighted some of the mistakes that developers can make when implementing these controls, but there are a myriad of other mistakes that can be made when attempting to secure your portal.

Finally, there’s always a trade-off between “ease-of-use” and “security”. Many of these controls are viewed by the marketing/sales teams as “detrimental to our cash-flow” and you’ll have a fight on your hands when you try to implement them. If you need some help convincing the naysayers, or if you’re just curious to see where your application’s security stands, 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.

Discover how the NetSPI BAS solution helps organizations validate the efficacy of existing security controls and understand their Security Posture and Readiness.