Automatic information enumeration - Corporate information
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.