ASP.NET 核心执行跨站点请求准备 (XSRF/CSRF) 对策

更新页 :
页面创建日期 :

环境

Visual Studio
  • Visual Studio 2019
ASP.NET酷
  • 3.0
  • 3.1

什么是跨站点请求伪造?

跨站点请求伪造 (CSRF/XSRF) 仅在原始目标站点中处理, 对从外部站点等执行更新处理等的漏洞的攻击。

例如,您能够在网站上发表评论。 通常,您将从该网站输入评论并发布。 在大多数情况下,此发送过程将数据发送到目标 URL 进行处理。

因此,如果您从目标站点以外的网站向 URL 发送类似的数据, 与发表评论相同。

如果只有攻击者这样做,它就不会成为太大的威胁。 CSRF 的可怕之处在于,攻击者通过构建模拟站点或将隐藏的 URL 嵌入到站点中来 其他用户无意中访问它,然后成为攻击者。

我们不会在这里进行深入讨论,因此请查看跨站点请求伪造的详细信息。

ASP.NET Core 将此功能集成到框架中。

查看跨站点请求伪造的工作原理

尝试查看更新过程是否实际从外部站点或工具执行。

在 Index.cshtml 中,创建一个输入表单,该表单将输入的文本发送到服务器。 然后,放置 ViewData 以显示服务器为输入文本创建的消息。

Index.cshtml

@{
  ViewData["Title"] = "Home Page";
}

<div class="text-center">
  <h1 class="display-4">Welcome</h1>
  <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

<form method="post">
  <input type="text" name="text" />
  <button type="submit">送信</button>
</form>

<p>@ViewData["Message"]</p>

服务器端 HomeController.cs 处理发送的文本并将其输出到 Visual Studio 跟踪中。 将相同的文本设置为 ViewData,以便客户端可以显示它们。

HomeController.cs

public class HomeController : Controller
{
  // 省略

  [HttpPost]
  public IActionResult Index(string text)
  {
    System.Diagnostics.Trace.WriteLine($"「{text}」が入力されました。");
    ViewData["Message"] = $"「{text}」が入力されました。";
    return View();
  }

  // 省略
}

尝试以正常方式完成您创建的功能。 执行调试运行并在屏幕出现时输入文本,然后单击"提交"按钮。

屏幕上将显示您期望的已处理文本。

由于跟踪也打印,因此文本也显示在 Visual Studio 的输出窗口中。 实际上,我们执行一些操作,例如在数据库中注册输入数据,但为了简化代码,我们省略了输入数据。

现在,尝试在调试程序时从目标站点外部访问它。 为了简化实现,我们将使用名为 Visual Studio 代码的工具发送 POST。 如果可以发送 POST,则可以安全地使用其他工具或为攻击构建单独的站点程序。

在 Visual Studio Code 中安装名为REST 客户端的扩展 只需打开 .http 文件,即可轻松验证 REST API 的行为。

在文本文件中创建 .http 文件,并在 Visual Studio Code 中打开该文件,如下所示: 您可以通过单击"发送请求"来发送 GET 或 POST。

创建以下 POST 数据时,将在屏幕上输入文本,然后按"发送"按钮发送几乎等效的数据。 (本地主机的端口号应适合执行环境。

RestTest.http

### Form で POST 送信
POST https://localhost:44372/home/index HTTP/1.1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="text"

なんらかのテキスト
------WebKitFormBoundary7MA4YWxkTrZu0gW--

发送时,您可以看到服务器端正在接收和处理文本。

Visual Studio Code 端可以获取结果。 如果您仔细查看结果代码,您将看到 ViewData 中设置的值。 (在 Unicode 中显示,但在 Web 浏览器中正确显示文本)

处理跨站点请求伪造漏洞

正如我在开头提到的,ASP.NET Core 包含了针对跨站点请求伪造的对策。 常见的对策是,在需要 POST 的屏幕上,必须提前向客户端颁发唯一令牌。 除非将令牌发送到服务器,否则不接受该令牌。

当然,如果您直接从外部站点访问 URL,则不接受令牌,因为令牌未知。

首先,我们是关于如何向客户端 (HTML) 颁发令牌,但实际上,这是框架的自动方法。 我会去的 在格式标记中指定 POST 方法等,以在 HTML 中包括令牌参数。

在下图中的 HTML 中,输入名称 = "__RequestVerificationToken" type="隐藏"部分。 按下"发送"按钮时,这一次一起发送到服务器。 顺便说一下,GET 方法不附加它。

对于服务器端,服务为 Startup.cs。 AddControllersWithViews 方法的选项。 到过滤器 只需设置AutoValidateAntiforgeryTokenAttribute,所有操作 此令牌检查将自动添加到 POST、PUT、PATCH 和 DELETE HTTP 方法中。

如果要将此限制附加到特定操作(而不是所有操作),请为每个控制器或每个操作添加此约束。 也可以设置。

相反,您希望对大多数操作施加约束,但您希望排除特定操作。 将 IgnoreAntiforgeryToken属性设置为控制器和操作,这是可以的。

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
  services.AddControllersWithViews(options =>
  {
    // 全ての「POST, PUT, PATCH, DELETE」アクションに自動で ValidateAntiForgeryToken を付与。
    // 個別に除外したい場合は「IgnoreAntiforgeryToken」属性を指定すること
    // API では HTML 側にトークンを発行できないのでコントローラーに「IgnoreAntiforgeryToken」を指定する必要がある。
    options.Filters.Add(new Microsoft.AspNetCore.Mvc.AutoValidateAntiforgeryTokenAttribute());
  });
}

现在,让我们看看它是如何工作的。 首先,通常从屏幕执行传输过程。

结果按预期反映在屏幕上。

还打印到跟踪。

现在,尝试从外部访问它。

已访问,但返回了坏请求。 与没有措施的结果不同。 您会发现它受到保护,因为它未输出到跟踪中。

总结

这一次,我们采取了措施,反对跨站点请求伪造。 实现非常简单,因为框架已经内置了它。

构建网站需要 CSRF 以外的许多漏洞防护。 或者,您可以使用 OWASP 等工具检查网站中的漏洞。