logo

Inappropriate coding practices - Eval function - Dart


Need

Elimination of the use of the eval function with unvalidated input


Context

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

Description

Insecure Code Example

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

  1. Remove the use of the eval function. It's a dangerous function that can lead to code injection attacks.
  2. 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.
  3. Always validate and sanitize user input. Never trust user input blindly. Use a whitelist of allowed characters and reject anything that does not match.
  4. Consider using prepared statements or parameterized queries if you're interacting with a database. This can help prevent SQL injection attacks.

Secure Code Example

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

  • 143 - Inappropriate coding practices - Eval function

  • Last updated

    2023/09/18