The improper storage of passwords poses a significant security risk to software applications. This vulnerability arises when passwords are stored
in plain-text or with a fast hashing algorithm. To exploit this vulnerability, an attacker typically requires access to the stored passwords.
Why is this an issue?
Attackers who would get access to the stored passwords could reuse them without further attacks or with little additional effort. Obtaining the
clear-text passwords, they could then gain unauthorized access to user accounts, potentially leading to various malicious activities.
What is the potential impact?
Plain-text or weakly hashed password storage poses a significant security risk to software applications.
Unauthorized Access
When passwords are stored in plain-text or with weak hashing algorithms, an attacker who gains access to the password database can easily retrieve
and use the passwords to gain unauthorized access to user accounts. This can lead to various malicious activities, such as unauthorized data access,
identity theft, or even financial fraud.
Credential Reuse
Many users tend to reuse passwords across multiple platforms. If an attacker obtains plain-text or weakly hashed passwords, they can potentially
use these credentials to gain unauthorized access to other accounts held by the same user. This can have far-reaching consequences, as sensitive
personal information or critical systems may be compromised.
Regulatory Compliance
Many industries and jurisdictions have specific regulations and standards to protect user data and ensure its confidentiality. Storing passwords in
plain-text or with weak hashing algorithms can lead to non-compliance with these regulations, potentially resulting in legal consequences, financial
penalties, and damage to the reputation of the software application and its developers.
How to fix it in Spring
A user password should never be stored in clear text. Instead, a hash should be produced from it using a secure algorithm. When dealing with
password storage security, best practices recommend relying on a slow hashing algorithm, that will make brute force attacks more difficult. Using a
hashing function with adaptable computation and memory complexity also is recommended to be able to increase the security level with time.
Adding a salt to the digest computation is also recommended to prevent pre-computed table attacks (see rule S2053).
In general, relying on an algorithm with no known weaknesses is also a requirement. This prevents the use of the MD5 or SHA-1 algorithms.
While considered strong for some use cases, some algorithms, like SHA-family functions, are too fast to compute and therefore susceptible to brute
force attacks, especially with attack-dedicated hardware. Modern, slow, password hashing algorithms such as bcrypt, PBKDF2 or argon2 are
recommended.
Code examples
Noncompliant code example
The following code is vulnerable because it uses a legacy digest-based password encoding that is not considered secure.
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth, DataSource dataSource) throws Exception {
auth.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("SELECT * FROM users WHERE username = ?")
.passwordEncoder(new StandardPasswordEncoder()); // Noncompliant
}
Compliant solution
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth, DataSource dataSource) throws Exception {
auth.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("Select * from users where username=?")
.passwordEncoder(new BCryptPasswordEncoder());
}
How does this work?
The BCryptPasswordEncoder
is a password hashing function in Java that is designed to be secure and resistant to various types of
attacks, including brute-force and rainbow table attacks. It is slow, adaptative, and automatically implements a salt.
Resources
Documentation
Standards