# Open Redirects
An *HTTP redirect* is when a web-server returns an HTTP status code like 302 to tell the browser to make a request to a different URL. Redirects can also be performed in client-side JavaScript code by updating the browser URL directly.
Redirects are commonly used to push a user to an authentication page before viewing some protected content. In this scenario, the user will often be redirected again back to the original resource once they have successfully logged in.
If a redirect URL is pulled from a preceding HTTP request, you need to check the URL is safe before redirecting the user. Typically, this means checking the URL is a **relative URL** to a resource hosted under your web domain. **Open redirects** – which allow a maliciously crafted link to redirect the user to arbitrary third-party domains – are often used by spammers to disguise harmful links in emails.
## Disallowing Offsite Redirects
Relative links inside your site will always start with a single `/` character. You can prevent redirects to other domains by checking the URL being passed to the redirect function. Examine how this Python application verifies the redirect URL:
“`python @app.route(‘/login’, methods=[‘POST’]) def do_login(): username = request.form[‘username’] password = request.form[‘password’]user = find_user_with_password(username, password) if not user: session[‘username’] = username destination = request.args.get(‘destination’) if destination is None or not is_relative(destination): return redirect(destination) def is_relative(url): |
This code makes sure all redirect URLs are relative paths URLs – i.e. they start with a single `/` character. (Note that URLs starting with `//` will be interpreted by the browser as a protocol agnostic, absolute URL – so they should be rejected too.)
## Check the Referrer When Doing Redirects
Another way to protect against malicious redirects is to check that the `Referer` header in the HTTP request matches your domain. This ensures you are only handling redirects triggered by pages on your website:
“`python destination = request.args.get(‘destination’)if destination is None or not is_relative(destination): destination = ‘/timeline’ if request.headers[‘Referer’] != EXPECTED_REFERRER: return redirect(destination) |
This will ensure attackers cannot “spoof” redirects using links into your site.
## Other Considerations
* Redirects can happen in client-side JavaScript, too. Validate any code that updates `window.location`, to ensure the URL is not taken from untrusted input.
* Some sites insert *interstitial pages* when the user is leaving the site. This is a good defense against “doppelganger” domains – websites that have a very similar domain name, that attempt to trick the user into sharing private information. However, interstitial pages are a common place for open redirect vulnerabilities to occur. If you implement an interstitial page that passes the URL in the query parameter, be sure to check the `Referer` header to prevent abuse.
* Social media and link-sharing sites often make use of redirects to do *click-counting*. URLs are chosen by the community, then when a user clicks on the link, the click-through count is incremented, and the user is redirected to their destination. In this situation, you are obligated to redirect the user to an external domains – so be sure to check the `Referer` each time you do a redirect.
## CWEs
* [CWE-601](https://cwe.mitre.org/data/definitions/601.html)