通常,当网站要求您先登录才能访问某个页面时,您将被带到登录屏幕,在成功验证自己的身份后,您将被重定向回最初请求的页面。这对于可用性来说非常有用 - 但如果不仔细审查,此功能很容易成为一个打开重定向 http://www.owasp.org/index.php/Open_redirect脆弱性。
遗憾的是,对于此漏洞的示例,只需查看 ASP.NET MVC 2 提供的默认登录操作即可:
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid) {
if (MembershipService.ValidateUser(model.UserName, model.Password)) {
FormsService.SignIn(model.UserName, model.RememberMe);
if (!String.IsNullOrEmpty(returnUrl)) {
return Redirect(returnUrl); // open redirect vulnerability HERE
} else {
return RedirectToAction("Index", "Home");
}
} else {
ModelState.AddModelError("", "User name or password incorrect...");
}
}
return View(model);
}
如果用户成功通过身份验证,他们将被重定向到“returnUrl”(如果它是通过登录表单提交提供的)。
下面是一个利用此漏洞的简单攻击示例(实际上是众多攻击之一):
- 攻击者冒充受害者的银行,向受害者发送一封包含链接的电子邮件,如下所示:
http://www.mybank.com/logon?returnUrl=http://www.badsite.com
- 在被教导如何验证整个域名(例如,google.com = GOOD,google.com.as31x.example.com = BAD)后,受害者知道链接没问题 - 不存在任何棘手的子域网络钓鱼在。
- 受害者点击链接,看到他们的actual熟悉的银行网站并被要求登录
- 受害者登录并随后被重定向到
http://www.badsite.com
该网站看起来与受害者银行的网站一模一样,因此受害者不知道他现在在不同的网站上。
-
http://www.badsite.com
内容类似于“我们需要更新我们的记录 - 请在下面输入一些极其个人的信息:[ssn]、[地址]、[电话号码]等。”
- 受害者仍然认为自己在访问自己的银行网站,因此中了骗局并向攻击者提供了信息
关于如何维护成功登录重定向功能并避免开放重定向漏洞有什么想法吗?
我倾向于选择将“returnUrl”参数拆分为控制器/操作部分,并使用“RedirectToRouteResult”而不是简单的“Redirect”。这种方法会带来新的漏洞吗?
Update
通过将自己限制在控制器/操作路线上,我无法重定向到自定义路线(例如/backend/calendar/2010/05/21
)。我知道通过向 LogOn 操作传递更多参数,我could让它工作,但我觉得我将永远重新审视这个方法——使其与我们的路由方案保持同步。因此,我没有将 returnUrl 拆分为其控制器/操作部分,而是按原样保留 returnUrl 并解析它以确保它仅包含相对路径(例如,/users/1
)而不是绝对路径(例如,http://www.badsite.com/users/1
)。这是我正在使用的代码:
private static bool CheckRedirect(string url) {
try {
new Uri(url, UriKind.Relative);
}
catch (UriFormatException e) {
return false;
}
return true;
}
旁注:我知道与 XSS 和 CSRF 之类的技术相比,这种开放重定向似乎没什么大不了的,但我们的开发人员是保护我们的客户免受坏人侵害的唯一力量 - 我们可以采取一切措施来阻止坏人在我看来,更加努力的工作就是胜利。
谢谢,布拉德