预防 ASP.NET Core 中的开放式重定向攻击

重定向到通过请求(例如 querystring 或表单数据)指定的 URL 的 Web 应用可能会被篡改,从而将用户重定向到外部恶意 URL。 这种篡改称为开放式重定向攻击。

每当应用程序逻辑重定向到指定的 URL 时,你必须验证重定向 URL 是否未被篡改。 ASP.NET Core 的内置功能可帮助保护应用免受开放式重定向攻击。

什么是开放式重定向攻击?

当用户访问需要身份验证的资源时,Web 应用程序频繁将用户重定向到登录页面。 重定向通常包含一个 returnUrl querystring 参数,以便用户在成功登录后可以返回到最初请求的 URL。 在用户进行身份验证后,他们会被重定向到最初请求的 URL。

由于目标 URL 是在请求​​的 querystring 中指定的,因此恶意用户可能会篡改 querystring。 被篡改的 querystring 可能允许站点将用户重定向到外部恶意站点。 这种技术称为开放式重定向攻击。

攻击示例

恶意用户可以开发一种攻击,旨在让恶意用户能够访问用户的凭据或敏感信息。 为了开始攻击,恶意用户会诱使用户单击指向你的站点登录页面的链接,并将 returnUrl querystring 值添加到该 URL。 以 contoso.com 上的应用为例,该应用在 http://contoso.com/Account/LogOn?returnUrl=/Home/About 包含一个登录页面。 攻击遵循以下步骤:

  1. 用户单击指向 http://contoso.com/Account/LogOn?returnUrl=http://contoso1.com/Account/LogOn 的恶意链接(第二个 URL 是“contoso1.com”,而不是“contoso.com”)。
  2. 用户成功登录。
  3. 用户被站点重定向到 http://contoso1.com/Account/LogOn(一个看起来与真实站点完全相同的恶意站点)。
  4. 用户再次登录(向恶意站点提供凭据)并被重定向回真实站点。

用户可能认为他们的第一次登录尝试失败,第二次尝试成功。 用户很可能仍然不知道他们的凭据已泄露。

Open Redirection Attack Process

除了登录页面,一些站点还提供重定向页面或终结点。 假设你的应用有一个包含开放式重定向的页面 /Home/Redirect。 例如,攻击者可以在电子邮件中创建一个指向 [yoursite]/Home/Redirect?url=http://phishingsite.com/Home/Login 的链接。 普通用户查看该 URL,会发现它以你的站点名称开头。 出于信任,他们会单击该链接。 然后,开放式重定向会将用户发送到看上去与你的站点相同的钓鱼站点,并且用户可能会登录到他们认为是你的站点的站点。

预防开放式重定向攻击

开发 Web 应用程序时,将所有用户提供的数据视为不可信。 如果应用程序具有基于 URL 内容重定向用户的功能,请确保此类重定向仅在应用本地完成(或重定向到已知 URL,而不是 querystring 中可能提供的任何 URL)。

LocalRedirect

使用 LocalRedirect 基类中的 Controller 帮助程序方法:

public IActionResult SomeAction(string redirectUrl)
{
    return LocalRedirect(redirectUrl);
}

如果指定了一个非本地 URL,LocalRedirect 将引发异常。 否则,它的行为与 Redirect 方法相同。

IsLocalUrl

在重定向之前使用 IsLocalUrl 方法测试 URL:

以下示例演示如何在重定向之前检查 URL 是否是本地 URL。

private IActionResult RedirectToLocal(string returnUrl)
{
    if (Url.IsLocalUrl(returnUrl))
    {
        return Redirect(returnUrl);
    }
    else
    {
        return RedirectToAction(nameof(HomeController.Index), "Home");
    }
}

IsLocalUrl 方法可防止用户被无意重定向到恶意站点。 在应提供本地 URL 却提供非本地 URL 的情况下,你可以记录所提供的 URL 的详细信息。 记录重定向 URL 可能有助于诊断重定向攻击。