Automatic information enumeration - Corporate information - Ruby

Automatic information enumeration - Corporate information - Ruby

Need

Prevention of automatic enumeration of corporate information

Context

  • Requirement of Ruby version 2.5.0 or higher for running the application
  • Usage of Rails framework for building web applications

Description

Non compliant code

        class FindingsController < ApplicationController
  def show
    @finding = Finding.find(params[:id])

    if @finding
      render json: { status: 'success', data: @finding }
    else
      render json: { status: 'error', message: 'Finding not found' }
    end
  end
end
        
        

The above code is a simple Ruby on Rails controller that retrieves a finding based on an id passed in through the parameters. The vulnerability lies in the difference in response when a finding exists versus when it does not exist.

When the id passed in the parameters corresponds to an existing finding, the server responds with the status 'success' and the data of the finding. However, when the id does not correspond to an existing finding, the server responds with the status 'error' and a message 'Finding not found'.

This difference in response can be exploited by an attacker to enumerate all valid finding IDs. By making requests with different IDs and observing the response, an attacker can determine which IDs correspond to real findings and which do not. This is a vulnerability because it allows an attacker to gather information about the system that they should not have access to.

Steps

  • Avoid providing different error messages for existing and non-existing finding IDs
  • Use a generic error message for all error scenarios
  • Ensure that the response does not reveal any sensitive information about the system

Compliant code

        class FindingsController < ApplicationController
  def show
    begin
      @finding = Finding.find(params[:id])
      render json: { status: 'success', data: @finding }
    rescue ActiveRecord::RecordNotFound
      render json: { status: 'error', message: 'Unable to process request' }
    end
  end
end
        
        

The updated code now handles the scenario where a finding with the provided ID does not exist. Instead of explicitly stating that the finding was not found, a generic error message 'Unable to process request' is returned. This prevents potential attackers from enumerating system information by observing different responses for existing and non-existing finding IDs.

The begin and rescue block is used to handle exceptions in Ruby. If the Finding.find(params[:id]) line throws an ActiveRecord::RecordNotFound exception (which it will do if a finding with the provided ID does not exist), the code execution will immediately jump to the rescue block.

In the rescue block, a JSON response is rendered with a status of 'error' and a generic message 'Unable to process request'. This ensures that the response does not reveal any sensitive information about the system.

References