ASP.NET MVC - 关于GET请求的CSRF

Fur*_*ikh 13 c# security asp.net-mvc csrf

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

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

}
Run Code Online (Sandbox Code Playgroud)

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

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

问题:

这可以被视为CSRF攻击吗?

如果是的话,如何减轻它?由于action方法是GET请求,我如何使用MVC的CSRF方法(应用@Html.AntiForgeryTokenValidateAntiForgeryToken操作方法).

HTML文件:

<html>
      <body>
        <form action="https://<baseurl>/Analysis/GetReport">
                <input type="submit" value="Submit request" />
            </form>
          </body>
</html>
Run Code Online (Sandbox Code Playgroud)

Ayd*_*din 19

简而言之,您刚才描述的并不是 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>
Run Code Online (Sandbox Code Playgroud) 恶意网站

现在让我们想起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>
Run Code Online (Sandbox Code Playgroud)

当提交恶意网站上的表单时,HTTP request会直接从您的银行发送到您的银行,并且由于您在银行的网站上进行了身份验证,因此可以接受该交易.

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


怎么预防呢?

您使用防伪标记,这token是一个包含随机值的字符串cookies,除了您的HTML表单之外,该标记也会放在您的标记中.

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


如何在ASP.NET MVC中实现它?

在您的控制器上将处理请求的Action,添加属性[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>
Run Code Online (Sandbox Code Playgroud)

而已!


提示/指针/建议

防伪标记在执行GET请求时没有多大意义,事实上,将它们放在您未修改和保留数据的任何地方都没有意义,因为任何GET请求都将返回给您的用户,不是攻击者.

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


Sil*_*Fox 7

通常安全的方法不必受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 />
Run Code Online (Sandbox Code Playgroud)

他也知道你的公司员工经常在论坛上,经常同时登录yoursite.example.org.

每当Chuck的一个帖子被您的员工读取时,身份验证cookie就会被发送到https://yoursite.example.org/Analysis/GetReport,因此您的站点会处理请求并生成报告,并且您的系统会因为CPU被这些常量请求吃掉而脱机.

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

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