Prevent Open Redirect Attacks in ASP.NET Core

Are you developing a web application that accepts untrusted input? If so, be wary of unvalidated redirects and forwards. The untrusted input could cause the application to redirect the request to a URL within a suspicious input.

An attacker can launch a phishing scam and steal the user's credentials by manipulating an untrusted URL to a malicious website. Phishing attempts look trustworthy; for example, the server name in the modified link is identical to the original website. Before we can prevent open redirect attacks, we need to understand them first.

What's Open Redirect Attack

An open redirect attack is a vulnerability in your coding that redirects a user to another page when accessing a website. It's usually associated with a phishing attack.

Web apps usually redirect users to log-in pages to access resources that require authentication. The redirection may include a returnUrl query string parameter so that the user returns to the original requested URL after a successful log-in. Once authenticated, the user is redirected to the originally requested URL.

Your application is vulnerable to open redirect attacks if

  • It redirects to a URL that is specified via the request like a query string or form data
  • The redirection occurs without checking whether the URL is local.

Open Redirect Attack; A Pseudocode

A malicious user may plan an attack to obtain a user's credentials or confidential information. To launch the attack, the hacker should trick the user into clicking on a link to your site's login page, but with a URL that has the value of the returnUrl query string added to it. For example, consider an application on contoso.com that has a login page at

http://contoso.com/Account/LogOn?returnUrl=/Home/About.

The attack can be carried out in these steps: (It's more evident if we look at it from the hacker's point of view. Sorry!)

STEP 1: The user clicks on a malicious link to http://myapp.com/LogOn?returnUrl=http://maypp.com/LogOn;

$ Caution. The valid address is myapp.com (not maypp.com).

STEP 2: The user successfully logs in to the real website;

$ He/She is redirected to the attacker's website.

STEP 3: The user is redirected to http://maypp.com/Account/LogOn;

$ He/She logs in again, but on a fake website that looks exactly like a real one.

STEP 4: The user is redirected back to the real website;

$ He/She is tricked and gives the malicious website his/her personal data.

In this algorithm, the user doesn't even know that their sensitive data is stolen.

In STEP 1, the user is tricked into clicking on a link where the returnUrl is set to the attacker's website. Note that the log-in page of the malicious website looks exactly like the authentic one.

In STEP 3, the user believes that their first attempt to log in failed and that the second attempt was successful.

Dangerous URL Redirect # Ex. 1 & Ex. 2

Now consider the following C#.NET code:

string url = request.QueryString["url"];
Response.Redirect(url);

If no validation or additional method controls are utilized, this code is vulnerable to attack.

A second example is the ASP.NET MVC 1&2 websites. They're also vulnerable to open redirection attacks. You need to use MVC 3 to avoid this vulnerability.

Protecting Your Site Against Open Redirect Attacks

App development is vulnerable to attacks because the URL is implemented from the query string. The redirection to this URL is done without any validation. And this makes our application vulnerable to open redirect attacks.

However, you can prevent open redirect attacks. One way is to check if the given URL is local. Another is to make sure that you redirect only to known, trusted websites.

LocalRedirect: This helper method throws an exception from the controller base class when a non-local URL is detected. Otherwise, it works exactly like the redirect method.

IsLocalUrl: This method allows you to test URLs before redirecting them. It protects users from being inadvertently redirected to a malicious website.

You can use the LocalRedirect() method to prevent the attack. If a non-local URL is specified, an exception is thrown.

public IActionResult Login(string returnUrl)
{
    return LocalRedirect(returnUrl);
}
public IActionResult Login(string returnUrl)
{
    //To check if the URL is local, use IsLocalUrl() method.
    if (Url.IsLocalUrl(returnUrl))            
    {
        return Redirect(returnUrl);
    }
    else
    {
        return RedirectToAction("index", "home");
    }
}

Bottom Line

Be careful when your controllers redirect to another location based on user input (a query string). You need to make sure that the location isn't malicious, i.e., you need to prevent open redirect attacks. The simplest way to provide this protection is to examine the URL provided by the user. To this end, the framework offers a few ways to accomplish this: LocalRedirect() and IsLocalUrl().