I have a project I'm working on, and I recently decided to add a "login bounceback" to my site. The idea is simple, and very common: The user is browsing the site, and runs into something they need to log in for. After logging in, they are bounced back to where they were before.
This is, of course, ridiculously easy to implement. My login link just provides the original location in a query variable, and my login page redirects to that location after success using a "Location:" header. This is very simple, and doesn't require any server-side state.
However, I've always got security on the mind, especially for my users, so I want to take steps to protect them from being redirected to arbitrary places. (See https://www.owasp.org/index.php/Top_10_2010-A10-Unvalidated_Redirects_and_Forwards)
My solution for this is very simple: after reading the query variable, if the URL doesn't begin with "/", I reject it. (The user gets sent to a default page instead.) This is based on the reasoning that a relative URL must point back to my site, and the only URLs that can start with "/" are relative. My site will only ever generate relative URLs , so I'm fine with this rather restrictive scheme. (Additionally, under this scheme, I can easily make it even tighter by prepending the protocol and my domain to the URL. I could even whitelist other domains later.)
Is redirecting only to URLs that start with "/" sufficient validation? Is there some way this could be abused to send a user somewhere outside my site? If so, how could I prevent it?
Some more context: I'm using PHP, but I don't think that's really important to the core of the question. The site does access checks on all pages, and all urls that cause an action are protected from CSRFs, so the user can be sent to anywhere on my site without negative consequences.
There appear to be two main dangers to Unvalidated Redirects:
- The request pointing to another possibly malicious site, possibly allowing XSS, or giving the user a false sense of safety.
- The request pointing to a sensitive URL on your own site, such as a URL that takes an action. (The same type of that is sensitive to a CSRF.)
However, I believe I've prevented these problems: - My script only allows redirection to my own site, meaning I only need to protect against dangerous URLs on my own site. On that note... - I'm already building my site to be hardened against CSRFs, so there shouldn't be any dangerous URLs to exploit. (Not even a logout URL.) Even if the user is sent to "interesting.php", nothing will happen, due to the request being malformed. (Any action on the site requires deliberate user action.) I'll be stripping query strings from the URL as well, although I don't use them for anything important.
So it seems to me that the worst thing that could happen with a manipulated URL is the user being sent to an unexpected page. (Or perhaps a 404.) Is this reasoning flawed?