Unvalidated Redirects

Karl Düüna
Security and Node.js
6 min readJan 4, 2016

--

Every so often, the web application you write will need to redirect the user based on the current situation. Most often this comes up when you redirect the user to a login page and if the login is successful, redirect them back. Sounds familiar?

This common logic in web applications is not without its caveats. In this blog post we will examine how attackers can abuse poorly implemented versions of this mechanism to their malicious ends and what we can do to defend our clients.

For a more thorough examination of web application security and how to defend your business be sure to check out my book “Secure Your Node.js Web Application” by Pragmatic Bookshelf.

The issue

A common implementation of a redirect logic will involve a query parameter specifying where to redirect the client. Something in the lines of https://example.com/login?r=https://example.com/original/page.
If the login is successful then the query parameter is used for redirecting the client to the desired page.

Now this implementation is not inherently flawed (read: It can be done securely), but more often than not, the following will also work https://example.com/login?r=https://evil.com/original/page.

If you can substitute the redirect path with any URL, then you are witnessing the Unvalidated Redirect problem in action.

“I don’t get what is wrong with this! So what if you can redirect yourself to another page?”

— Random developer

The exploit is not technical — this will not be used to attack your site directly. Instead, you are enabling attackers to use your site as a tool for social engineering attacks. Those attacks will mostly target your users, but can also be used to target users of other sites. This in turn will damage your reputation and likely your business.

“How can a simple redirect be used to attack my users?”

— Another random developer

Let’s look at a video of a demonstrative phishing attack using this particular threat vector.

Did you spot what was going on? Well, take a closer look at the URL throughout the video.

See it now? The URL change is minimal, but that is all it takes — the person in the video just got his/her account information stolen. Using something like “evil.com” would be way too obvious, so the attacker substituted the “L” in “example.com” with an “i” instead, which in uppercase format looks exactly like a lowercase “L”. Lets recap exactly how that happened step by step.

Another way this attack vector is used is to simply get users to visit a malicious URL. If you happen to have a path on your web server that sets a cookie and redirects the user forward, based on a query parameter, then even this can be used. People are more inclined to click on a link to a website they already know or simply looks legitimate. However, having a instant redirect can mean they end up somewhere completely different instead. It means that not only are we presenting a threat to our users and our system, but we are also jeopardising other users.

Now you should have an overview of what an unvalidated redirect attack is and why you should care where your users are redirected. Let’s now look at how we can mitigate this issue.

Fortunately the mitigation methods for this vulnerability is quite straightforward — don’t use unvalidated user input as the basis for redirect. This problem is similar to the Insecure Direct Object Reference, and as such, also has similar methods of mitigation. These vary in implementation complexity — so we get to choose which fits our needs best.

Disallow user input

The first method is simply removing any access the user has to the variable used to determine the redirect. This can be achieved by simply moving the variable to the session. So lets replace the following code, where we use query parameter:

With something like this, where we store this information in the session instead:

As you can see, the user no longer has any control over the redirect variable, and as such, an attacker can’t manipulate it for their own purposes.

Alternatively, we can also move the variable to a cookie. Preferably it will be a signed cookie, but even an unsigned cookie provides a decent amount of protection as the attacker will have to exploit some other vulnerability to manipulate the cookies on your website. And if they already have this type of access, then Unvalidated Redirect is not the worst of your problems.

While I recommend this approach and it is best for most systems, then applying this within a large existing system can mean a lot of work. This also means that we can’t do a direct link redirect — the variable can’t be preset, but must be set by our system.

So if we are faced with either too much work or a need for direct links, then we can revert to the next option, which addresses the whole issue only in the actual redirect locations.

Validate redirect URLs

While the previous solution removed user’s access to the redirect variable, this solution is to simply validate the provided URL before we redirect. This means that the user will still be able to manipulate the URL, but only to a certain degree which we control.

The following two different approaches can be taken to determine the validity.

  1. Construct a whitelist of possible URLs where we can redirect and check if the URL is on that list.
  2. Assume that internal redirects are safe (redirects that don’t leave the domain), for the rest use option 1.

Again, depending on the application in question, constructing a complete whitelist can present problems, so using the second approach is usually a better compromise.

Considering the options above, our validation function could look something like this:

And then we just use the following function before we redirect

This means of course that if we have a lot of external redirects (unusual, but could happen in a multi domain environment), then we have the extra obligation of maintaining the whitelist.

There is also a third method, which can be used if we need to set the variable without having a session or cookie access and when building a whitelist or validation function is too complex.

Sign/encrypt the variable

There might be situations where we can’t store the redirect variable from the server side and building a validation is too complex (lets say we have a heavily sharded domain with thousands of possible URL combinations). In such a situation, we can resort to signing/encrypting the variable in the URL.

For this we can use the Node.js built in crypto library and construct a module to encrypt and decrypt our input.

Then we use this library to create the URL with the redirect variable:

And get the URL variable from the URL.

This method allows us to create direct links with safe redirects by using the key to pre-calculate the redirect parameters we want. However, considering that the hash will be visible and the end result guessable, a decent encryption key is required to be secure it against cracking.

All in all, this method is not recommended — it uses a lot of server resources and can be exploited as an asymmetrical DOS attack point. Consider applying other methods whenever possible.

Wrapping up

Unvalidated Redirect is an attack vector that comes from giving too much control to our users — usually simply out of humane ignorance or negligence. However, despite the seeming innocence, it can be an effective tool in the hands of malicious hackers skilled with proper phishing methods.

So in order to mitigate this threat vector we should either:

  1. Remove user’s control over the redirect variable by setting the variable on a server controlled location (session, cookie, db); or
  2. Validate the URL before we actually redirect; or
  3. As a last resort, if no other method is applicable, encrypt or sign the url parameter.

Mitigating this threat vector will not only protect both your own business, but as well as other users on the web.

Sufficient knowledge about web security is something every decent developer should know. Even if you are not security oriented, this knowledge will be useful for designing more robust and secure systems. This in turn makes you a better developer overall.

If you find these mini tutorials useful, I recommend that you buy and read my book “Secure Your Node.js Web Application: Keep Attackers Out And Users Happy”. The book provides more in depth and practical knowledge about Web Application Security and implementing security mechanisms in Node.js applications.

Originally published at nodeswat.com on January 4, 2016.

--

--

Entrepreneur & Hacker by heart. CTO of http://www.nodeswat.com — researching and developing scalable & secure #nodejs apps