Authentication is one of the key policies of any application. This policy can control and protect the resources from unauthorized access. But if not implemented properly, it can result in multiple security vulnerabilities.
Java has held up great through the test of time. It's been around since 1996 and has been reinvented periodically to keep up with programmers' needs. It's one of the most widely used languages and has its share of vulnerabilities in authentication.
By the end of this post, you'll be able to understand the underlying problem and its actual impact, along with how to prevent it.
What Is Broken Authentication?
Broken authentication is a broad range of security vulnerabilities that occur due to poor implementation of an authentication mechanism.
Broken authentication occurs when a hacker or cybercriminal can bypass the authentication process in any possible way. This allows unauthenticated access to a system or, in some cases, allows the attacker to authenticate without providing a valid password or PIN.
For example, if a cybercriminal successfully obtains a username from a victim but the authentication system doesn't have any rate limit in place, the attacker can bypass the authentication by brute-forcing the password.
There are many different methods attackers can use to exploit broken authentication vulnerabilities.
Depending on the type of vulnerability and how it's exploited, attackers may be able to access sensitive data, change data, and much more.
What Leads to Broken Authentication Vulnerabilities?
Broken authentication can cause many problems such as data leakage and system compromise. Various reasons lead to broken authentication, including
using a guessable session ID,
having a session that doesn't expire after a password change,
using weak and well-known passwords,
have a lack of brute-force protection, and
storing sensitive data (passwords) in clear text.
But these are just vulnerabilities; how do hackers exploit these issues? Let's dig into that.
Common Attacks to Exploit Broken Authentication Vulnerabilities
When a hacker finds a vulnerability in a website's authentication system, they'll try to exploit it and retrieve sensitive data. But what exactly does the hacker do when it comes to exploiting the vulnerability? Here are three different types of attacks hackers use to exploit broken authentication vulnerabilities.
1. Brute-Force and Dictionary Attacks
A brute-force attack is the simplest type of attack. It's a trial-and-error method where the hacker tries to guess the target user's credentials. The attacker can use several techniques to do this.
On the other hand, a dictionary attack is the most common method and is simply a trial-and-error method to guess the user's password by using a wordlist.
2. Password Spraying
Password spraying is one of the most common attack methods. Oftentimes, it's used in conjunction with bots. This attack involves repeatedly attempting to log on to a server or website with a username and password combination.
The advantage of password spraying over a brute-force attack is that it's often successful. This is because it takes advantage of a common password used by many users.
3. Response Manipulation
Response manipulation exploits vulnerabilities in the communication channel between a server (or any other host) and a client. This happens when the application relies on the successful response (only boolean) of the server to validate a user. Additionally, an attacker can easily manipulate the incoming response using proxy and bypass authentication.
Also read: React Broken Authentication Guide: Examples and Prevention
Now that we've looked at broken authentication vulnerability in general, let's understand the vulnerability specific to Java.
Understanding Broken Authentication in Java
In this section, we'll look at three different code snippets (Java Spring Boot) and understand broken authentication vulnerabilities and how you can prevent them.
Let's get started.
Code Snippet #1
@RequestMapping("/register")
public void Register(@RequestBody UserInfo user){
try{
database.openConnection();
database.saveUser(User.email, user.password);
}
catch(Exception ex){
throw ex;
}
finally{
database.closeConnection();
}
}
In the code snippet above, we have a /register endpoint that receives an email address and password from the request body. The security risks in this code snippet are:
Weak password policy—There is no check on the length of a password or even to check if the password is strong enough.
Cleartext storage of sensitive data—A password is stored directly in the database without hashing or salting the password.
To prevent the issues mentioned above, we recommend you have a helper function to check if the password is strong and to salt the password before storing it in the DB.
@RequestMapping("/register")
public void Register(@RequestBody UserInfo user){
try{
database.openConnection();
if(isPasswordStrong(password))
password = saltPassword(password);
database.saveUser(User.email, user.password);
}
catch(Exception ex){
throw ex;
}
finally{
database.closeConnection();
}
}
Code Snippet #2
@RequestMapping("/changePassword")
protectedvoidchangePassword(
@RequestParam("currentPassword") String currentPassword,
@RequestParam("newPassword") String newPassword,
HttpServletResponse response) throws Exception
{
PrintWriter writer = response.getWriter();
try
{
handler.handleChangePassword(currentPassword, newPassword);
}
catch (Exception ex)
{
writer.println( ex.getMessage() );
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return;
}
writer.println(HttpServletResponse.SC_OK);
}
In the code above, we have a /changePassword route that takes currentPassword and newPassword as input and changes the user's password by updating it in the DB. This code has an improper session management vulnerability due to which the session would not expire after the user changes his password.
To prevent this issue, the application should log out the user from all other active sessions.
@RequestMapping("/changePassword")
protectedvoidchangePassword(
@RequestParam("currentPassword") String currentPassword,
@RequestParam("newPassword") String newPassword,
HttpServletRequest request,
HttpServletResponse response) throws Exception
{
PrintWriter writer = response.getWriter();
try
{
handler.handleChangePassword(currentPassword, newPassword);
HttpSession session = request.getSession(false);
if(session != null)
session.invalidate();
}
catch (Exception ex)
{
writer.println( ex.getMessage() );
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return;
}
writer.println(HttpServletResponse.SC_OK);
}
Code Snippet #3
@Controller
public class AdminController {
@RequestMapping(value = "/admin/user/data", method = RequestMethod.GET)
@ResponseBody
public List<String> getUserDetails(Authentication authentication) {
if(authentication.isAuthenticated()){
return userDao.getDetailsFromDb();
}
}
}
In the code above, we have an admin route /admin/user/data responsible for retrieving all of a user's data. The security risk in this code involves the lack of API authentication to check a user's authenticity and validate whether the authenticated user is admin.
To prevent the issue above, we recommend you add an authentication check and a proper authorization check (if the user is an admin) to avoid a data breach.
@Controller
public class AdminController {
@RequestMapping(value = "/admin/user/data", method = RequestMethod.GET)
@ResponseBody
public List<String> getUserDetails(Authentication authentication) {
if (authentication instanceof AdminAuthenticationToken){
return userDao.getDetailsFromDb();
}
}
}
Now that we thoroughly understand the vulnerability, let's take a look at some common best practices to avoid such risks.
Best Practices to Avoid Broken Authentication Vulnerabilities
Broken authentication vulnerabilities are a huge problem for all applications, including mobile, web, and iOS.
Furthermore, account takeover attacks are responsible for a significant portion of the damage done to web applications and often involve broken authentication vulnerabilities.
Here are some best practices to help you avoid broken authentication vulnerabilities in your applications.
Enforce a strict password policy. Above all, creating longer and stronger passwords is the first step to avoiding broken authentication vulnerabilities. To enforce a strict password policy, you need to either use LDAP and Active Directory to manage your authentication credentials, or use a password management tool like LastPass, DashLane, or 1Password.
Require multi-factor authentication. Multi-factor authentication is a very effective method of preventing unauthorized access to your systems. This approach, in combination with a username/password pair, is highly recommended for systems that access sensitive data.
Use rate limiting. One of the best ways to avoid authentication attacks is to use a rate limit on all authenticated related endpoints such as login, which prevents brute-force attacks. Modern-day applications use two different ways to implement rate limitations. First, they can block the user's account after he has tried to log in several times with an incorrect password (known as account lockout). Second, they can stop an attack using a CAPTCHA image challenge. Although these CAPTCHA challenges were annoying and difficult to decipher in the past, nowadays, with advances in computer vision, OCR, etc., this is becoming less effective.
Conclusion
Broken authentication vulnerability is a major threat to a system's security. For example, it can result in a loss of confidential information, loss of reputation, and financial loss. Moreover, the severity of this vulnerability is usually very high, as the unauthorized user can access the system and its resources. Consequently, this may lead to the theft of an organization's data and sensitive information.
In this post, we've discussed broken authentication vulnerability in-depth and learned how hackers can exploit it. Furthermore, we've learned some preventive measures you can take to protect your applications from such attacks.
Scanning for broken authentication vulnerabilities using StackHawk DAST is a breeze! For more information, don't hesitate to contact us at hello@stackhawk.com.
This post was written by Keshav Malik. Keshav is a full-time developer who loves to build and break stuff. He is constantly on the lookout for new and interesting technologies and enjoys working with a diverse set of technologies in his spare time. He loves music and plays badminton whenever the opportunity presents itself.