Technical information leak - Stacktrace - kotlin

Technical information leak - Stacktrace - kotlin

Need

Prevention of technical information leakage from system error traces

Context

  • Usage of Kotlin for building modern and scalable applications
  • Usage of javax.servlet for creating Kotlin web applications with Servlets
  • Usage of java.io for input and output operations in Kotlin programming

Description

Non compliant code

        import javax.servlet.*
import javax.servlet.http.*
import java.io.IOException

class VulnerableServlet : HttpServlet() {

    @Throws(ServletException::class, IOException::class)
    override fun doGet(request: HttpServletRequest, response: HttpServletResponse) {
        try {
            // some risky operation
            throw Exception("This is a forced exception")
        } catch (e: Exception) {
            e.printStackTrace(response.writer)
        }
    }
}
        
        

The following Kotlin servlet contains a security vulnerability that leads to technical information leakage through stack traces.

In the doGet method, an exception is intentionally thrown to simulate a scenario where an error occurs. The catch block then prints the stack trace directly to the HTTP response using e.printStackTrace(response.writer).

This is a serious issue because the stack trace exposes internal details of the application, such as class names, method signatures, and even system properties. If an attacker can trigger this error, they could gather useful information about the system to plan further attacks.

To mitigate this risk, the exception should be logged securely instead of being exposed to the user.

Steps

  • Avoid printing stack traces directly to the response.
  • Implement proper error handling and logging mechanisms.
  • Catch the exception and handle it appropriately instead of printing the stack trace.
  • Consider using a centralized error handling mechanism to handle exceptions consistently across the application.
  • Ensure that sensitive technical information is not exposed to the user in error messages or logs.

Compliant code

        import javax.servlet.*
import javax.servlet.http.*
import java.io.IOException
import java.util.logging.Level
import java.util.logging.Logger

class SecureServlet : HttpServlet() {

    companion object {
        private val LOGGER = Logger.getLogger(SecureServlet::class.java.name)
    }

    @Throws(ServletException::class, IOException::class)
    override fun doGet(request: HttpServletRequest, response: HttpServletResponse) {
        try {
            // some risky operation
            throw Exception("This is a forced exception")
        } catch (e: Exception) {
            LOGGER.log(Level.SEVERE, e.message, e)
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "An error occurred while processing your request. Please try again later.")
        }
    }
}
        
        

The secure version of the code properly handles errors and prevents technical information leakage. Key improvements include:

1. Preventing stack trace exposure: The e.printStackTrace(response.writer) line is removed to avoid leaking internal system details.

2. Implementing proper logging: A Logger instance is used to record exceptions securely on the server side.

3. Using a generic error message: Instead of showing detailed error information to the client, a standardized error response is sent.

4. Ensuring centralized error handling: Logging is handled in a consistent way, making debugging easier while improving security.

5. Keeping sensitive information private: Error details remain in server logs instead of being exposed to users.

References