Insecure service configuration - Keys - Dart

Insecure service configuration - Keys - Dart

Need

Secure storage and management of cipher keys

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;

void main() {
  var handler = const shelf.Pipeline().addMiddleware(shelf.logRequests())
      .addHandler(_echoRequest);

  shelf.serve(handler, 'localhost', 8080);
}

shelf.Response _echoRequest(shelf.Request request) {
  // Insecure practice: Storing keys directly in source code
  String privateKey = 'my_private_key';
  String publicKey = 'my_public_key';

  // ... rest of the code
}
        
        

In the above Dart code, we are using the Shelf package to create a simple server. The server is set up to listen on localhost at port 8080. The function _echoRequest is used to handle incoming requests.

The vulnerability lies in the _echoRequest function where we directly store the privateKey and publicKey as string literals. This is an insecure practice because anyone who has access to the source code can easily read these keys and potentially misuse them.

If an attacker gains access to these keys, they can impersonate the application or decrypt communications between the server and client, leading to a serious security breach.

The keys should never be stored directly in the source code. Instead, they should be stored in a secure and encrypted manner, such as in environment variables or secure key vaults.

Steps

  • Remove the hard-coded keys from the source code.
  • Store the keys in a secure and encrypted configuration file or use a secure key management system.
  • Ensure the keys are only accessible to the necessary services and personnel.
  • Rotate the keys periodically to limit the potential damage if they are compromised.
  • Implement a process to change the keys immediately if they are suspected to be compromised.

Compliant code

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

void main() {
  var handler = const shelf.Pipeline().addMiddleware(shelf.logRequests())
      .addHandler(_echoRequest);

  shelf.serve(handler, 'localhost', 8080);
}

shelf.Response _echoRequest(shelf.Request request) {
  // Secure practice: Load keys from environment variables
  String privateKey = Platform.environment['PRIVATE_KEY'];
  String publicKey = Platform.environment['PUBLIC_KEY'];

  // ... rest of the code
}
        
        

The updated code no longer stores the keys directly in the source code. Instead, it retrieves them from environment variables. This is a more secure practice because:

- The keys are not exposed in the source code, which could be accessed if the code repository is compromised.
- The keys can be managed securely outside of the application, for example in a secure and encrypted configuration file or a secure key management system.
- Access to the keys can be restricted to only the necessary services and personnel.
- The keys can be rotated periodically or immediately changed if they are suspected to be compromised.

To implement this, you would need to set the PRIVATE_KEY and PUBLIC_KEY environment variables in your server environment. The method to do this depends on your operating system and server setup.

Remember to never expose these keys in logs, error messages, or any other output that might be accessible to an attacker.

References