ValideAntiForgeryToken是否可以防止伪造POST参数?

时间:2016-01-14 23:46:59

标签: c# asp.net-mvc security

我有点理解[ValidateAntiForgeryToken]如何阻止CSRF并且我已阅读this question,但我不确定这是否会阻止某人伪造表单帖子的参数。

ItemList有一个Items属性,它是一个项集合和一个User属性,它是对它所属的ApplicationUser的引用。 Item具有ItemList属性,该属性是对其所属列表的引用。以下是ItemController中的Add方法:

// GET: Item/Add/4 (Adds new Item to the ItemList with ID=4)
public ActionResult Add(int? itemListId)
{
    // Gets the current user and the ItemList that the Item will be added to
    UserManager<ApplicationUser> userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(db));
    ApplicationUser currentUser = userManager.FindById(User.Identity.GetUserId());
    ItemList itemList = db.ItemLists.Find(itemListId);

    // Makes sure that ItemList exists and belongs to the user
    if (itemList == null || itemList.User != currentUser)
    {
        return View("InsufficientPerm");
    }
    ViewBag.ItemListId = itemListId;
    return View();
}

// POST: Item/Add/4 (Adds new Item to the ItemList with ID=4)
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Add([Bind(Include = "ID,Name")] Item item, int? itemListId)
{
    if (ModelState.IsValid)
    {
        ItemList itemList = db.ItemLists.Find(itemListId);

        item.ItemList = itemList;
        db.Items.Add(item);
        itemList.Items.Add(item);
        db.SaveChanges();

        return RedirectToAction("Index");
    }
    return View(item);
}

我的问题是[ValidateAntiForgeryToken]是否会阻止用户在帖子中伪造itemListId参数,或者我是否需要在post方法中另外进行if (itemList == null...检查。

编辑:这是我现在正在看的逻辑:

  • 使用ValidateAntiForgeryToken强制用户访问第一个方法(因此加载视图)以便接受帖子。如果他们没有加载该视图,那么就没有防伪令牌。
  • 用户将转到表单网页(让我们说http://foo.bar/Item/Add/3
  • 用户将填写并提交表单,该表单会调用post方法(在这种情况下为itemListId=3,因为这是访问过的网页)
  • 用户无法将不同的itemListId传递给上述步骤,因为它在提交表单时由网页传递

现在,如果我上面所述的内容有问题,或者该逻辑是否正确(意味着我不需要在帖子中检查itemListId的有效性),请告诉我。 请举例说明或说明我的逻辑不正确的链接

4 个答案:

答案 0 :(得分:1)

  

ValidateAntiForgeryToken 不会阻止伪造,它会阻止请求来自其他地方。

ValidateAntiForgeryToken检查表单中是否存在__RequestVerificationToken并验证它,因此无论params在请求正文中,如果__RequestVerificationToken无效将会中断并且不会返回200 OK,所以要使用它只需将帮助 @Html.AntiForgeryToken()放在表单中,并将[ValidateAntiForgeryToken]过滤器放在操作中。

请参阅此文章:How AntiForgeryToken works

答案 1 :(得分:1)

没有。 ValidateAntiForgeryToken属性对每个表单字段可能包含的值的影响绝对为零。它也完全不知道哪些数据属于哪个用户。

答案 2 :(得分:1)

  

用户无法将不同的itemListId传递给上述步骤,因为它在提交表单时由网页传递

这是错误的。 AntiForgeryToken不会保护您免受更改数据的侵害。

  1. Item/Add/4发出GET请求。我假设你将在这个页面上有一个表格。您可以加入@Html.AntiForgeryToken()

  2. 使用浏览器的调试工具检查表单。

    • 现在,您可以修改action属性以直接修改Item/Add/5值。
    • 或修改任何<input>字段值。
  3. 在POST操作上设置调试中断,当您提交表单时,您会看到更改的值。

  4. 以上不是篡改数据的唯一方法。因此,您应始终验证任何输入。

    [Authorize, ValidateAntiForgeryToken]
    [HttpPost]
    public ActionResult NukeMyBankAccount(int accountId)
    {
        var account = db.GetAccount(accountId);
    
        // validate
        if (CurrentUser.Id != account.Owner.Id)
        {
            return RedirectToAction("Unauthorized");
        }
        else
        {
            db.NukeAccount(accountId, areYouSure: true);
        }
        ...
    }
    

答案 3 :(得分:0)

CSRF攻击包括欺骗受害者单击链接或加载图像,其中URL是受害者被记录的系统,但攻击者不知道受害者凭据。

简单的情况是,攻击者知道目标系统中的HTTP GET请求会更改某些信息。要进行攻击,只需使用URL指向目标系统的图像将电子邮件或链接发送给目标系统的用户。

为了预防这种情况,一个好的方法是不要创建通过HTTP GET请求更改系统数据的URL。

在复杂的情况下,攻击者使用表单创建一个页面,该表单的操作指向使用POST方法的目标系统的URL。

在这种情况下,使用ValidateAntiForgeryToken是根本。因为目标系统生成的令牌只能由目标系统知道并且可以进行验证。

因此,ValidateAntiForgeryToken仅验证请求是否源自目标系统。与表格中的其他参数没有任何关系。