Kotlin Open Redirect
Guide: Examples
and Prevention

stackhawk

StackHawk|November 16, 2021

In this article, we'll dive into Kotlin open redirect. We will explore the vulnerabilities that one can find in platforms lacking security.

In the interest of providing robust solutions for the ever-evolving needs of our users, we developers must keep our skillsets sharp and updated. Building solutions that stand the tests of the modern web and its threats is simply not a one-person task anymore. Moreover, protecting our platforms from the vast catalog of threats is unquestionably a daunting responsibility that requires years of experience. But don't be intimidated. Resources exist all over the web to help those who need guidance.

The objective of this article is to provide guidance on open redirect vulnerabilities. We will explore the many vulnerabilities that one can find in platforms lacking proper security measures and how to mitigate them effectively. And we'll keep our examination of open redirect brief and limit the scope to the Kotlin and Spring boot development stack. If you want to explore open redirect further, you can read our in-depth article.

We assume you already have some background knowledge of the Kotlin and Spring development stack. If that's not the case, Spring has published some great introductory material.

Kickstarting Our Demo Site

Before we tackle open redirect, we want to make sure your environment is ready. So let's start by crafting a demo site in Spring boot using the start.spring.io tool.

Note: If you want to get straight to the point, feel free to skip to the next section.

If you already have your environment ready to work with Java and have an IDE set up and ready, we can proceed to https://start.spring.io and set up our project. Again, remember to select "Spring Web" as your dependency before downloading your boilerplate project.

After the download completes, proceed to the src/main/java/com/example/demo folder and create a class file called HomeController.kt and input the following code:

package com.example.blog 

import org.springframework.stereotype.Controller

import org.springframework.ui.Model 
import org.springframework.ui.set 
import org.springframework.web.bind.annotation.GetMapping 

@Controller 
class HomeController { 
    @GetMapping("/")
    fun home(model: Model): String { 
        model["title"] = "Blog" 
        
        return "home" 
    } 
}

Then proceed to the src/main/resources/templates folder and corresponding header and footer templates. Notice that we have chosen the mustache template syntax. You can, however, make them in the syntax of your preference.

header.mustache
<html> 
    <head> 
        <title>{{title}}</title> 
    </head> 
    
    <body>
footer.mustache
   </body> 
</html>
home.mustache
{{> header}} 

<h1>{{title}}</h1> 

<p>This is a test blog.</p> 

{{> footer}}

That's all you need.

Now run the code by typing "gradle bootRun" in the terminal and see your website on localhost:8080.

Kotlin Open Redirect Guide: Examples and Prevention image

You can proceed to the Spring Boot tutorial page for more information on this particular example and the whole code.

What Is Open Redirect?

Understanding open redirect requires knowing what redirects are. Essentially, redirects are the way servers move the user from one page to another. Thus, redirects serve as a tool for developers to ensure that their users follow the proper flow of predefined use cases.

The primary purpose of redirects is to provide continuity in navigation for functionality purposes. Additionally, they are used as a contingency against the incursion into an incorrect or unauthorized address. 

Clearly, redirects provide vital functionality for the web. That's why they're a prime target for an attacker hoping to mislead users to malicious sites.

Open redirect attacks happen when an unvalidated URL, usually provided by a bad actor, is not adequately validated. As a result, users clicking on links using these malicious URLs end up redirected to malicious websites. Attackers rely on these vulnerabilities in phishing scams and when attempting to steal a visitor's credentials.

Examples of Open Redirect Attacks

So what does a malicious URL look like? Well, something like this:

http://mysafesite.com/page.php?to_url=http://attackersite.com

OK, so we can see at a glance that the vulnerable site mysafesite.com contains a "page" that includes a feature that receives user input, in this case a URL, in the query string and uses it to redirect the user.

Kotlin Open Redirect Guide: Examples and Prevention image

If you were to click on this link, the browser would redirect you to the legitimate website. 

Great, right? 

Yeah, but if the target server does not correctly validate the provided URL, it will redirect you to the URL provided as a query string. In this case, the site happens to be a malicious site controlled by the attacker. 

Additionally, since the original URL contains a safe-looking URL, the attacker could easily fool you about the intention of the attack. 

Subsequently, once you land on the attacker's site, the attacker can disguise the site to look just like the target site and ask for credentials. Ultimately, the attacker will redirect you to the legitimate site after obtaining your credentials.

Kotlin Open Redirect Guide: Examples and Prevention image

This is not the full extent of open redirect vulnerabilities. Despite the low level of sophistication, open redirect attacks are usually bundled with phishing and cross-site scripting.

Now let's look at the different types of open redirect attacks.

Header-Based Open Redirect

Header-based open redirect attacks exploit vulnerable code by attacking the user input. These attacks depend on social engineering tactics and the redirect mechanism in the platform. Moreover, no JavaScript is required for this attack.

JavaScript-Based Open Redirect

JavaScript-based open redirects happen when part of the redirect requires executing JavaScript. Accordingly, redirects of this kind do not work for server-side functions.

Mitigating Open Redirect Vulnerabilities

The best way to mitigate open redirect vulnerabilities is to do away with redirects. Unfortunately, this means we have to rethink our approach to solutions that rely on redirection.

This course of action might not be viable for you. Still, we want to stress that even if you think you need redirection, you might not. There are modern, reliable, and safe ways to provide the same functionality. 

Nevertheless, we will offer some alternatives.

Limiting Destinations

Limiting the possible redirection destinations available to users can go a long way toward preventing attacks. 

Additionally, using fixed options in your application makes it harder for these exploits to work.

Sanitizing Input

Parsing and sanitizing user inputs can weed out many of the attacks the application could be subject to. For example, if the user is not supposed to navigate out of your domain but tries to anyway, that is a red flag.

A simple implementation of this solution on Spring boot would look like the following:

private val BASE_PATH: String = "http://mysafesite.com/"
private val VALID_PATHS = HashSet<String>(arrayOf("/profile", "/photos", "/music").asList());

fun redirectTo(path: String): String { 
    var normalized_path: String = Paths.get(path).normalize().toString()

    if (VALID_PATHS.contains(normalized_path)) {
        return "redirect:" + BASE_PATH + normalized_path;
    } else { 
        return "Access Error"; 
    }
}

Notice that we are verifying that the user input is in the safelist with a simple match. However, you can implement a more robust and complex matching solution with a RegEx.

Additionally, we explicitly indicate the URL's domain in the redirect. This way, if the attacker manages to exploit the safelist for some reason, the attack will not succeed in taking the user away from your domain.

Beyond these strategies, implementing system-wide solutions like firewalls and redirection notices is recommended.

Find and Fix Security Vulnerabilities

In Conclusion

Finally, we want to stress the importance of regular penetration tests, security audits, and keeping libraries updated. Unfortunately, doing this extra work can be complex and time-consuming. That's why we encourage you to consider StackHawk.

StackHawk tests your production-ready applications, services, and APIs for security vulnerabilities that your team might have introduced. Additionally, it searches for exploitable open source security bugs and suggests actionable solutions to mitigate them.

Please follow this link if you want to read more about our solution and start providing sound and reliable protection for your platforms.

This post was written by Juan Reyes. Juan is an engineer by profession and a dreamer by heart who crossed the seas to reach Japan following the promise of opportunity and challenge. While trying to find himself and build a meaningful life in the east, Juan borrows wisdom from his experiences as an entrepreneur, artist, hustler, father figure, husband, and friend to start writing about passion, meaning, self-development, leadership, relationships, and mental health. His many years of struggle and self-discovery have inspired him and drive to embark on a journey for wisdom.


StackHawk  |  November 16, 2021