I recently wrote a post on enumerating valid usernames in web applications, and the next logical step for an attacker is to then take those valid usernames and attempt to use them in other attacks, such as password guessing. Given enough time, and lacking security mechanisms and monitoring, you can guess username/password combinations and eventually access a system (that does not use MFA).
Unfortunately, there are usually security mechanisms preventing you from continuously guessing, and it is often some sort of account lockout mechanism. Let’s face it, these account lockout mechanisms can really be annoying. But every once in a while, you can bypass the mechanism and guess passwords without having to worry about getting locked out.
Here are 5 methods/tests I use to bypass account lockout mechanisms in web applications:
- Look for client-side counters
Applications try to keep track of the number of failed login attempts for user accounts. Many times this is done with a counter variable. For each failed login attempt, the counter is incremented by one. If the counter reaches a threshold, the account will be locked. On rare occasions, the developer may make this counter variable accessible to the client side. It may be some seemingly innocuous parameter. For example, an authentication attempt POST request may look like this:
POST /login HTTP/1.1 Host: example.com Cookie: token=6707C79012b3ba4c10967d9348a97355b3298 c=0&username=jmiller&password=August2018!!&submit=submit
The username and password parameters were non-hidden form fields, however the hidden c parameter was also submitted with a value 0. This attempt failed, and the server updated the hidden c value to 1, so the next login attempt looked like:
POST /login HTTP/1.1 Host: example.com Cookie: token=6707C79012b3ba4c10967d9348a97355b3298 c=1&username=jmiller&password=August2018!&submit=submit
For this application, if the c parameter incremented above 2, then the user account was locked out, but since this variable could be controlled on the client side, the account lockout could be bypassed by setting the value of c to 0 or 1 while continuing to cycle through different passwords.
- Delete your session cookie
When you navigate to an application the server will often set a cookie prior to authentication, and then issue a new cookie when successfully authenticated. Sometimes any invalid login attempt tracking will be scoped to the initial, unauth cookie. In these cases, you can continually submit requests without the cookie header, allowing you to avoid account lockout.
- Try using Basic Authentication
Many commercial web applications use form base auth as well as some form of header based authentication such as Basic Auth. It is typical that if form based auth is in use, then Basic Auth will be disabled, however that is not always the case. A simple test is to add an Authorization header to your HTTP requests. If you receive an abnormal response, it may be trying to validate the credentials.
For example, consider the following request and response:
POST /login HTTP/1.1 Host: otherexample.com Cookie: id=NTQ0NTVmM2IxMmIxZGM0YzE0OTY3ZDkzNDhhNDczYTU2MzJkNA== username=jmiller&password=August2018!&submit=submit
HTTP/1.1 302 Found Location: /login
Normal behavior for this web application is to redirect you to the login page on a failed login. Now consider how the application responds when the Authorization header is added:
GET /login HTTP/1.1 Host: otherexample.com Authorization: Basic am1pbGxlcjpBdWd1c3QyMDE4IQ==
HTTP/1.1 401 Unauthorized
This indicates that the server is likely evaluating the Basic Auth credentials. In these situations, I have never seen Basic Auth be associated with an account lockout mechanism, so guessing credentials via Basic Auth will bypass the form-based lockout.
- Look for other places that evaluate credentials
In sites that have registration, password changes, or multi-step logins, there might be an opportunity to test authentication outside of the normal login form. For example:
A site had password reset functionality, but prior to changing their password they needed to enter their current password:
After you entered your old password, the site sent an AJAX request with your username and password to the server, to verify if the password was correct (the creds were also sent via GET, which was also bad). If incorrect, an error message would be written:
If correct, an empty response was given:
While the main login page enforced an account lockout, guessing passwords through the password change module allowed me to avoid account lockout.
- Keep trying even if locked out
Many applications that have an account lockout mechanism do not display any error message to a user to let them know they are locked out of their account. In some instances, though, the application will display a different response when a user successfully authenticates with a locked-out account. For example, the CA Identity Manager previously suffered from this problem (CVE-2017-9393):
A failed login attempt, even when the user account is locked out, would display to the user the following:
However, when the correct credentials were entered the application responds with an error message telling the user they are locked out:
Authentication is one of my favorite things to attack, and it is common to find a way to bypass the account lockout mechanism. Vulnerabilities scanners do a poor job at identifying these flaws, so don’t be surprised if you run into a flawed lockout system. While these are not the only ways to bypass account lockout, hopefully you these methods will be useful to you in future testing or development.