Lack of data validation - Source Code - Dart

Lack of data validation - Source Code - Dart

Need

Implementation of robust data validation mechanisms in the source code

Context

  • Usage of Dart for building cross-platform mobile, web, and desktop applications
  • Usage of Shelf for managing data storage and retrieval

Description

Non compliant code

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

shelf.Response handleRequest(shelf.Request request) {
  var regexPattern = request.url.queryParameters['pattern'];
  var inputString = request.url.queryParameters['input'];

  var regex = RegExp(regexPattern);

  if (regex.hasMatch(inputString)) {
    return shelf.Response.ok('Match found');
  } else {
    return shelf.Response.ok('No match found');
  }
}
        
        

In the provided Dart code, we are handling a request in a backend application that uses the Shelf framework. The function handleRequest retrieves two query parameters from the request URL: pattern and input.

The pattern parameter is used to create a regular expression ( RegExp) without any sanitization or validation. This RegExp is then used to check if it matches the input parameter.

The vulnerability here lies in the lack of data validation for the pattern parameter. An attacker could provide a complex or malicious regular expression as the pattern parameter. This could lead to a Regular Expression Denial of Service (ReDoS) attack, where the server could be forced to spend a significant amount of time processing the regular expression, potentially leading to a server crash.

For example, an attacker could provide a regular expression that results in catastrophic backtracking. This occurs when a regular expression has multiple paths it could take, but none lead to a successful match, forcing it to backtrack and try every possible combination, which can take a very long time for complex patterns.

This vulnerability could be mitigated by implementing data validation for the pattern parameter to ensure it is a safe and valid regular expression before it is used.

Steps

  • Validate the 'pattern' and 'input' query parameters to ensure they are not null or empty.
  • Implement a timeout for the regular expression evaluation to prevent long-running operations that could cause a server crash.
  • Consider using a safer method for pattern matching that doesn't involve regular expressions, or use a library that provides protection against dangerous regular expressions.
  • Limit the complexity of the regular expressions allowed. This could be done by limiting the length of the 'pattern' query parameter or by disallowing certain characters or sequences that are known to cause problems in regular expressions.
  • Implement error handling to catch any exceptions thrown by the RegExp constructor or the hasMatch method. This will prevent the server from crashing if an invalid regular expression is provided.

Compliant code

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

shelf.Response handleRequest(shelf.Request request) {
  var regexPattern = request.url.queryParameters['pattern'];
  var inputString = request.url.queryParameters['input'];

  if (regexPattern == null || regexPattern.isEmpty || inputString == null || inputString.isEmpty) {
    return shelf.Response.badRequest('Invalid input');
  }

  if (regexPattern.length > 100) { // Limit the complexity of the regex
    return shelf.Response.badRequest('Pattern too complex');
  }

  try {
    var regex = RegExp(regexPattern);

    // Implement a timeout for the regex evaluation
    var hasMatch = timeout(Duration(seconds: 2), () {
      return regex.hasMatch(inputString);
    });

    if (hasMatch) {
      return shelf.Response.ok('Match found');
    } else {
      return shelf.Response.ok('No match found');
    }
  } catch (e) {
    return shelf.Response.internalServerError('Error processing request');
  }
}
        
        

The updated code includes several measures to mitigate the risk of server crashes due to dangerous regular expressions:

1. Input Validation: The 'pattern' and 'input' query parameters are checked to ensure they are not null or empty. If either is null or empty, a 400 Bad Request response is returned.

2. Limiting Regex Complexity: The complexity of the regular expressions allowed is limited by restricting the length of the 'pattern' query parameter to 100 characters. If the 'pattern' is longer than this, a 400 Bad Request response is returned.

3. Timeout for Regex Evaluation: A timeout is implemented for the regular expression evaluation using the timeout function from the timeout package. This prevents long-running operations that could cause a server crash. If the regex evaluation takes longer than 2 seconds, the timeout function will throw a TimeoutException, which is caught and handled by returning a 500 Internal Server Error response.

4. Error Handling: Any exceptions thrown by the RegExp constructor or the hasMatch method are caught and handled by returning a 500 Internal Server Error response. This prevents the server from crashing if an invalid regular expression is provided.

References