Prevention of technical information leakage from system error traces
import play.api.mvc._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
class HomeController @Inject()(cc: ControllerComponents) extends AbstractController(cc) {
def index() = Action.async { implicit request: Request[AnyContent] =>
Future {
try {
// Some risky operation that might throw an exception
throw new Exception("An error occurred.")
} catch {
case e: Exception => InternalServerError(e.getStackTrace.mkString("\\n"))
}
}
}
}
This code represents a simple Play Framework controller in a Scala backend application. It has a single action
index()
which is asynchronously executed. Inside this action, a risky operation is performed that might throw an exception.
In the event of an exception, the catch block captures it and the stack trace of the exception is directly returned as a response with a status of
InternalServerError(500)
.
The vulnerability here is the improper handling of exceptions which leads to the disclosure of technical information. When the exception is caught, the stack trace (which is a technical detail of the system's internal workings) is directly sent back to the user. This stack trace can provide an attacker with valuable information about the system, such as the structure of the code, the libraries being used, and potential points for exploiting further vulnerabilities. This is a classic example of a Technical Information Leak via Stacktrace vulnerability.
import play.api.mvc._
import play.api.Logger
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
class HomeController @Inject()(cc: ControllerComponents) extends AbstractController(cc) {
private val logger = Logger(this.getClass)
def index() = Action.async { implicit request: Request[AnyContent] =>
Future {
try {
// Some risky operation that might throw an exception
throw new Exception("An error occurred.")
} catch {
case e: Exception =>
logger.error("An error occurred: ", e)
InternalServerError("An error occurred. Please try again later.")
}
}
}
}
The original code was vulnerable because it exposed the stack trace of an exception directly in the HTTP response. This could potentially leak sensitive technical information to an attacker.
The fixed code avoids this vulnerability by logging the exception and returning a generic error message to the user. The stack trace is logged using Play's built-in
Logger
class, which allows developers to view the stack trace for debugging purposes without exposing it to the user.
The
try-catch
block is used to handle any exceptions that might be thrown by the risky operation. If an exception is thrown, it is caught and logged, and a generic error message is returned in the HTTP response.
This approach provides meaningful information to the user (i.e., that an error occurred) without exposing sensitive technical details. It also ensures that exceptions are handled consistently across the application, as all exceptions are caught and handled in the same way.
In addition, by using a centralized logging mechanism, it is easier to manage and monitor errors across the entire application. This can help with identifying and fixing issues more quickly, as well as improving the overall reliability and robustness of the application.