URL Redirection – Attack and Defense
Table of Contents
URL Redirection is a vulnerability which allows an attacker to force users of your application to an untrusted external site. The attack is most often performed by delivering a link to the victim, who then clicks the link and is unknowingly redirected to the malicious website.
This vulnerability exploits the inherent trust that a user has in the legitimate domain. Since the victim is generally unaware of URL redirections; they are considerably more susceptible to phishing and social engineering attacks.
URL Redirection in Penetration Testing
For penetration testers, most instances of URL redirection will be fairly obvious. A smaller number, on the other hand, are a little more complex. Below are three common types of URL redirection pentesters should look out for.
Type 1 – Parameter Based URL Redirection
Parameter based URL redirection is the most common and easy to spot. There are two behaviors which contribute to this issue:
- A GET parameter containing a URL/URI.
- A 302/301 redirect made using that parameter.
So if you see a parameter passed in a URL before a page redirection, it’s a good idea to test if that can be modified with an arbitrary URL.
Type 2 – Session Restoration URL Redirection (2 step)
Ever click a link within an application, only to find out your session has terminated? Many applications will give the courtesy of preserving the last URL they viewed, and redirect them to that location after they authenticate. This feature is useful, but is commonly the source of URL Redirection vulnerabilities.
Example:
https://example.com/login?returnUrl=/dashboard
The above URL brings us to the login page, and instructs the server to store /dashboard
to redirect the user after authentication. This scenario can be tricky since the application does not immediately reflect the URL in a 302 redirect, but is stored and waiting for a successful authorization.
When we authentication the server redirects us back to our dashboard.
But as a penetration tester we should always test the following:
https://example.com/login?returnUrl=https://www.virtuesecurity.com
Now this brings us to the login page. After we authenticate, the server redirects us to the external site:
Not super exciting, but don’t worry, we can take this one step further.
URL Redirection with Cross-site Scripting (XSS)
Did you know that you can run JavaScript in your browser with a JavaScript: url handler? You can test this out:
You can also use this during a penetration test to turn URL redirection into XSS. Just replace the url with JavaScript:alert(1)
Type 3 – DOM Based URL Redirection
The third type of URL Redirection highlights the importance of a manual penetration test. There is unfortunately no automated solution for reliably detecting this. Tools like Burpsuite can provide assistance in identifying combinations of JavaScript sinks and redirection functions, but these are very often false positives.
To understand DOM-based open redirects, we have to first understand JavaScript sinks. Remember that JavaScript can obtain data directly from the browser. A URL in your web browser such as https://example.com/#dashboard
, does not send #dashboard
to the application. In fact, you can verify this with Burp:
However dashboard
is accessible to JavaScript already loaded in your browser by window.location.hash
. We can confirm this with the browser console:
If the page uses JavaScript such as the following:
// use substr() to remove the '#'
window.location = window.location.hash.substr(1)
This would be open redirection. An attacker could create a link https://example.com/#https://www.virtuesecurity.com
and phish example users! By using DOM attributes, this vulnerability may even be missed by pentesters who are only looking at Burp traffic.
URL Redirection Remediation
The vast majority of URL redirection vulnerabilities that we identify are generally considered “needless”. By needless, we mean these are redirects that only point to a small number of pages within an application. So if you don’t need to redirect users to a large number of external websites, you can probably change the scheme in which you redirect users to pages.
Mitigation Method 1: Whitelist URLs
If you don’t need to take the redirect via a query parameter then don’t take it. Instead, query your URLs by simpler numeric identifiers:
https://example.com/redirect?externalPage=1
https://example.com/redirect?externalPage=2
https://example.com/redirect?externalPage=3
If you are only redirecting users internally, use a page naming scheme:
https://example.com/redirect?page=dashboard
https://example.com/redirect?page=account
https://example.com/redirect?page=settings
Method 2: Regex
You may be inclined to use regex to validate URL parameters, however, extreme caution should be used here. Recently during a penetration test a client had implemented the following logic:
redirect_url = urlparse.urlparse(url)
if bool(re.search("^https://example.com", url)): # Vulnerable code
#redirect user
else:
# fail
Can you spot the vulnerability?
The following bypass could be used by an attacker:
https://example.com/redirect?page=https://example.com.evil-hackers.corp.com
To use regex it’s critical to use a trailing slash to prevent malicious use of subdomains:
redirect_url = urlparse.urlparse(url)
if bool(re.search("^https://example.com/", url)):
#redirect user
else:
# fail
This ensures you will not redirect to javascript URL handlers or unauthorized domains.
Mitigation Method 3: The unavoidable arbitrary URL
For applications where whitelisting is simply not feasible, we recommend at minimum filtering based on protocol handler. A regex such as ^https?://
can ensure you redirect only to websites (and not javascript:
handlers).
If your application is a secure authenticated application it is recommended that a “speed bump” is put in place. This would show a warning on screen that users are leaving to an external URL.
Conclusion
In conclusion, URL Redirection is not inherently bad, but you must take steps to ensure that users are both aware of external redirections that occur, and to minimize the locations where you redirect to when necessary to do so.