Broken authentication vulnerability was recognized as one of the OWASP's top 10 vulnerabilities.
Broken authentication vulnerability essentially is when an attacker gains unsolicited access to restricted data and/or functionality. It can lead to identify theft, data leakage and, in worst-case scenarios, give total control of the compromised system to the attacker.
This post will cover broken authentication vulnerability in general and in Java Spring in particular.
What Is Broken Authentication Vulnerability?
Broken authentication means an attacker can gain access to restricted data by pretending to be a different user. The attacker provides the authentication credentials of a different user and logs in to the system.
In this way, the attacker gains access to all the data and functionality of the user he pretends to be. For instance, if an attacker provides the credentials of the admin user, he'll have total control over the compromised system.
What Causes Broken Authentication Vulnerability?
There are many things that can result in a broken authentication vulnerability. Let's review some of them.
Using Weak and Standard Passwords
This is obviously a bad idea. If the username and password for your admin panel are "admin" and "admin," an attacker can easily guess them. The same is true if you use "admin" for the username and "12345" as a password.
This seems to be trivial, but it's actually not. Hackers have broken into a lot of systems in the past because of weak passwords.
Allowing Brute Force Cracking
If you change the credentials to something stronger—let's say "us8234243" for the username and "2ukZ3fav" for the password—those credentials can still become compromised.
One way an attacker can gain those credentials is via brute force cracking. In other words, the attacker creates an automated script that uses different combinations of usernames and passwords sequentially until he finds the right combination. This process can be very time-consuming (days, weeks, or even months), but if you don't prevent this kind of attack, it's still doable.
Sending Credentials in an Insecure Way
Even if you use a strong password and prevent brute force attacks but send the credentials to the server in plain text using an unencrypted connection (HTTP and not HTTPS), any other user who's connected to the same network as you can eavesdrop. Once he has the credentials, he can log in as if he were you.
Improper Session Handling
Improper Session Storage
Since the HTTP protocol is stateless, there's some need for session management between the client and server. Essentially, what we need is a way to identify the user and its state between distinct requests to the server. This can be done in various ways, some of them less secure than others.
For instance, after a successful login, we can save the credentials in a file (cookie) on the client's device. In subsequent requests, we can send this cookie to the server. This way, the server will know that the user is authenticated and identify him.
However, unencrypted cookies can be eavesdropped as easily as a username and password.
Improper Session Timeout
It's important to set a timeout for our login session. This means that after a certain period of inactivity, the user is automatically logged out from the system. Failing to do so may result in session hijacking.
This means that a session lasts forever. Hence, even if the cookie is encrypted, copying the cookie to another machine can allow an attacker to log in to the system.
Exposing Session Identifiers
Another way in which an attacker can compromise a session is by seeing the session identifiers in the URL. During this process, anyone who has the link can enter the login session.
For instance, if we store the session info in a URL of this structure—https://domain.com/login?username=test&password=test—anyone who has the link can log in to the system. This is bad practice.
Failing to Secure API Routes
In an API, there's usually a way to define which routes should require an authentication and which should not.
If you fail to add an authentication requirement for a route that should contain it, the functionality behind this route will be available worldwide. More on this later.
Click here to learn about more reasons for a broken authentication vulnerability and additional info on this vulnerability in general.
Mitigating Spring Broken Authentication Vulnerability
Here, I'll first discuss mitigating a vulnerability in general and then touch on mitigating the vulnerability in Java Spring.
Substantially reducing the risk of compromising the system due to this vulnerability is usually quite straightforward.
Credentials Handling
Here are some best practices:
Don't use default passwords (admin/123123).
Avoid using keyboard sequences (qwerty, 123456).
Use a password rotation policy (change the password every X weeks).
Don't disclose your passwords to others.
Don't log in to a website that uses an unencrypted connection (HTTP instead of HTTPS).
Brute Force Prevention
Here are some best practices:
Limit failed login attempts.
Log all failures and alert administrators when multiple failed requests happen in a short time span.
Ban IP addresses that generate failed login attempts from logging in to the system.
Session Handling
Here are some best practices:
Don't store credentials on the client's side, especially in an unencrypted way.
Store the session identifiers on the server.
Limit the session duration and invalidate the session after a logout.
Don't send session identifiers in a URL.
Spring Boot
The Spring framework is a superb Java framework for creating web applications and enterprise applications.
In 2005, Pivotal developed the Spring framework, and it's still very popular today. Ever since Pivotal developed the Spring framework, they've added various modules to the core Spring container.
Spring Boot is one of the most commonly used ones, representing the convention over configuration part of the Spring framework. Spring Boot lets you code with very minimal configuration.
Mitigating Broken Authentication Vulnerability in Spring Boot
Although the actions that describe vulnerability prevention in terms of credentials handling are quite framework agnostic, there are some specifics in securing routes in Spring Boot.
Securing Routes
Example of Vulnerability
This Spring controller doesn't explicitly enforce any authentication:
@RestController
@RequestMapping(path = "/administrator")
public class AdminEndpoint {
@PostMapping(path = "action")
public ResponseEntity doAdmin() { // ... } }
Additionally, in this example below, we have only one route that we've marked as requiring authentication:
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatchers(HttpMethod.GET, "/public/**").permitAll();
.antMatchers(HttpMethod.POST, "/administrator/some-action").authenticated();
// ...
}
The right way to protect routes in Spring is to mark any route except the public ones as requiring authentication:
.antMatchers(HttpMethod.GET, "/public/**").permitAll();
.anyRequest().authenticated();
Conclusion
Broken authentication vulnerability is a serious threat to application and website developers, administrators, and owners. It can result in data theft and identity theft and may make the whole system totally comprised.
Various things can cause this vulnerability, including having weak credentials, allowing brute force attacks, conducting improper session handling, and failing to secure API routes.
Luckily, most of the mitigation techniques are simple and straightforward. If you use these techniques, the risk decreases substantially. Most of those techniques are framework agnostic and can apply to all frameworks equally, including Java Spring Boot.
However, there are some specifics in the way routes should be handled in Spring Boot, and I've described them in this article. Make sure to protect all routes except the public ones, and you'll be on the safe side.
This post was written by Alexander Fridman. Alexander is a veteran in the software industry with over 11 years of experience. He worked his way up the corporate ladder and has held the positions of Senior Software Developer, Team Leader, Software Architect, and CTO. Alexander is experienced in frontend development and DevOps, but he specializes in backend development.