如何避免打开重定向漏洞和安全重定向成功登录(提示:ASP.NET MVC 2默认代码易受攻击)?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (4)
  • 关注 (0)
  • 查看 (248)

通常情况下,当一个站点要求你登录之前,你可以访问某个页面将被带到登录屏幕,并且在成功验证身份之后,您将被重定向回原始请求的页面。 这对可用性很好 - 但是如果没有仔细的审查,这个功能很容易变成一个开放的重定向漏洞。

遗憾的是,对于此漏洞的示例,只需查看ASP提供的默认登录操作即可。NETMVC 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”(如果它是通过登录表单提交提供的)。

下面是一个利用此漏洞的简单示例攻击(实际上是许多攻击之一):

  1. 攻击者假装是受害者的银行,向受害者发送一封电子邮件,其中包含一个链接,如下所示:http://www.mybank.com/logon?returnUrl=http://www.badsite.com
  2. 在被告知要验证整个域名(例如,google.com=Good,google.com.as31x.example.com=bad)之后,受害者知道链接没有问题--没有任何棘手的子域钓鱼发生。
  3. 受害者点击链接,看到他们的实际熟悉银行网站,并被要求登录
  4. 受害者登录并随后被重定向到http://www.badsite.com这看起来就像受害者银行的网站,所以受害者不知道他现在在另一个网站上。
  5. http://www.badsite.com上面写着“我们需要更新我们的记录--请在下面输入一些非常个人的信息:SSN,地址,电话号码等“
  6. 受害者仍然认为自己在银行网站上,向攻击者提供了信息。

对于如何维护这种成功的重定向登录功能,还能避免打开重定向漏洞,有什么想法吗?

我倾向于选择将“back nUrl”参数拆分为控制器/动作部件,并使用“RedirectToRouteResult”而不是简单的“Redirect.ToRouteResult”。这种方法是否打开了新的漏洞?

通过将自己限制为控制器/操作路由,我不能重定向到自定义路由(例如/ backend / calendar / 2010/05/21)。 我知道通过将更多的参数传递给LogOn操作,我可以让它工作,但是我觉得我会一直重新审视这个方法 - 使它跟上我们的路由方案。 所以,而不是将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;
}
提问于
用户回答回答于

只要使用使用控制器和操作参数或路由名称的重定向变体之一,应该没问题,只要控制器方法具有足够的安全控制

这个概念是,无论你用于你的重定向必须通过路由引擎,并通过匹配一条路线进行验证。

但是我怀疑真正的漏洞是Cross-Site Scripting。 除非你的恶意用户可以在页面中注入一些Javascript,否则他们没有办法处理返回Url或其任何参数(因为你另外控制所有的服务器和浏览器代码)。

用户回答回答于

当用户未经过身份验证时,可以始终使用TempData保存上一页的记录,并使用该记录重定向到上一页而不是url参数。

用户回答回答于

是的,这是一个漏洞。 在重定向之前,需要将它传递给Uri对象来检查returnUrl字符串参数,并确保目标域与请求域相同。 你也应该考虑到returnUrl是/ admin这样的相对地址的情况。 在这种情况下没有问题,因为重定向将是相同的应用程序。

用户回答回答于

Jon Galloway写了一篇关于MVC 2(和1)的解决方案。

以下是应该帮助解决问题的片段::

private bool IsLocalUrl(string url)
{
    if (string.IsNullOrEmpty(url))
    {
        return false;
    }

    Uri absoluteUri;
    if (Uri.TryCreate(url, UriKind.Absolute, out absoluteUri))
    {
        return String.Equals(this.Request.Url.Host, absoluteUri.Host, 
                    StringComparison.OrdinalIgnoreCase);
    }
    else
    {
        bool isLocal = !url.StartsWith("http:", StringComparison.OrdinalIgnoreCase)
            && !url.StartsWith("https:", StringComparison.OrdinalIgnoreCase)
            && Uri.IsWellFormedUriString(url, UriKind.Relative);
        return isLocal;
    }
}

扫码关注云+社区

领取腾讯云代金券