Prevention of sensitive information exposure through print functions
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.
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.