Uncontrolled external site redirect - PHP

Uncontrolled external site redirect - PHP

Need

Controlled and secure external site redirects

Context

  • Usage of PHP 7.0+ for server-side scripting and web development
  • Usage of Illuminate\\Http\\Request for handling HTTP requests in Laravel
  • Usage of Illuminate\\Support\\Facades\\Redirect for handling URL redirection in Laravel

Description

Non compliant code

        public function redirectToExternalSite(Request $request) 
{
    $externalUrl = $request->get('external_url');
    return redirect()->away($externalUrl);
}
        
        

The above code is a Laravel method that redirects the user to an external URL. The URL is being taken directly from the request without any validation or sanitization. This is a major security vulnerability known as Uncontrolled External Site Redirect (or Open Redirect).

In this case, a malicious user could manipulate the 'external_url' parameter in the request to redirect users to a phishing site or any other malicious site. For example, they could send an email to a user with a link to your site like http://yourwebsite.com/redirect?external_url=http://maliciouswebsite.com. If the user clicks on the link, they will be redirected to the malicious site.

This vulnerability can lead to various serious attacks like phishing, where the attacker can create a replica of a legitimate site and steal sensitive information like usernames and passwords. It can also be used for spreading malware.

The code does not verify if the URL is a valid and trusted URL before redirecting. This lack of control over the redirect destinations poses a significant security risk.

Steps

  • Validate the URL before redirecting. Ensure it is a valid URL and it belongs to a trusted domain.
  • Implement a whitelist of trusted domains. Only allow redirection to these domains.
  • Avoid directly using user input to determine the redirection URL. If necessary, map user inputs to URLs on the server side.
  • Use a safe method for redirection, such as using the 'Location' header with a relative path.
  • If possible, avoid redirection to external sites altogether. If it's necessary, ensure it's done securely.

Compliant code

        public function redirectToExternalSite(Request $request) 
{
    $allowedDomains = ['trusteddomain1.com', 'trusteddomain2.com']; // Add your trusted domains here
    $externalUrl = $request->get('externalUrl');

    if(filter_var($externalUrl, FILTER_VALIDATE_URL)) {
        $parsedUrl = parse_url($externalUrl);
        if(in_array($parsedUrl['host'], $allowedDomains)) {
            return redirect()->away($externalUrl);
        }
    }

    // If the URL is not valid or not in the trusted domains, redirect to a default page
    return redirect()->away('defaultPageUrl');
}
        
        

The updated code now includes a validation step before the redirection. It uses PHP's filter_var function with the FILTER_VALIDATE_URL filter to check if the externalUrl is a valid URL.

If the URL is valid, the code then parses the URL to extract the host part using the parse_url function. It checks if this host is in the list of allowed domains. If it is, the code proceeds with the redirection.

The allowed domains are defined in the allowedDomains array. You should replace 'trusteddomain1.com' and 'trusteddomain2.com' with the domains you trust and want to allow redirection to.

If the URL is not valid or the domain is not in the list of allowed domains, the code redirects to a default page. You should replace 'defaultPageUrl' with the URL of the page you want to redirect to in these cases.

This way, the code ensures that the application only redirects to valid URLs on trusted domains, preventing attackers from manipulating the redirection.

References