Inappropriate coding practices - Eval function - Dart

Inappropriate coding practices - Eval function - Dart

Need

Elimination of the use of the eval function with unvalidated input

Context

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

Description

Non compliant code

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

shelf.Response handleRequest(shelf.Request request) {
  var userInput = request.url.queryParameters['userInput'];
  var result = eval(userInput);
  return shelf.Response.ok('Result: $result');
}
        
        

The above Dart code is a simple server-side function that receives a request and retrieves a userInput parameter from the request URL query parameters. This userInput is then passed into the eval() function.

The eval() function evaluates or executes an argument. If the argument is an expression, eval() evaluates the expression. If the argument is one or more JavaScript statements, eval() executes the statements. This means that if userInput is a string of code, it will be executed by the eval() function.

The vulnerability lies in the fact that the userInput is not being validated or sanitized before it is passed into the eval() function. This means that an attacker could inject malicious code as the userInput parameter, which will then be executed by the server. This is a type of injection vulnerability known as eval injection.

Eval injection can lead to serious security issues, such as arbitrary command execution, data leakage, and even total system compromise. The attacker could potentially execute any command that the server has the privileges to execute, which could lead to a full system compromise in the worst case.

In this case, the attacker could simply send a request to the server with a URL that contains the userInput parameter set to a string of malicious code. Since the server does not validate or sanitize the userInput before passing it to the eval() function, the malicious code would be executed.

For example, an attacker could send a request with the following URL:

http://yourserver.com/?userInput=malicious_code_here

The server would then execute the malicious code contained in the userInput parameter.

To mitigate this vulnerability, you should never use the eval() function with user input. Always validate and sanitize user input before using it in your code. If you need to evaluate code dynamically, consider safer alternatives to eval(), such as new Function().

Please note that Dart does not have an eval() function, this is a hypothetical example.

Steps

  • Remove the use of the eval function. It's a dangerous function that can lead to code injection attacks.
  • Instead of eval, use safer alternatives to perform the required operation. If you're performing mathematical operations, consider using a library that can safely parse and evaluate mathematical expressions.
  • Always validate and sanitize user input. Never trust user input blindly. Use a whitelist of allowed characters and reject anything that does not match.
  • Consider using prepared statements or parameterized queries if you're interacting with a database. This can help prevent SQL injection attacks.

Compliant code

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

shelf.Response handleRequest(shelf.Request request) {
  var userInput = request.url.queryParameters['userInput'];
  
  // Validate user input
  if (!RegExp(r'^[0-9+\\-*/.() ]*$').hasMatch(userInput)) {
    return shelf.Response.forbidden('Invalid characters in input');
  }

  // Use math expressions library to safely evaluate the expression
  var parser = Parser();
  var expression = parser.parse(userInput);
  var contextModel = ContextModel();
  var result = expression.evaluate(EvaluationType.REAL, contextModel);

  return shelf.Response.ok('Result: $result');
}
        
        

The original code was vulnerable to code injection attacks because it used the eval function with user input. This function can execute arbitrary code, which is a serious security risk if the input is not properly validated and sanitized.

The fixed code removes the use of the eval function and replaces it with the math_expressions library, which can safely parse and evaluate mathematical expressions. This library throws an exception if the expression is not valid, which prevents code injection.

The user input is also validated with a regular expression that only allows numbers, basic arithmetic operators, parentheses, and spaces. If the input contains any other characters, the server responds with a 403 Forbidden status.

This solution prevents code injection attacks by both validating and sanitizing user input, and by using a safe method to evaluate mathematical expressions. It's a good practice to always validate and sanitize user input, and to avoid dangerous functions like eval.

References