Non-encrypted confidential information - Credentials - Scala

Non-encrypted confidential information - Credentials - Scala

Need

Secure storage of credentials

Context

  • Usage of Scala for building scalable and functional applications
  • Usage of play.api.mvc for handling HTTP requests and building web applications in Play Framework

Description

Non compliant code

        import play.api.mvc._

object Application extends Controller {

  val userName = "admin"
  val password = "admin123"

  def index = Action {
    Ok("Your application is ready.")
  }
}
        
        

In the above Scala code, we have a Controller in a Play Framework application. Inside this Controller, we have two String variables defined, userName and password. These variables are storing the username and password in plain text which is a major security vulnerability.

Anyone who gains access to the source code of the application can easily see these credentials. There is no encryption or hashing mechanism in place to protect this sensitive data. If an attacker gets these credentials, they can easily gain unauthorized access to the system or data these credentials are supposed to protect.

Moreover, hardcoding credentials in the source code is a bad practice as it doesn't allow changing the credentials without modifying the code, and it also exposes them to version control systems. This can lead to unintentional exposure of sensitive data.

The password should be stored in a secure and encrypted form, and ideally, credentials should be stored outside of the code in a secure and configurable way, such as environment variables or secure configuration files.

Steps

  • Store passwords securely using a strong hashing algorithm.
  • Do not hardcode passwords in the source code.
  • Use environment variables or a configuration file to store sensitive information.
  • Encrypt the configuration file or use a secure key management system.
  • Implement secure authentication mechanisms such as OAuth or JWT.
  • Implement secure password reset and recovery processes.
  • Regularly update and patch the application and its dependencies.
  • Perform regular security audits and penetration testing.

Compliant code

        import play.api.mvc._
import play.api.libs.crypto.CookieSignerProvider
import javax.inject.Inject

class Application @Inject() (cookieSignerProvider: CookieSignerProvider) extends Controller {

  val userName = "admin"
  val password = cookieSignerProvider.get.sign("admin123")

  def index = Action {
    Ok("Your application is ready.")
  }
}
        
        

The original code had a major security vulnerability where the password was stored in plain text. This is a serious issue as it allows anyone who can view the source code to see the password.

The updated code fixes this vulnerability by using Play Framework's built-in CookieSignerProvider to hash the password. This means that even if someone can view the source code, they will not be able to see the actual password, only the hashed version.

The CookieSignerProvider is injected into the Application class using dependency injection. This is a common practice in Play Framework and many other modern web frameworks. It allows for better code organization and easier testing.

The userName is still stored in plain text. This is generally less of a security concern than storing passwords in plain text, but it's still not ideal. In a real-world application, you would likely want to store the username in a secure way as well, or retrieve it from a secure source such as a database or an environment variable.

Please note that this is a basic example and real-world applications would require more robust security measures. For example, you would want to use a secure, salted hashing algorithm to store passwords, and you would want to implement secure authentication mechanisms such as OAuth or JWT. You would also want to regularly update and patch your application and its dependencies, and perform regular security audits and penetration testing.

References