ASP MVC: Mass Assignment

 
 
  • Gérald Barré

This post is part of the series 'Vulnerabilities'. Be sure to check out the rest of the blog posts of the series!

#What's Mass Assignment?

Rather than a lengthy explanation, let me illustrate with an example.

Here is the model used:

C#
public class User
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public bool IsAdmin { get; set; }
}

The view that allows editing only the first and last name of the user:

Razor
@using(Html.BeginForm())
{
    @Html.EditorFor(model => model.FirstName)
    @Html.EditorFor(model => model.LastName)
    <input type="submit" value="Submit" />
}

And the controller:

C#
[HttpPost]
public ActionResult Index(User user)
{
    return View();
}

What happens when the user clicks the submit button?

The framework creates a User instance and populates its properties from the request data (query string and body). In this case, the form only exposes the first and last name fields. However, if an attacker guesses the name of the IsAdmin property and sets it to true in the URL (e.g., https://example.com/mapage?IsAdmin=True), the model binder will use that value when creating the User instance, resulting in the user being granted administrator privileges.

#How to guard against it?

There are two main approaches.

The first is to use the Bind attribute, which lets you specify which properties should be included or excluded during model binding.

C#
public ActionResult Index([Bind(Include = "FirstName, LastName")]User user)

Or

C#
public ActionResult Index([Bind(Exclude = "IsAdmin")]User user)

The second approach is to define a dedicated view model class containing only the properties needed for this view, then use a mapping tool to convert it to the domain model. AutoMapper can handle this automatically.

C#
public class UserModel
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

[HttpPost]
public ActionResult Index(UserModel user)
{
    User u = Mapper.Map<UserModel, User>(user);
    return View();
}

And voilà.

Do you have a question or a suggestion about this post? Contact me!

Follow me:
Enjoy this blog?