Skip to main content

Lack of data validation - Trust boundary violation

Need

Enforce strict data validation and trust boundaries

Context

  • Usage of PHP 7.0 for server-side scripting and web development
  • Usage of Request for making HTTP requests
  • Usage of the User dependency for user-related functionality
  • Usage of Hash for secure password storage and data encryption

Description

Non compliant code

public function store(Request $request)
{
$user = new User;
$user->name = $request->input('name');
$user->email = $request->input('email');
$user->password = Hash::make($request->input('password'));
$user->save();
return response()->json(['user' => $user], 200);
}

In the above code, we are directly using the input data from the request to create a new user in the system. This is a typical example of Trust boundary violation.

The store function creates a new User object and then directly assigns values from the request input to the object's properties. This is a dangerous practice as it trusts the input data implicitly without performing any form of validation or sanitization on it.

An attacker can potentially send malicious data in the request which can lead to various forms of attacks such as SQL Injection, Cross-Site Scripting (XSS), etc. For example, an attacker can send a script in the 'name' or 'email' field which can be executed when the data is displayed in the application, leading to an XSS attack.

In a nutshell, the code is vulnerable because it mixes trusted and untrusted data in the same data structure (User object) without any form of validation or sanitization.

Steps

  • Implement input validation: Before storing the user data, validate the inputs. Use Laravel's built-in validation rules or create custom ones to ensure the data is in the correct format and safe to store.
  • Sanitize the inputs: Even after validation, sanitize the inputs to remove any potentially harmful data. This can be done using Laravel's built-in sanitization functions or third-party libraries.
  • Separate trusted and untrusted data: Do not mix trusted and untrusted data in the same data structure. Keep them separate and only combine them when necessary, after ensuring the untrusted data is safe.
  • Use prepared statements for SQL queries: To prevent SQL injection attacks, use prepared statements when making SQL queries. This ensures that user input is never directly included in the query, making it safe from injection attacks.
  • Implement proper error handling: Do not reveal sensitive information in error messages. Customize your error messages to provide useful feedback to the user without exposing any sensitive system information.

Compliant code

public function store(Request $request)
{
$validatedData = $request->validate([
'name' => 'required|max:255',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|min:8',
]);

$user = new User;
$user->name = e($validatedData['name']);
$user->email = e($validatedData['email']);
$user->password = Hash::make($validatedData['password']);
$user->save();

return response()->json(['user' => $user], 200);
}

The updated code now includes data validation and sanitization to ensure that the data being stored is safe and in the correct format.

  1. Data Validation: The validate method on the $request object is used to validate the incoming request data. It checks that the 'name' is required and does not exceed 255 characters, the 'email' is required, in the correct email format, does not exceed 255 characters, and is unique in the 'users' table, and the 'password' is required and is at least 8 characters long. If the validation fails, a validation exception is thrown and the user is redirected back to their previous location with the validation errors.

  2. Data Sanitization: The e function is used to sanitize the validated data. This function runs the data through PHP's htmlspecialchars function with the ENT_QUOTES flag, converting special characters to their HTML entities and preventing cross-site scripting (XSS) attacks.

  3. Separation of Trusted and Untrusted Data: The validated and sanitized data is stored in a new User object, keeping it separate from the untrusted request data.

  4. Use of Prepared Statements: The save method on the User object uses prepared statements when making the SQL query to store the user data, preventing SQL injection attacks.

  5. Error Handling: Laravel's built-in error handling is used to handle any errors that occur. If an error occurs, the user is redirected back to their previous location with the error message, without revealing any sensitive system information.

References