Lack of data validation - Trust boundary violation - Dart

Lack of data validation - Trust boundary violation - Dart

Need

Enforce strict data validation and maintain trust boundaries

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;

Future handleRequest(shelf.Request request) async {
  var data = request.url.queryParameters;
  var username = data['username'];
  var password = data['password'];
  
  // Mixing trusted and untrusted data in the same data structure
  var userInfo = {
    'username': username,
    'password': password,
    'isAdmin': false
  };

  // Rest of the code
}
        
        

In the above Dart code, we're using the Shelf framework to handle HTTP requests. The function handleRequest is designed to handle incoming requests.

In this function, we first extract the query parameters from the URL of the request. This data is untrusted because it comes directly from the user, who can manipulate it.

We then extract the 'username' and 'password' from this untrusted data and put it into a new data structure userInfo along with a trusted data 'isAdmin': false.

The problem here is that we are mixing trusted and untrusted data in the same data structure. This is a Trust Boundary Violation vulnerability.

The trusted data (isAdmin) is hardcoded and controlled by the system, while the untrusted data (username and password) is supplied by the user. If an attacker can manipulate the untrusted data in a way that affects the system's behavior, they could potentially gain unauthorized access or perform actions they shouldn't be able to.

In this case, if there is any code later that relies on the 'isAdmin' field to grant administrative privileges, and if the untrusted data is not properly validated, an attacker could potentially manipulate the 'username' or 'password' field to trick the system into granting them admin rights.

Steps

  • Separate the handling of trusted and untrusted data. Do not mix them in the same data structure.
  • Validate the input data. Ensure that the 'username' and 'password' parameters are present and meet the required format or criteria before using them.
  • Consider using a dedicated data structure or class for user information. This can help to encapsulate the data and provide a clear distinction between trusted and untrusted data.
  • Implement proper error handling. If the validation fails, the function should return an appropriate error response.

Compliant code

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

class UserInfo {
  String username;
  String password;
  bool isAdmin;

  UserInfo(this.username, this.password, {this.isAdmin = false});
}

Future handleRequest(shelf.Request request) async {
  var data = request.url.queryParameters;
  
  // Validate the input data
  if (!data.containsKey('username') || !data.containsKey('password')) {
    return shelf.Response(400, body: 'Missing username or password');
  }

  var username = data['username'];
  var password = data['password'];

  // Ensure the username and password meet the required format or criteria
  if (username.isEmpty || password.isEmpty) {
    return shelf.Response(400, body: 'Username or password should not be empty');
  }

  // Use a dedicated data structure for user information
  var userInfo = UserInfo(username, password);

  // Rest of the code
}
        
        

The updated code now separates the handling of trusted and untrusted data by using a dedicated class UserInfo for user information. This provides a clear distinction between trusted and untrusted data.

Before using the 'username' and 'password' parameters, the code validates the input data. It checks if these parameters are present in the request data and if they meet the required format or criteria (in this case, they should not be empty). If the validation fails, the function returns an appropriate error response with a status code of 400 and a descriptive error message.

This way, the system does not mix trusted and untrusted data in the same data structure, thus fixing the trust boundary violation vulnerability.

References