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.