Skip to main content

Uncontrolled external site redirect - Host Header Injection

Need

Prevention of uncontrolled external site redirects

Context

  • Usage of Ruby for scripting and web development
  • Usage of ActionController for handling actions and routing in a Ruby on Rails application

Description

Non compliant code

class ApplicationController < ActionController::Base
def redirect
redirect_to params[:url]
end
end

In the above code snippet, the redirect method in ApplicationController is vulnerable to Host Header Injection. This is because it uses the params[:url] directly from the request to redirect the user. This parameter can be manipulated by an attacker to redirect users to malicious websites.

This vulnerability is known as Uncontrolled External Site Redirect or Open Redirect. It allows an attacker to craft a URL with a different Host header that points to a malicious website. When the user clicks on this link, they are redirected to the attacker's website instead of the expected location.

In the context of a Ruby on Rails application, this can lead to serious security issues as the attacker can use this vulnerability to steal sensitive information such as session cookies or perform phishing attacks.

Steps

  • Validate and sanitize the input received in the 'url' parameter to prevent any malicious input.
  • Implement a whitelist of allowed redirect destinations to restrict the redirection to trusted domains only.
  • Use a safe redirect method provided by the framework that automatically handles the Host header, such as 'redirect_back' or 'redirect_to' with a specific route or path.
  • Avoid using user-supplied input directly in the redirect URL. Instead, use a separate variable or construct the URL using a trusted source.
  • Implement proper input validation and sanitization throughout the application to prevent other types of injection attacks.

Compliant code

class ApplicationController < ActionController::Base
def redirect
url = params[:url]
if url.present? && valid_url?(url)
redirect_to url
else
redirect_to root_path
end
end

private

def valid_url?(url)
allowed_domains = ['www.trusteddomain1.com', 'www.trusteddomain2.com']
uri = URI.parse(url)
allowed_domains.include?(uri.host)
rescue URI::InvalidURIError
false
end
end

The updated code includes a new method valid_url? that checks if the URL is part of a whitelist of allowed domains. This method is used in the redirect action to validate the url parameter before redirecting to it. If the URL is not valid or not present, the user is redirected to the root path of the application.

The valid_url? method uses the URI.parse method to parse the URL and extract the host. It then checks if this host is included in the allowed_domains array. If the URL is not valid or its host is not in the allowed domains, the method returns false.

This approach ensures that the application only redirects to trusted domains, preventing Host Header Injection attacks. It also provides a fallback redirect to the root path of the application in case the url parameter is not present or not valid. This improves the robustness of the application and enhances its security.

References