If you use ASP.NET forms authentication, you may be familiar with URLs like this one:
https://Example.com/Banking/login.aspx?ReturnUrl=%2fBanking%2fBalances.aspx
You will get this whenever you access "Balances.aspx" without a forms authentication cookie. ASP.NET will bounce you to the login page, but provide the ReturnUrl in the querystring so that it can redirect you back.
Unfortunately this introduces an unvalidated forward, which is an infraction of OWASP A10.
Imagine if I craft an email and spam it out... the email looks just like an email from your bank, and has a URL like this:
https://Example.com/Banking/login.aspx?ReturnUrl=https://Example.org/Banking/login.aspx
Notice I cleverly switched Example.com
with Example.org
which you might not notice. If I am very clever, I may even URL-encode the entire ReturnUrl using hex codes so that you don't see it coming. BTW I have an EV cert for Example.org
which means you will get no phishing error and will even get a nice green address bar. Unfortunately you won't be on the site you think you are on! On my version of the login page (which looks just like the real one), I will tell you that your password was wrong and you may enter it again, and voila I have just gotten your password.
Same scenario... I send an email which looks like it came from your bank. But your bank doesn't allow cross-domain redirects. Still, I can issue an attack with this URL:
https://Example.com/Banking/login.aspx?ReturnUrl=https://Example.com/Banking/Transfer.aspx?FromAcct=Checking&ToAcct=6273826&ToCountry=Nigeria&Amount=5000.00
The above looks bad, but remember I can mask the whole thing using URL-encoding, so it'll just look like hexadecimal junk.
When you click the link, you'll be prompted to sign on to your site, and then it'll immediately issue a transfer to my Nigerian account.
Seems to me that ASP.NET forms authentication is pretty widespread. How are developers mitigating this vulnerability?
How about using this to redirect the user away from the login page:
FormsAuthentication.RedirectFromLoginPage
There appears to be protections already build into the framework:
By default, the ReturnUrl variable must refer to a page within the current application. If ReturnUrl refers to a page in a different application or on a different server, the RedirectFromLoginPage methods redirects to the URL in the DefaultUrl property. If you want to allow redirects to a page outside the current application, you must set the EnableCrossAppRedirects property to true using the enableCrossAppRedirects attribute of the configuration element.
Example Code:
FormsAuthentication.SetAuthCookie(user.UserName, false);
FormsAuthentication.RedirectFromLoginPage(user.UserName, false);