Technical information leak - Print Functions - Scala

Technical information leak - Print Functions - Scala

Need

Prevention of sensitive information exposure through print functions

Context

  • Usage of Scala for building scalable and high-performance applications
  • Usage of play.api.mvc for handling HTTP requests and responses in a Play Framework application
  • Usage of global execution context for Scala concurrent operations

Description

Non compliant code

        import play.api.mvc._
import scala.concurrent.ExecutionContext.Implicits.global

class HomeController @Inject()(val controllerComponents: ControllerComponents) extends BaseController {

  def index() = Action.async { implicit request: Request[AnyContent] =>
    try {
      val data = Database.getData()
      Ok(views.html.index(data))
    } catch {
      case e: Exception =>
        e.printStackTrace()
        InternalServerError("Something went wrong!")
    }
  }
}
        
        

In the provided Scala code, we have a Play Framework controller named HomeController with a function index(). This function tries to fetch some data from the Database and render it in the view.

However, if an exception occurs while fetching the data, the catch block is triggered. Inside this catch block, the printStackTrace() function is called. This function prints the details of the exception, including the description of the exception, the stack trace, and other technical information, to the standard output (usually the console).

The problem here is that if this application is running in a production environment, this output could potentially be accessed by unauthorized users. This is a technical information leak vulnerability, as it might expose sensitive information about the application, such as the structure of the code, the database schema, or even credentials.

In addition, even if the system is configured to not display the standard output to users, this information could still be logged somewhere. If the logs are not properly secured, the same risks apply.

The best practice is to avoid using functions like printStackTrace() in a production environment. Instead, exceptions should be properly handled and logged using a secure and controlled logging mechanism.

Steps

  • Remove the use of print functions (Print, PrinStackTrace, Println, etc.)
  • Instead of printing technical information, handle and log the error messages
  • Configure a proper logging framework to capture and store error messages
  • Ensure that sensitive information is not exposed in error messages

Compliant code

        import play.api.mvc._
import play.api.Logger
import scala.concurrent.ExecutionContext.Implicits.global

class HomeController @Inject()(val controllerComponents: ControllerComponents) extends BaseController {

  val logger: Logger = Logger(this.getClass())

  def index() = Action.async { implicit request: Request[AnyContent] =>
    try {
      val data = Database.getData()
      Ok(views.html.index(data))
    } catch {
      case e: Exception =>
        logger.error("Something went wrong!", e)
        InternalServerError("Something went wrong!")
    }
  }
}
        
        

The original code was vulnerable due to the use of e.printStackTrace(), which could potentially leak sensitive information about the application's internals. This is especially dangerous in a production environment.

The fixed code removes the use of e.printStackTrace(). Instead, it uses the Play Framework's built-in Logger to log the error message. This is a safer approach as it ensures that the error message is captured and stored in a secure manner, without exposing sensitive information.

The Logger is initialized with Logger(this.getClass()), which sets the name of the logger to the fully qualified name of the class. This helps in identifying the source of the log messages.

In the catch block, logger.error("Something went wrong!", e) is used to log the error message and the exception. This ensures that the exception's stack trace is logged, which can be useful for debugging. However, unlike e.printStackTrace(), this does not print the stack trace to the standard output.

Finally, InternalServerError("Something went wrong!") is used to send a response to the client. This message does not contain any sensitive information, making it safe to be shown to the user.

References