The last item on the OWASP Top 10 is A10 - Unvalidated Redirects and Forwards.
First - here is the risk rating from OWASP:
Threat Agents | Attack Vectors | Security Weakness | Technical Impacts | Business Impacts | |
---|---|---|---|---|---|
______ | Exploitability AVERAGE |
Prevalence UNCOMMON |
Detectability EASY |
Impact MODERATE |
______ |
Consider anyone who can trick your users into submitting a request to your website. Any website or other HTML feed that your users use could do this. | Attacker links to unvalidated redirect and tricks victims into clicking it. Victims are more likely to click on it, since the link is to a valid site. Attacker targets unsafe forward to bypass security checks. | Applications frequently redirect users to other pages, or use internal forwards in a similar manner. Sometimes the target page is specified in an unvalidated parameter, allowing attackers to choose the destination page. | Such redirects may attempt to install malware or trick victims into disclosing passwords or other sensitive information. Unsafe forwards may allow access control bypass. | Consider the business value of retaining your users’ trust. What if they get owned by malware? What if attackers can access internal only functions? |
The problem is that javascript sets document.location or does some other kind of redirect to a URL under the attackers control. The attacker can use this to launch attacks towards the user, who is more likely to click the link, because the hostname is to a trusted site.
A vulnerable server-side redirect will typically be a simple http handler that blindly redirects to a URL given as a parameter:
http://example.com/redirect.php?url=http://evil.com
As you can imagine it's rather simple to make this redirect to a phishing site, or even a javascript: url.
How do we do redirects in javascript? There is a decent list at the DOM XSS Wiki. Assignment of untrusted data to any of these can lead to trouble:
I highly recommend you read A Twitter DomXss, a wrong fix and something more from Minded Security. It starts with the following code:
//<![CDATA[
(function(g){
var a=location.href.split("#!")[1];
if(a){g.location=g.HBR=a;}
})(window);
//]]>
and shows how Twitter tried to address the problem - in multiple rounds.
Consider an application that does the following code where we try to limit our redirects to redirects on the same server:
var relativePath = document.location.hash.substring(1);
var re = new RegExp("^/[a-z0-9/.]+$");
if (re.test(relativePath)) {
document.location = relativePath;
}
At first we may think this is ok. We will allow things like /blog/test.html
. However we forgot about scheme less URLs like //www.insecurelabs.org
. If the URL starts with //, it inherits the scheme from the current URL. Broken.