How to prevent Model Binding of UI properties to the MVC Model in your .NET Core application

We are dealing here with a security risk for your .NET Core application. Suppose you are having the following MVC model in your .NET application and the user can edit in a UI-form her Firstname and Lastname. The property Age cannot be edited on the form. The business logic tells us that it will be filled later. However, the user, with the help of simple tools such as Postman or Google console debugger can edit the Age property. Let us see how we can block such actions.

We first define our simple Model:

1
2
3
4
5
6
7
8
  public class Person
  {
      public string Firstname { get; set; }

      public string Lastname { get; set; }

      public int Age { get; set; }   
  }

We then write a MVC action in our Controller:

1
2
3
4
5
6
7
  [HttpPost]
  public Guid AddUser(Person person)
  {
      // Save the person into the DB and return the new ID of the user.

      return Guid.NewGuid();
  }

Now we have four ways in total to accomplish our goal of restricting model bindings from the UI.

Create a whitelist of allowed properties

For that we are going to add the Bind attribute on the parameter of the action we defined:

1
2
3
4
5
6
7
  [HttpPost]
  public Guid AddUser([Bind(nameof(Person.Firstname), nameof(Person.Lastname))] Person person)
  {
      // Save the person into the DB and return the new ID of the user.

      return Guid.NewGuid();
  }

As you can see we are using the nameof to provide some type safety, thus avoiding using strings directly. We are testing the action with Postman:

A POST request with Postman

And we are getting the value of only the two allowed properties:

The MVC Bind parameter-attribute in action

The BindNever Attribute

Another way to “hide” the Age property from the UI, if we do not want to use the Bind attribute, is to add the BindNever attribute on top of the property in our MVC model:

1
2
  [BindNever]
  public int Age { get; set; }

Restrict the setter of the property

We can also define the setter of the property to private, so that only our code is able to update its value:

1
  public int Age { get; private set; }

The view-model solution

My personal favorite solution is the definition of a new POCO class which contains only the two properties (Firstname, Lastname) we want to be editable in the UI. These model is then used instead of the larger model. Inside our controller we can then map from the one object to the other without. The user can access only two properties and the Age property is only visible inside our code.

comments powered by Disqus