Technical information leak - Errors - Ruby

Technical information leak - Errors - Ruby

Need

Prevention of technical information leaks through error messages

Context

  • Usage of Ruby for building dynamic and object-oriented applications
  • Usage of ActionController for handling actions and requests in a Ruby on Rails application
  • Usage of ActionController::API for building API controllers in Ruby on Rails
  • Usage of the User dependency for managing user-related functionality

Description

Non compliant code

        class ApplicationController < ActionController::API
  def create
    @user = User.new(user_params)

    if @user.save
      render json: @user, status: :created
    else
      render json: @user.errors, status: :unprocessable_entity
    end
  end

  private

    def user_params
      params.require(:user).permit(:username, :email, :password)
    end
end
        
        

In the above code, the create method in ApplicationController is used to create a new user. The user's details are received from the client-side in the request body. These details are then used to create a new user object ( @user = User.new(user_params)). If the user object is successfully saved ( @user.save), the server responds with a status of :created and the user's details.

However, if there is an error while saving the user object, the server responds with a status of :unprocessable_entity and the details of the errors ( render json: @user.errors). This is where the vulnerability lies.

By responding with the details of the errors, the server leaks technical information to the client. An attacker can send various types of requests to the server (e.g., massive requests to the endpoint, sending massive characters in the body of the request) to force the server to throw errors. By analyzing the error details, the attacker can gain insights into the internal workings of the server, which they can then exploit to launch more sophisticated attacks.

Steps

  • Implement proper error handling and error messages to avoid leaking sensitive technical information.
  • Avoid displaying detailed error messages to the user in the production environment.
  • Use generic error messages instead of specific error messages that could reveal implementation details.
  • Consider logging the errors for debugging purposes, but ensure that the logged information does not contain sensitive technical details.
  • Regularly review and update error handling mechanisms to address any potential vulnerabilities.

Compliant code

        class ApplicationController < ActionController::API
  def create
    @user = User.new(user_params)

    if @user.save
      render json: @user, status: :created
    else
      render json: { error: 'Unable to process your request' }, status: :unprocessable_entity
    end
  rescue => e
    render json: { error: 'Internal server error' }, status: :internal_server_error
    Rails.logger.error e.message
  end

  private

    def user_params
      params.require(:user).permit(:username, :email, :password)
    end
end
        
        

The updated code includes a rescue block to handle any unexpected errors that may occur during the execution of the create method. This prevents the server from leaking technical information about the error to the client. Instead, a generic error message is returned to the client.

In the case of a failed user save operation, instead of returning the specific error messages generated by the @user.errors object, a generic error message is returned. This prevents potential attackers from gaining insights into the application's implementation details.

The error message is also logged using Rails.logger.error for debugging purposes. This allows developers to investigate the error in the server logs without exposing sensitive information to the client.

Remember to ensure that your server logs do not contain sensitive information and are properly protected against unauthorized access. Regularly review and update your error handling mechanisms to address any potential vulnerabilities.

References