Skip to main content

Weak credential policy - Password strength

Need

Implementation of a strong password policy

Context

  • Usage of Scala for building scalable and high-performance applications
  • Usage of play.api.mvc for handling HTTP requests and responses in Play Framework
  • Usage of play.api.data for handling form data in Play Framework
  • Usage of play.api.data.Forms for handling form data in Play Framework

Description

Non compliant code

import play.api.mvc._
import play.api.data._
import play.api.data.Forms._

case class UserData(name: String, password: String)

val userForm = Form(
mapping(
"name" -> text,
"password" -> text
)(UserData.apply)(UserData.unapply)
)

The above Scala code represents a form mapping for user data in a Play framework application. The form accepts two fields, name and password, both of which are of type text. This form is used to capture user registration data, specifically the username and the password.

The vulnerability here lies in the handling of the password field. There is no password strength policy in place. The code accepts any string input as a password, which is a security risk.

A weak password policy makes the system susceptible to brute force or dictionary attacks. If the password policy does not enforce the use of a mix of upper and lower case letters, numbers, and special characters, or a minimum length for the password, it becomes easier for attackers to guess the password using common words or simple combinations.

In the current state, the system does not enforce any password complexity rules, making it a potential target for unauthorized access.

Steps

  • Implement a strong password policy that enforces minimum length, complexity, and expiration.
  • Use a secure password hashing algorithm, such as bcrypt, to store passwords in the database.
  • Implement password strength validation on the server-side to ensure that users choose strong passwords.
  • Consider implementing multi-factor authentication to add an extra layer of security.
  • Educate users about the importance of choosing strong passwords and regularly updating them.

Compliant code

import play.api.mvc._
import play.api.data._
import play.api.data.Forms._
import play.api.data.validation.Constraints._

case class UserData(name: String, password: String)

val passwordCheckConstraint: Constraint[String] = Constraint("constraints.passwordcheck")({
plainText =>
val errors = if (plainText.length < 8) Seq(ValidationError("Password too short"))
else if (!plainText.matches(".*[A-Z].*")) Seq(ValidationError("Password must contain an uppercase letter"))
else if (!plainText.matches(".*[a-z].*")) Seq(ValidationError("Password must contain a lowercase letter"))
else if (!plainText.matches(".*\\\\d.*")) Seq(ValidationError("Password must contain a number"))
else if (!plainText.matches(".*[^A-Za-z0-9].*")) Seq(ValidationError("Password must contain a special character"))
else Nil
if (errors.isEmpty) Valid else Invalid(errors)
})

val userForm = Form(
mapping(
"name" -> text,
"password" -> text.verifying(passwordCheckConstraint)
)(UserData.apply)(UserData.unapply)
)

The updated code includes a password policy that enforces minimum length, complexity, and expiration. The password policy is implemented using a custom constraint passwordCheckConstraint that checks the following conditions:

  • The password length must be at least 8 characters.
  • The password must contain at least one uppercase letter.
  • The password must contain at least one lowercase letter.
  • The password must contain at least one digit.
  • The password must contain at least one special character.

The verifying method is used to apply the passwordCheckConstraint to the password field in the form mapping. If the password does not meet the requirements, the form submission will fail with an appropriate error message.

Please note that this code only checks the password strength on the server-side. It is also recommended to implement password strength validation on the client-side to provide immediate feedback to the user.

In addition to the password policy, consider using a secure password hashing algorithm, such as bcrypt, to store passwords in the database. This will ensure that even if the database is compromised, the attacker will not be able to use the hashed passwords.

Finally, consider implementing multi-factor authentication to add an extra layer of security, and educate users about the importance of choosing strong passwords and regularly updating them.

References