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.
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
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.
Let’s say there’s a “well known” website -
https://example.com/. And let’s assume that there’s a link like
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
What happens if we change the
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
Here, the php code blindly grabs the url from
redirect_url parameter and redirects to that url using the
Location HTTP header.
Here, a jsp page takes the url from the parameter
u and blindly redirects it to the specified url.
We can assign the URL string to the
window’s object. This will cause a redirect. If there are no checks inplace, then it’s a bug.
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.
- Google is your friend, example query:
- 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
- Try with double forward slashes
firstname.lastname@example.org. In this case the interpretation will be like, the
target.comis the username and
attacker.comwill be the domain.
target.com/?image_url=attacker.com/.jpgif 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.comto bypass weak regex implementations.
- Chinese seperator 。 as the dot -
- Test for String reverser unicode(“\u202e”)
- No slashes
- Back slashes
- Different domain
redirect_url=.jpresulting in redirection of
target.com.jpwhich is not the same as
- Try some unicode(including emojis) madness
𝐀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!
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
If we tamper with the
redirect parameter and change it to
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
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
Then we can use this with the SSRF by adding the open Open Redirect url from above as the
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.
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.”
- 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
hmacif 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.
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
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
- 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 :)