Skip to main content

HTTP parameter pollution

Need

Prevention of HTTP parameter pollution

Context

  • Requirement of Ruby version 2.0 or higher
  • Usage of Rails framework for building web applications
  • Usage of ActiveRecord for Object-Relational Mapping (ORM) in database operations

Description

Non compliant code

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
def index
@user = User.find_by_email(params[:email])
end
end

The above code is a simple representation of a Ruby on Rails controller action that is vulnerable to HTTP Parameter Pollution attacks.

In the index action, the find_by_email method is being used to retrieve a user from the database using the email parameter that is passed in via the HTTP request.

The vulnerability here lies in the fact that the application does not perform any checks to ensure that the email parameter is not polluted with extra parameters. An attacker could potentially inject extra parameters into the HTTP request, causing unexpected behavior on the server.

For example, an attacker could send a request with multiple email parameters, like so:

In this case, the find_by_email method would return the first user that matches either of the email addresses, which could lead to unauthorized access to user accounts.

Steps

  • Validate and sanitize user input before using it in the application.
  • Implement strong parameterization to whitelist and validate the expected parameters.
  • Avoid using user input directly in database queries or other sensitive operations.
  • Use parameter naming conventions to prevent conflicts and confusion.
  • Implement input validation to ensure that only valid and expected values are accepted.
  • Implement proper error handling and logging to detect and respond to any unexpected behavior.

Compliant code

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
def index
email = params[:email]
if email.present? && email.match(/\\A[\\w+\\-.]+@[a-z\\d\\-]+(\\.[a-z\\d\\-]+)*\\.[a-z]+\\z/i)
@user = User.find_by_email(email)
else
# Handle invalid email
flash[:error] = "Invalid email address"
redirect_to root_path
end
end

private

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

The updated code includes a few changes to mitigate the HTTP parameter pollution vulnerability.

Firstly, we extract the email parameter from the request and store it in a local variable. This is done to avoid using the params hash directly in the database query, which could potentially lead to parameter pollution.

Next, we validate the email parameter using a regular expression. This ensures that the email is in the correct format before we use it in the database query. If the email is not present or not in the correct format, we display an error message to the user and redirect them to the home page.

We also introduce a new private method user_params which uses Rails' strong parameters feature. This method requires the presence of a :user key in the params hash and permits only the :email key within it. This ensures that only the expected parameters are allowed in the request, preventing any extra parameters from being injected.

These changes help to validate and sanitize user input, preventing HTTP parameter pollution. They also improve error handling and logging, allowing us to detect and respond to any unexpected behavior.

References