views:

125

answers:

4

I have a multi-user ASP.NET MVC application. The users are not supposed to see or do anything with each other's data.

One of my controller actions is the obligatory POST to /Edit to edit a record (e.g. a contact). Now here is my problem: What if somebody forges a simple POST to /Edit (which automatically model-binds to my contact class) and edits somebody else's information? As each record is identified by Id, all that would have to be done is make a fake POST with Id XXX and then record # XXX would be overwritten with whatever the attacker supplied. How can I stop this?

The only thing I thought of is fetching the original instance every time first from the DB, check that it is in fact within the user's scope of editable objects (the ones he'd usually see to edit) and only if that check passes to proceed with UpdateModel and committing the update changes.

Is there a better way?

Edit: This is not a Cross Site/CSRF attack. Another logged in user can do this.

A: 

Loading the original record first and checking the owner sounds like a good approach to me. Alternatively you could add a hidden field containing the record ID and cryptrographically sign that field to make sure it can't be changed, or take the record ID, hash it using the user ID as a salt and check that (assuming you're using the membership providers you should use the provider unique ID, not the login name)

blowdart
+1  A: 

What you could do is exclude the ID in the model binding with this syntax:

 public ActionResult Edit([Bind(Exclude="Id")] User userToEdit)

and then fetch the ID from the current logged in user instead, so that it is only the logged in user that can edit his own items and noone elses.

Robban
Although you might also want to have an administrator who can go in and modify details of all users.
Zhaph - Ben Duguid
+1  A: 

Authorization for the view/page and authorization for the particular object are really two separate concepts. The best approach is problem to use an Authorize attribute in conjunction with the ASP.NET roles system to either grant or deny access to a given page. Once you have verified that the user has access to the page, then you can verify whether he has the permission he is requesting for the object on which he is requesting it. I use this approach in my application, and it works great. By using the Authorize filter first, it significantly improves performance since the actual object permission checking is a much heavier operation.

Also, I use a home brewed rules system to actually set and determine whether the user has access to the object. For example, in my system, administrators have full access to every object. (That's a rule.) The user who creates the objects has full access to the object (also specified by a rule). Additionally, a user's manager has full access to every thing his employees have access to (again specified by a rule.) My application then evaluates the object to see if any of the rules apply--starting with the lest complex rules first and then moving on to the more complex rules last. If any rule is positive, I discontinue rule evaluation and exit the function.

Anthony Gatlin
A: 

This question reminded me of an article that covers a similar issue (in light of URL manipulation attacks) that i had bookmarked. They deal with an authenticated user messing with the data of another user. You might find it useful: [link text][1]

Prevent URL manipulation attacks: http://www.superexperttraining.com/blog/archive/2008/06/26/prevent-url-manipulation-attacks.aspx

Jamie M