Lack of data validation - Numbers - Ruby

Lack of data validation - Numbers - Ruby

Need

Implementation of robust data validation for numbers

Context

  • Requirement of Ruby 2.0+ for running the application
  • Usage of Ruby on Rails framework for web application development

Description

Non compliant code

        def update_user_age
  age = params[:age]
  @user = User.find(params[:id])
  @user.update_attribute(:age, age)
end
        
        

The above vulnerable code is a typical example of a lack of data validation in a Ruby on Rails backend application.

In the update_user_age method, the age parameter is directly fetched from the request parameters without any form of validation or sanitation. This age value is then used to update the age attribute of a User object.

The vulnerability lies in the fact that an attacker can pass in any value for the age parameter, including negative numbers, extremely large numbers, or non-numeric values. This can break the application's business logic, as age is typically a positive integer and within a certain range.

For instance, an attacker could pass in a negative number for age, which is logically incorrect as age cannot be negative. Similarly, an attacker could pass in a non-numeric value for age, which could potentially cause a type error in the application, leading to unexpected behavior or crashes.

This lack of data validation can lead to various negative impacts on the business, including incorrect data being stored in the database, application crashes leading to service downtime, and potential exploitation of other vulnerabilities due to unexpected input.

Steps

  • Implement input validation to ensure that the 'age' parameter is a valid number.
  • Use a validation method or regular expression to check if the 'age' parameter is a number.
  • Handle invalid input by displaying an error message to the user.
  • Consider using strong parameters to whitelist and sanitize the input before updating the user's age.
  • Ensure that the user's age is properly validated and sanitized before updating the database.
  • Consider implementing additional business logic checks to ensure the age value is within a valid range.

Compliant code

        def update_user_age
  age = params[:age]
  @user = User.find(params[:id])

  if valid_age?(age)
    @user.update_attribute(:age, age)
  else
    render json: { error: 'Invalid age' }, status: :unprocessable_entity
  end
end

private

def valid_age?(age)
  age.to_s.match?(/\\A[+-]?\\d+\\z/) && age.to_i.between?(0, 120)
end
        
        

The updated code includes a validation method valid_age? that checks if the 'age' parameter is a valid number and within a reasonable range (0 to 120 years).

The valid_age? method uses a regular expression ( /\\A[+-]?\\d+\\z/) to check if the 'age' parameter is a number. The match? method returns true if the 'age' parameter matches the regular expression, and false otherwise.

The between? method is used to check if the 'age' parameter is within a valid range (0 to 120). This is a basic business logic check to ensure the age value is reasonable.

If the 'age' parameter is not a valid number or not within the valid range, the update_user_age method will render a JSON response with an error message and a status code of 422 (Unprocessable Entity).

If the 'age' parameter is valid, the update_user_age method will update the user's age in the database.

This code ensures that the user's age is properly validated and sanitized before updating the database, which helps to prevent potential issues with the business logic.

References