TL;DR
This post talks about Open/Unvalidated Redirects and Forwards. You’ll learn what they are, how to find them, how to exploit them, and how to fix them.
Things to Note
- Read the Disclaimer before reading this post.
- Basic knowledge about the HTTP is required.
- If you have some programming knowledge, it helps too, because we’ll be looking at some code in this post.
Introduction
What are Redirects?
Redirect means allowing a website to forward the request for the resources to another URL/endpoint. Let’s assume that you make a request to apple.com
and apple.com can redirect you to another website(new-apple.com
), so you’ll end up at new-apple.com
even though the original request was made for apple.com
. This is called “redirection”. There are different types of redirects in HTTP, check em out below.
Redirection Status Code - 3xx
- 300 Multiple Choices
- 301 Moved Permanently
- 302 Found
- 303 See Other
- 304 Not Modified
- 305 Use Proxy
- 307 Temporary Redirect
- 308 Permanent Redirect
The redirection can happen on the server-side or the client side.
Server-Side: Request to redirect is sent to the server, then the server notifies the browser to redirect to the url specified via the response.
Client-Side: Browser is notified to redirect to the url specified directly without the intervention of the server.
What are Open Redirects?
Open redirect is basically what the name says, Openly allow Redirects to any website.
Why is this an issue?
Well this is bad right off the bat, think about it for a moment, what if apple.com
, a TRUSTED website allows you to redirect to any other website. Then a malicious user can simply redirect apple.com
to attacker.com
, and people fall for it all the time believing that it’s trusted, but infact, it’s not. So allowing redirects to any website without a stop in the middle or without a proper notification for the user is Bad.
Explanation
Let’s say there’s a “well known” website - https://example.com/
. And let’s assume that there’s a link like
https://example.com/signup?redirectUrl=https://example.com/login
This link is to a sigup page, once you signup, you get redirected to https://example.com/login
which is specified in the HTTP GET Parameter redirectUrl
.
What happens if we change the example.com/login
to attacker.com
?
https://example.com/signup?redirectUrl=https://attacker.com/
By visiting this url, if we get redirected to attacker.com
after the signup, this means we have an open redirect vulnerablility. This is a classic open redirect and often used for phishing(Refer Exploitation section for more info).
Why does this happen?
This happens due to insufficient redirection checks in the back-end, which means the server is not properly checking if the redirect URL is in their whitelist or not. Here are some examples of vulnerable code
PHP (Server-Side)
<?php
$url_to_redirect = $_GET['redirect_url'];
header('Location: ' . $url_to_redirect);
die();
Here, the php code blindly grabs the url from redirect_url
parameter and redirects to that url using the Location
HTTP header.
Java (Server-Side)
response.sendRedirect(request.getParameter("u"));
Here, a jsp page takes the url from the parameter u
and blindly redirects it to the specified url.
Javascript (Client-Side)
window.location.href = "https://attacker.com";
We can assign the URL string to the location.href
of window
’s object. This will cause a redirect. If there are no checks inplace, then it’s a bug.
HTML (Client-Side)
<meta http-equiv="refresh" content="0;URL='http://attacker.com/'" />
HTML Meta tags can refresh the site with the given url as it’s content
and also you can specify the refresh delay time.
How to find them?
- Visit every endpoint of the target to find these “redirect” parameters.
- View your proxy history, you might find something. Make sure to use filters.
- Bruteforcing helps too.
- You might uncover many endpoints by reading javascript code.
- Google is your friend, example query:
inurl:redirectUrl=http site:target.com
- Understand and analyze where the redirection is needed in the target application like redirecting to dashboard after login or something like that.
Some Magic tricks
- Test for basic modification of the url like
target.com/?redirect_url=https://attacker.com
. - Try with double forward slashes
target.com//attacker.com
. - Try
target.com/@attacker.com
. In this case the interpretation will be like, thetarget.com
is the username andattacker.com
will be the domain. - Test for javascript Protocol
javascript:confirm(1)
. - Try
target.com/?image_url=attacker.com/.jpg
if there’s an image resource being loaded. - Try IP address instead of the domain name.
- You can go further in terms of representing the IP in decimal, hex or octal.
- You can also try
target.com/?redirect_url=target.com.attacker.com
to bypass weak regex implementations. - Chinese seperator 。 as the dot -
https://attacker%E3%80%82com
. - Test for String reverser unicode(“\u202e”)
target.com@%E2%80%AE@attacker.com
. - No slashes
https:attacker.com
. - Back slashes
http:/\/\attacker.com
orhttps:/\attacker.com
. - Different domain
redirect_url=.jp
resulting in redirection oftarget.com.jp
which is not the same astarget.com
. - Try some unicode(including emojis) madness
t𝐀rget.com
or𝐀ttacker.com
(‘𝐀’ is “\uD835\uDC00”). - There are a lot more, please refer the Cool Finds & Cheat Sheets section of this article. If you want more tricks, DISCOVER EM!
Exploitation
Phishing
Assume that the target is example.com
. It has a password recovery page at example.com/forgot-password
. You enter the email and you click on Forgot Password button, and it’ll send you an email with a password reset link, and this link might look like
https://example.com/reset-password/some-random-token?redirect=https://example.com/login
If we tamper with the redirect
parameter and change it to
https://example.com/reset-password/some-random-token?redirect=https://attacker.com/login
This redirects the user to an evil login page instead if the original one and the user can be phished.
Chaining with SSRF
If you don’t know about SSRF, you might wanna google that, I’ll be dropping another post specifically about SSRFs, so stay tuned.
Anyways, let’s say that we have a target - example.com
and you’ve found an SSRF bug on https://example.com/?get-image=https://images.example.com/cat.jpg
. Basically we want to force the server to make a request on behalf of us. We can change the get-image
parameter value and the server makes a request to this endpoint. But in this case, it restricts the requests to its own (sub)domain(s) like images.example.com
.
That means you can make the request to *.example.com
(Any subdomain) as the server and can’t access anything outside this scope.
Let’s say you’ve also found an Open Redirect bug on https://test.example.com/redirect_url=https://www.example.com/
, now you can chain them together to make the SSRF work for any domain like
First we craft the Open Redirect bug by modifying the redirect_url
parameter
https://test.example.com/?redirect_url=https://www.attacker.com/
Then we can use this with the SSRF by adding the open Open Redirect url from above as the get-image
parameter.
https://example.com/?get-image=https://test.example.com/?redirect_url=https://www.attacker.com/
Now this will make the server make a request to one of it’s own subdomain(test.example.com
) and then it is redirected to attacker.com
making the SSRF bug work.
------------- -------------------- ----------------
==> | get-image | ==> | test.example.com | ==> { REDIRECTS } ==> | attacker.com |
------------- -------------------- ----------------
Like this Open Redirects can be used in many ways, I can’t discuss all of em, it just depends on the target.
“you are only limited by your imagination.”
Mitigation
- Only use redirects if you really want em.
- If you want to use them, make sure you properly check the whitelisted domains and allow the matched ones.
- You can also use
hmac
if you wanted to, but it’s quite easy to f*ck this up with it(length extension attacks), so dont over complicate things, use proper whitelisting.
Cool Finds
These are the list of all unique Open Redirect Reports on HackerOne that I could find from the top 20 pages of Google results.
- [Report-226408] Open Redirect on Shopify
- [Report-211213] Open Redirect on Nextcloud
- [Report-246897] Open Redirect on Twitter
- [Report-103772] Open Redirect on Shopify
- [Report-309058] Open Redirect on Wordpress
- [Report-260744] Open Redirect and XSS on Twitter
- [Report-320376] Open Redirect on HackerOne
- [Report-111968] Interstitial redirect bypass / Open Redirect on HackerOne Zendesk Session
- [Report-244721] Open Redirect on Mail.Ru
- [Report-236599] Open Redirect on ExpressionEngine
- [Report-299403] Open Redirect on HackerOne
- [Report-239503] Open Redirect & Information Disclosure on HackerOne
- [Report-210875] Open Redirect via Host Header
- [Report-119236] Open Redirect on Uber
- [Report-126203] Open Redirect on Uber
- [Report-28865] Open Redirect Filter bypass on HackerOne
- [Report-144525] Open Redirect bypass on New Relic
- [Report-104087] Open Redirect bypass using svg on Slack
- [Report-179568] Open Redirect via window.opener on Open-Xchange
- Open Redirect to RCE on Google Hangouts Electron app & RCE Tweet
Cheat Sheets
This list might not be unique, download em all, clean duplicates and sort em.
- EdOverflow Open Redirect CheatSheet
- cujanovic Open Redirect Payloads
- fuzzdb Redirect Url Templates
- ak1t4 Open Redirect Payloads
- random robbie Open Redirect Payloads
- OWASP Unvalidated Redirects and Forwards Cheat Sheet
Resources
- Open Redirect by zseano
- Open Redirect by SI9INT
- Using Burp to Test for Open Redirections
- Detectify Unvalidated Redirects and Forwards
- Open redirects that matter
- Client Side URL Redirections
- Fun With Redirects 2010
That’s all for now folks. Thank you for reading. Have a great day :)
– s0cket7