2

I somewhat understand how [ValidateAntiForgeryToken] prevents CSRF and I have read through this question, but I'm unsure whether this would prevent someone from falsifying the parameters for a form post.

ItemList has an Items property that is a collection of items and a User property that is a reference to the ApplicationUser that it belongs to. Item has an ItemList property that is a reference to the list it belongs to. Here are the Add methods in the ItemController:

// 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);
}

My question is whether [ValidateAntiForgeryToken] would prevent a user from falsifying the itemListId parameter during the post, or if I would need to put another if (itemList == null... check in the post method.

Edit: Here is the logic that I am looking at right now:

  • The use of ValidateAntiForgeryToken forces a user to access the first method (therefore loading the view) in order for a post to be accepted. If they don't load that view, then there will be no anti-forgery token.
  • The user will go to the form webpage (let's say http://foo.bar/Item/Add/3)
  • The user will fill out and submit the form, which would call the post method (in this case itemListId=3 because that's the webpage that was accessed)
  • There is no way for a user to pass a different itemListId to the above step, because it is passed by the webpage when they submit the form

Now, please let me know if there is something wrong with what I have stated above, or if that logic is correct (meaning that I don't need to check the validity of itemListId during the post). PLEASE give an example or a link to clarify where my logic is incorrect

Community
  • 1
  • 1
MisterEman22
  • 238
  • 2
  • 10
  • Who is the _someone_ and what do you mean by falsify? – Jasen Jan 15 '16 at 00:01
  • The *someone* is any user trying to add an item to a list that isn't theirs. By *falsify* I mean they try to post with `itemListId = x` where *x* is the ID of a list that isn't theirs. – MisterEman22 Jan 15 '16 at 00:07
  • No, you will need to validate data yourself. You need to check if a resource id belongs to the current authenticated user. – Jasen Jan 15 '16 at 00:39
  • 1
    _There is no way for a user to pass a different itemListId to the above step, because it is passed by the webpage when they submit the form_ This is false. You can use your browser's debug tools to alter form values. [**Never trust any input**](http://stackoverflow.com/questions/2794016/what-should-every-programmer-know-about-security). – Jasen Jan 15 '16 at 02:26
  • @Jasen I dont understand how the itemListId is a "form value". When it is in the URL is it just passed as another value in the form? – MisterEman22 Jan 15 '16 at 03:55
  • Doesn't matter. The value can be altered -- query string or form body. – Jasen Jan 15 '16 at 20:48
  • @Jasen if you could make an answer with an explanation of how someone would do that so I could test it to understand better, I would accept it – MisterEman22 Jan 16 '16 at 00:03
  • [Here's](http://stackoverflow.com/a/1655180/2030565) one way. – Jasen Jan 16 '16 at 00:05

4 Answers4

1

ValidateAntiForgeryToken dont prevent falsify, it prevent that the request becomes from another place.

The ValidateAntiForgeryToken check if __RequestVerificationToken exists in the form and validate it, so whatever params is in the body of the request, if the __RequestVerificationToken is invalid will break and dont returns a 200 OK, so to use it just put the Helper @Html.AntiForgeryToken() inside the form and the [ValidateAntiForgeryToken] filter in the action.

So see this article about that: How AntiForgeryToken works

Joel R Michaliszen
  • 4,164
  • 1
  • 21
  • 28
  • I understand how to use `ValidateAntiForgeryToken`. I am asking whether it would prevent someone from posting with an itemListId for a list that doesn't belong to them. – MisterEman22 Jan 15 '16 at 00:10
  • Sorry if i was not clear, but i answer that in the begining. – Joel R Michaliszen Jan 15 '16 at 00:17
  • I am only asking if it would prevent falsification in this specific case, not if it actively prevents falsification. – MisterEman22 Jan 15 '16 at 00:35
  • 1
    @MisterEman22 AntiForgeryToken doesn't care about the data going to the server, it ensures that the user that respond is the same that has requested the page. – Pedro Benevides Jan 15 '16 at 15:11
1

No. The ValidateAntiForgeryToken attribute has absolutely zero impact on the values each form field may contain. It also has absolutely no idea what data belongs to which user.

Sam Axe
  • 33,313
  • 9
  • 55
  • 89
  • My question doesn't relate to form fields, as the itemListId isn't a form field and I understand that it doesn't know what data belongs to which user. I will edit the question to try and clarify what I'm asking. – MisterEman22 Jan 15 '16 at 00:40
1

There is no way for a user to pass a different itemListId to the above step, because it is passed by the webpage when they submit the form

This is false. The AntiForgeryToken will not protect you from altered data.

  1. Make a GET request to Item/Add/4. I assume you will have a form on this page. You can include the @Html.AntiForgeryToken().

  2. Use your browser's debug tools to inspect the form.

    • Now you can edit the action attribute to directly modify Item/Add/5 the value.
    • Or modify any <input> field value.
  3. Put a debug break on your POST action and you will see the altered values when you submit the form.

The above is not the only way to tamper with the data. Therefore, you should always validate any input.

[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);
    }
    ...
}
Jasen
  • 14,030
  • 3
  • 51
  • 68
0

The CSRF attack consists in deceive victim to click in link or load a image where the URL is of a system that victim is logged, but attacker do not know the victim credentials.

The simple case, the attacker know that the HTTP GET request in the target system change some information. To attack, just send the e-mail or link to a user of the target system with a image where the URL point to the target system.

To prenvent this, a good pratice is do not create URL that make changes in data of the system through HTTP GET request.

In complex case, the attacker create a page with a form whose action point to a URL of the target system with POST method.

In this case, use the ValidateAntiForgeryToken is fundamental. Because the token generated by the target system is known only by the target system and can be validated.

So, the ValidateAntiForgeryToken only validate if the request was originated from the target system. Don't have any relationship with others parameters in the form.

Gean Ribeiro
  • 1,025
  • 2
  • 10
  • 23