Modern web applications face a never-ending risk of attack. These days you can become a target even if your website is small and new. There are automated robots running twenty-four-seven all over the internet looking for any kinds of vulnerabilities. Therefore, securing your web application is more important than ever. Some security best practices are universal, such as, for example, never exposing ports and endpoints to the internet that don't need to be exposed. Others are language- and framework-specific. In this post, you'll learn how to protect your Rails application from open redirect vulnerability.
What's Open Redirect Vulnerability?
First things first: let's talk about open redirect vulnerability in general. Open redirect vulnerability, also known as unvalidated redirects and forwards, is a type of attack in which a hacker can change the destination URL of a redirect that your application performs. It can, for example, force your web application to redirect users to an untrusted URL, possibly one provided by the attacker. Another use case can be trying to gain access to places that they normally don't have access to, such as an admin panel.
In today's applications, it's very common to be redirected back and forth to and from different URLs. For example, when logging into some websites, you may get redirected to an OAuth provider. When making a purchase in an online shop, you may get redirected to a third-party payment provider. If an attacker finds a way to provide their own destination URL, your users may get redirected to a malicious website. Such a website, for example, can look like your payment provider's website, and it may then try to steal credit card details. So let's take at look at what vulnerable code might look in Rails. And if you want to learn more about open redirect vulnerability in more detail, check this blog post.
You may be familiar with the very commonly used Rails redirect_to method. It's a simple method that generates HTML hyperlinks. It can be used to generate simple text links as well as buttons, images, and logo-based hyperlinks. For example, if you want to create a simple link, you can do so by writing the following code:
On your website it will become the following:
That's the simple scenario. In real life, instead of directly providing the desired URL, you'll often provide variables, helper methods, or controller actions. And if you don't pay attention to what you provide to redirect_to, you may expose yourself to an open redirect vulnerability.
Vulnerable Rails Examples
So what do you need to avoid when using redirect_to? User input is more important than anything else. This is the single most dangerous thing you can pass to a redirect_to method. You may be thinking, well, OK, but why would I use user input for redirect_to anyway? Surprisingly, there are a few common use cases. For example, you may ask the user to provide their Instagram or Twitter handle and use the value of that input as a parameter for redirect_to. Or you could simply ask for a portfolio URL from a user. These are only the most obvious examples. There are use cases where you won't even realize that you're using user input.
Imagine the following code:
You could, for example, give a user an option when creating a support ticket to specify the URL of a page they're having a problem with. What could go wrong here, right? Well, an attacker may specify something like this:
Most users will only check (if at all) the beginning of the URL without noticing the redirect at the end of the link.
Another approach that attackers may take is trying to gain access where they don't have permission. So instead of trying to redirect other users to a phishing page, they may try to get access, for example, to an admin panel of your page. A user-provided URL may look something like this:
When redirects are not properly validated, they may be able to bypass your typical authorization mechanisms. Since it's Rails itself that would redirect a user to an admin page, it's possible that they'll see it even if they don't have admin accounts.
How to Secure Your Rails Redirects
Now that you know what vulnerable Rails code looks like, let's talk about how to avoid this type of attack.
The short and best solution is to avoid using user input as a redirect_to parameter.
If you really need to do that, there are a few options.
One solution would be to let users pass only the parameter you are looking for instead of a full URL. For example, ask a user only for the ID or short name of an object if possible. This can, however, create another vulnerability when the attacker could try to loop over all possible values trying to find all IDs and therefore all possible redirect targets. This could give them an option to find, for example, product pages that haven't been published yet.
If that's an option, implement a whitelist of allowed parameters. You can also sanitize input by parsing it via regex or an allow list.
Another approach is to force all redirects created from user input to be first redirected to a specific page clearly notifying users what the destination is. As we mentioned before, this vulnerability is sometimes hard to spot because your real website URL is in some cases still visible as the destination URL. Therefore, having only the real destination target clearly visible can help in many cases.
You also need to keep in mind that your Rails application may be vulnerable to open redirect even if you don't use risky redirect_to parameters. How's that? The vulnerability may be simply coming from Rails's own libraries. There have already been a few examples of such cases. For example, this CVE. And the more third-party gems you use, the higher the risk.
What does it mean for you? Of course, you can't read the entire Rails code in order to find all possible vulnerabilities. Instead, you can get help from modern security testing tools like StackHawk. You can get automated security testing as part of your CI/CD process and therefore find and fix vulnerabilities faster.
In this post, you learned how to spot vulnerable Rails code and more importantly how to fix it. Open redirect vulnerability is not so popular anymore among hackers, but you shouldn't underestimate it. Attackers still use it as a possible attack vector when most popular vulnerabilities are not present. And with an open redirect, an attacker can steal your user credentials and bank details relatively easily. Therefore, we encourage you to check your Rails code.
Even better, let StackHawk do it for you on every CI/CD pipeline that you run. An automatic security scanner can help you avoid not only open redirect but also other popular vulnerabilities and can drastically improve the security of your application. If you want to learn more about dynamic application security testing, check out this blog post. And if you want to learn more about open redirect vulnerability itself, don't forget to read our main blog post about it here.
This post was written by Dawid Ziolkowski. Dawid has 10 years of experience as a Network/System Engineer at the beginning, DevOps in between, Cloud Native Engineer recently. He’s worked for an IT outsourcing company, a research institute, telco, a hosting company, and a consultancy company, so he’s gathered a lot of knowledge from different perspectives. Nowadays he’s helping companies move to cloud and/or redesign their infrastructure for a more Cloud Native approach.