Technical information leak - Print Functions - Dart

Technical information leak - Print Functions - Dart

Need

Prevention of sensitive information exposure through print functions

Context

  • Usage of Dart for building cross-platform mobile, web, and desktop applications
  • Usage of Shelf for managing and organizing data in Node.js applications

Description

Non compliant code

        import 'package:shelf/shelf.dart' as shelf;

shelf.Response handleRequest(shelf.Request request) {
  try {
    // Some operations...
  } catch (e, s) {
    print('Exception details:');
    print(e);
    print('Stack trace:');
    print(s);
    return shelf.Response.internalServerError();
  }
}
        
        

The above code is a simple handler for requests in a backend application using the Shelf framework in Dart. When an exception occurs during the processing of a request, the exception details and stack trace are printed to the standard output.

This is a vulnerability because it leaks technical information about the application. The details of the exception and the stack trace can provide valuable information to an attacker about the internal workings of the application, such as the structure of the code, the libraries used, and possibly even sensitive information like database queries or user data.

The print statements are used here for debugging purposes, which is acceptable in a development environment. However, in a production environment, this information should not be exposed. Instead, exceptions should be logged to a secure and private logging system, and generic error messages should be returned to the user.

Steps

  • Remove all print statements from the production code. These statements can expose sensitive information.
  • Instead of print statements, use a logging framework that supports different levels of logging (debug, info, warning, error, fatal).
  • Configure the logging framework to log only the necessary information in production environment. For example, you might want to log only warnings, errors, and fatal messages in production.
  • Ensure that the logs are stored in a secure location and are accessible only to authorized personnel.
  • In the catch block, instead of printing the exception details and stack trace, log them using the logging framework.
  • Make sure to handle the exception in a way that does not expose any sensitive information to the user. For example, you can return a generic error message to the user.

Compliant code

        import 'package:shelf/shelf.dart' as shelf;
import 'package:logging/logging.dart';

final _logger = Logger('handleRequest');

shelf.Response handleRequest(shelf.Request request) {
  try {
    // Some operations...
  } catch (e, s) {
    _logger.severe('Exception details:', e);
    _logger.severe('Stack trace:', s);
    return shelf.Response.internalServerError();
  }
}
        
        

The updated code removes all print statements and replaces them with a logging framework, in this case, the logging package from Dart. This package supports different levels of logging (debug, info, warning, error, fatal).

In the handleRequest function, when an exception is caught, instead of printing the exception details and stack trace, they are logged using the severe method of the logger. This method is used for logging errors. The logger is configured to log only the necessary information in the production environment.

The logs are stored in a secure location and are accessible only to authorized personnel. This ensures that sensitive information is not exposed.

In the catch block, a generic error message is returned to the user, without exposing any sensitive information. This is done by returning shelf.Response.internalServerError().

This approach ensures that the application does not leak technical information, thus fixing the vulnerability.

References