In today's blog post, I am going to discuss the over posting attack in MVC application.
Let's take a look at an example to understand this. Suppose, we have a class called Expense:
Suppose, we have a View called Edit.cshtml which exposes all the properties to be edited. Suppose there is a logic on when to allow the IsApproved flag to be edited. We show the IsApproved checkbox to only HR users and not to other employees.
Similar to standard controller, we have Edit action method in ExpenseController like this:
For regular employee, the IsApproved checkbox doesn't appear on the Edit View. So ideally he should not be able to Approve or Disapprove the expense request.
However, a malicious user can easily update the value of the flag as per his convenience. In order to demo this attack, I installed a plugin on my Chrome called Request Maker. It allows me to edit/ send any HTTP request.
So what I did was just added the flag IsApproved and set the value to true. And voila, the Expense is approved.
The reason why I was able to accomplish this was because model binding in ASP.NET MVC tries to bind the data submitted to model properties based on their names. If it matches, it is accepted. And once it reaches the model, we simply save everything to the database.
In this example, only one property is added. So now, no matter how many values are posted from the client, we will get only one property out of those i.e. AmountMoney. All other properties will be ignored by the binding.
Similarly, we can also Exclude certain properties, if needed.
For future updates to my weekly blog, please subscribe to my blog via the "Subscribe By Email" feature at the right.
Over Posting
Model-binding is a useful and powerful feature of MVC. It automatically handles the mapping of form input to model properties. This prevents me from writing all that mapper code again and again. However, it opens up the vulnerability which allows the attacker to submit extra data with the form to populate model properties which were not intended to be changed.Let's take a look at an example to understand this. Suppose, we have a class called Expense:
public class Expense { public int ExpenseId { get; set; } public int EmployeeId { get; set; } public string EmployeeName { get; set; } public int AmountMoney { get; set; } public bool IsApproved { get; set; } }
Suppose, we have a View called Edit.cshtml which exposes all the properties to be edited. Suppose there is a logic on when to allow the IsApproved flag to be edited. We show the IsApproved checkbox to only HR users and not to other employees.
Similar to standard controller, we have Edit action method in ExpenseController like this:
[HttpPost] [ValidateAntiForgeryToken] public ActionResult Edit(Expense expense) { //save expense to database }
For regular employee, the IsApproved checkbox doesn't appear on the Edit View. So ideally he should not be able to Approve or Disapprove the expense request.
However, a malicious user can easily update the value of the flag as per his convenience. In order to demo this attack, I installed a plugin on my Chrome called Request Maker. It allows me to edit/ send any HTTP request.
So what I did was just added the flag IsApproved and set the value to true. And voila, the Expense is approved.
The reason why I was able to accomplish this was because model binding in ASP.NET MVC tries to bind the data submitted to model properties based on their names. If it matches, it is accepted. And once it reaches the model, we simply save everything to the database.
How to Prevent?
Bind
Using Bind attribute is a good way to prevent over posting attack. Using Bind attribute, we can include or exclude specific properties which are supposed to bind.public ActionResult Edit
([Bind(Include = "AmountMoney")]Expense expense) { ....... }
In this example, only one property is added. So now, no matter how many values are posted from the client, we will get only one property out of those i.e. AmountMoney. All other properties will be ignored by the binding.
Similarly, we can also Exclude certain properties, if needed.
ViewModel
Using ViewModel for each view also helps us in preventing this attack. The ViewModel should have only the properties which are supposed to edited by a particular view and no other properties. So these can be mapped to specific properties of the Model before its saved to the database. It is a good practice to have view models for views and to not use model entities for the view.Server-Side Checking
On the HttpPost action method, we can explicitly check the value of the properties. We can write custom code to check if the current user is of employee role then use the database value of IsApproved flag else if the user is HR user role then use the value posted. This is feasible if the check needs to be done once in a while. This might get difficult to maintain pretty soon.Conclusion
In this blog post, we talked about what over posting attack is and how it can be harmful. We also discussed some of the ways to prevent it.For future updates to my weekly blog, please subscribe to my blog via the "Subscribe By Email" feature at the right.
No comments:
Post a Comment