One of the most important parts of a web application is the authentication mechanism, which secures the site and also creates boundaries for each user account. However, during my years of testing web applications, it’s still very common to find authentication mechanisms with vulnerabilities. I currently work as a principal penetration tester on Veracode’s MPT team, and I would say nine out of 10 websites I test have at least one of the following vulnerabilities:
Weak Password Policy
It’s not uncommon to find a website that does not follow a strong password policy. Recently, I tested an application where the minimum length of the password was only five characters long. This vulnerability is very common as developers try to get the balance between security and usability correct.
It’s also not uncommon to find applications that allow end users to set weak passwords, like “password,” “qwerty,” or “1234567,” for example. These types of passwords are well known to attackers and are always found in data leaks where companies have been breached.
Another vulnerability that I have seen, but is less common, is not allowing end users to copy and paste in the password field. This does not really improve security, but hinders it, since it stops people from generating passwords of 15 characters or more.
When I find vulnerabilities like this during a penetration test, I recommend the following:
- Minimum of eight characters
- Alphanumeric characters
- Mixture of upper and lowercase
- Forbid passwords containing username or company name
- Forbid three or more identical characters, e.g., aaa or 111
- Forbid three or more consecutive characters, e.g. abc or 123
- If possible, implement a blacklist, which would stop end users entering weak and common passwords. You could also use the haveibeenpwned API to look for compromised passwords. You can find some examples on the following URL: https://haveibeenpwned.com/API/Consumers
Two-Factor Authentication (2FA)
Another very common vulnerability I come across often with web authentication mechanism is the lack of additional security measures. It’s very rare to see developers implementing two-factor authentication, especially on high-privileged accounts.
There are a number of ways to implement 2FA technology, including RSA tokens, code generators such as Google Authenticator, and Duo and SMS text messaging of one-time codes. Implementing 2FA can also present a number of challenges, especially when “regular” users and “privileged” users both log into the application using the same authentication mechanism. While I would recommend two-factor authentication whenever it is practical, it is difficult to propose across the board for privileged roles. Because there is no industry standard to recommend for applications that mix administrative and non-administrative functions together, a broader design analysis may be needed. Separating administrative functions, such as user-account management, into completely separate applications with stronger authentication schemes is a good goal.
User Enumeration
This vulnerability is usually one of the quickest and easiest vulnerabilities to prevent. It’s mainly due to the error messages being presented back to the end user. If an invalid user attempts to authenticate, the error presented back would be different from that presented to a valid user. An invalid user might be presented with the error “account not found.” As such, a change to the error message will resolve this vulnerability nine times out of 10.
This type of vulnerability can often be found in various places within a web application where a username is required, e.g., login page, forgot password, registration, etc. A good solution for user enumeration vulnerabilities would be to make sure any information presented back to the end user is generic. For example, “if your account was found in our system, you will receive an email shortly.” However, this can be a bit tricky to implement on user registration pages. In these situations, it’s best to provide the new account with a random username.
Resolving user enumeration on account registration is a bit harder. A captcha should be implemented on the page and must be filled out correctly before being able to “Submit” the form. While this does not prevent harvesting altogether, it does defeat automated attacks and limits probing to manual analysis only. An alternative method would be to assign usernames instead of letting users choose them.
Broken Password Reset
This is not that common, but every so often I test a web application that has implemented this functionality in a bad way. This is usually found in the token being used for the reset either being weak or the password being sent to the end user via email.
A common mistake a lot of developers make is thinking that base64 encoding is the same as encryption. As such, they sometimes use this method to encode sensitive data. In password reset functionality, I have seen the token to reset a password using a base64 encoded email address. By decoding this and adding another email address, it was possible to change that end user’s password as long as the account was valid.
Another vulnerability affecting password resets is sending the plaintext password back to the end user. This is bad for a number of reasons, including the fact that the password has been sent via email, which is deemed insecure. This may indicate that the password is being stored in the database without proper salting and hashing or is in a reversible format like base64.
This is less common these days as most frameworks have built-in functions that are tried and tested. However, every so often, you do come across developers that write their own functions to implement password reset functionality. I recommend that if you're using a framework, you use the functionality within that framework. I also recommend that all passwords are stored in a secure manner using a salt and strong hashing algorithm.
Brute Force Attacks
A common attack against authentication pages is a brute force attack. A brute force attack is where an attacker will attempt multiple usernames and passwords until they obtain access to a valid account. This type of attack can be easier to perform if the application has a user enumeration or has a weak password policy. There are a number of free tools that help an attacker perform such an attack and make it relatively easy to do.
I would recommend that you track the number of failed login attempts for a user and mark the account as locked. When the number of consecutive unsuccessful login attempts reaches a reasonable threshold (typically three to five failed attempts in a row), require a user to go through the forgotten password process to remove the lock on their account.
Look for These First
As defined in the blog title, these are the most common authentication vulnerabilities I tend to find on web application penetration tests. There are a number of other vulnerabilities that affect web application authentication systems, but these are less common in my experience. It is recommended that web developers look for these common issues and resolve them before they have a penetration test. In most cases, these types of issues can be easy to resolve, and by doing so, the tester can spend his or her time on more complex vulnerabilities.
Learn more about manual penetration testing on our website.