ASP.NET MVC - GET请求上的CSRF

本文关键字:CSRF 请求 GET NET MVC ASP | 更新日期: 2023-09-27 18:35:12

我们有一个 ASP.NET 的MVC应用程序。所有 POST 请求(表单提交)都已通过使用 @Html.AntiForgeryTokenValidateAntiForgeryToken 属性受到 CSRF 保护。控制器上的操作方法之一是 GET,它将报告返回给用户(包含来自数据库的数据的 pdf 文件)。签名为:

[AcceptVerbs(HttpVerbs.Get)]
public ActionResult GetReport()
{
    // get data from db
    return GetReport();
}

以下是我针对此操作测试 CSRF 的步骤:

  1. 用户登录到应用程序
  2. 登录后,用户打开以下HTML文件并单击"提交"按钮:
  3. 报告将下载。

问题:

这可以被视为CSRF攻击吗?

如果是,如何缓解?由于操作方法是GET请求,我如何使用MVC的CSRF方法(在操作方法上应用@Html.AntiForgeryTokenValidateAntiForgeryToken)。

文件:

<html>
      <body>
        <form action="https://<baseurl>/Analysis/GetReport">
                <input type="submit" value="Submit request" />
            </form>
          </body>
</html>

ASP.NET MVC - GET请求上的CSRF

简而言之,您刚才描述的不是XSRF攻击的示例...


什么是 XSRF 攻击?

CSRFXSRF都用于描述所谓的Cross Site Request Forgery。这是恶意网站利用您在另一个网站上的身份验证状态来执行欺诈性跨站点请求的地方。

示例:网上银行。

银行

想象一下,您正在银行的网站上authenticated,并且您的银行网站包含创建新交易的form,一切都非常简单......

<!-- Your bank -->
<form action="/send_moneh" method="POST">
    <input type="text" name="amount" />
    <input type="text" name="accountNumber" />
    <input type="submit" value="Send Money" />
</form>
恶意网站

现在让我们想想您也正在访问的Malicious website,想象一下它还包含一个 form ,一个隐藏的,其值是预先填充的......

<!-- Malicious website -->
<form action="http://yourbank.com/send_moneh" method="POST">
    <input type="hidden" name="amount" value="100.00"/>
    <input type="hidden" name="accountNumber" value="123456" />
</form>

提交恶意网站上的表格后,HTTP request将直接从您发送到您的银行,并且由于您在银行网站上进行了身份验证,因此交易可能会被接受。

从本质上讲,攻击者通过伪造请求并使用您作为传递该请求的信使来对您使用自己的身份验证。


如何预防?

您使用防伪令牌,此token是一个包含随机值的字符串,除了HTML表单外,令牌还放置在您的cookies中。

当您收到请求时,您将验证表单是否包含防伪令牌,以及它是否与存储在 Cookie 中的令牌匹配。恶意站点无法看到您的网站在客户端上设置的令牌,如果没有此信息,XSRF 攻击就会停止。


如何在 MVC ASP.NET 实现它?

在将处理请求的控制器操作上,添加属性 [ValidateAntiForgeryToken] ,然后在 HTML 表单中添加(@Html.AntiForgeryToken())

public class ExampleController : Controller
{
    [ValidateAntiForgeryToken]
    [HttpPost]
    public ActionResult Test(Foo fooModel)
    { 
        // do your thing...
        return this.View();
    }
}

<form action="/Example/test" method="POST">
    @Html.AntiForgeryToken()
    <input type="text" name="bar" />
    <input type="submit" value="Submit" />
</form>

就是这样!


提示/指针/建议

防伪令牌在执行GET请求时没有多大意义,事实上,将它们放在您不修改和持久化数据的任何位置都没有意义,因为任何 GET 请求都将返回给您的用户,而不是攻击者。

如果您正在创建、更新或删除数据...确保您正在使用它。

通常,

安全的方法不必针对 CSRF 进行保护,因为它们不会对应用程序进行更改,即使它们返回敏感信息,也将受到浏览器中的同源策略的保护。

如果您的网站按照标准实施,则您的GET请求应该是安全的,因此不需要保护。

但是,在一种特定情况下,可能会执行"跨站点 DoS"* 攻击。假设您的报告页需要 10 秒才能执行,数据库服务器上的 CPU 使用率为 100%,Web 服务器上的 CPU 使用率为 80%。

您网站的用户知道永远不要在办公时间内访问https://<baseurl>/Analysis/GetReport,因为它会杀死服务器并给其他用户带来糟糕的用户体验。

但是,Chuck想将您的<baseurl>网站离线,因为他不喜欢您或您的公司。

在他经常发帖的繁忙论坛上,http://forum.walkertexasranger.example.com,他将自己的签名设置为以下内容:

<img src="https://yoursite.example.org/Analysis/GetReport" width=0 height=0 />

他还知道贵公司的员工经常访问论坛,同时经常登录yoursite.example.org

每次您的员工阅读 Chuck 的帖子之一时,身份验证 cookie 都会发送给https://yoursite.example.org/Analysis/GetReport,因此您的站点处理请求并生成报告,并且您的系统会脱机,因为 CPU 被这些持续的请求吞噬。

因此,即使该请求是GET请求并且不会对您的系统进行任何永久性更改(也称为"安全"),它实际上每次运行时都会使您的系统瘫痪。因此,最好用一些CSRF预防方法来保护它。最简单的方法是转换它,以便只能通过 POST 请求生成报告,因此可以通过 AntiForgeryToken 验证请求。

*XSDoS或跨站点拒绝服务是我创造的一个短语,所以不要去谷歌搜索它。