The framework binder used for binding the HTTP request parameters to the model class has not been explicitly configured to allow, or disallow, certain attributes.
Explanation:
To ease development and increase productivity, most modern frameworks allow an object to be automatically instantiated and populated with the HTTP request parameters whose names match an attribute of the class to be bound. Automatic instantiation and population of objects speeds up development, but can lead to serious problems if implemented without caution. Any attribute in the bound classes, or nested classes, will be automatically bound to the HTTP request parameters. Therefore, malicious users will be able to assign a value to any attribute in bound or nested classes, even if they are not exposed to the client through web forms or API contracts.
Example 1: With no additional configuration, the following ASP.NET MVC controller method will bind the HTTP request parameters to any attribute in the RegisterModel or Details classes:
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
try
{
return RedirectToAction("Index", "Home");
}
catch (MembershipCreateUserException e)
{
ModelState.AddModelError("", "");
}
}
return View(model);
}
Where RegisterModel class is defined as:
public class RegisterModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
public string ConfirmPassword { get; set; }
public Details Details { get; set; }
public RegisterModel()
{
Details = new Details();
}
}
and Details class is defined as:
public class Details
{
public Details()
{
IsAdmin = false;
}
public bool IsAdmin { get; set; }
...
}
Example 2: When using TryUpdateModel() or UpdateModel() in ASP.NET MVC or Web API applications, the model binder will automatically try to bind all HTTP request parameters by default:
public ViewResult Register()
{
var model = new RegisterModel();
TryUpdateModel<RegisterModel>(model);
return View("detail", model);
}
Example 3: In ASP.NET Web API applications, the model binder will automatically try to bind all HTTP request parameters by default using the configured JSON or XML serializer/deserializer. By default, the binder will try to bind all possible attributes from the HTTP request parameters or body:
public class ProductsController : ApiController
{
public string SaveProduct([FromBody] Product p)
{
return p.Name;
}
...
}
Example 4: In ASP.NET Web Form applications, the model binder will automatically try to bind all HTTP request parameters when using TryUpdateModel() or UpdateModel() with IValueProvider interface.
Employee emp = new Employee();
TryUpdateModel(emp, new System.Web.ModelBinding.FormValueProvider(ModelBindingExecutionContext));
if (ModelState.IsValid)
{
db.SaveChanges();
}
and Employee class is defined as:
public class Employee
{
public Employee()
{
IsAdmin = false;
IsManager = false;
}
public string Name { get; set; }
public string Email { get; set; }
public bool IsManager { get; set; }
public bool IsAdmin { get; set; }
}
Recommendations:
When using frameworks that provide automatic model binding capabilities, it is a best practice to control which attributes will be bound to the model object so that even if attackers are able to identify other non-exposed attributes of the model or nested classes, they will not be able to bind arbitrary values from HTTP request parameters.
Depending on the framework used there will be different ways to control the model binding process:
Example 5: It is possible to control the ASP.NET MVC model binding process using opt-in approach, decorate the class with the [DataContract] attribute. If this attribute is present, members are ignored unless they have the [DataMember] attribute:
[DataContract]
public class Details
{
public Details()
{
IsAdmin = false;
}
[DataMember]
public int Id { get; set; }
public bool IsAdmin { get; set; }
...
}
Example 6: It is also possible to control the ASP.NET MVC model binding process using opt-out approach, decorate the members with the [IgnoreDataMember] attribute. If this attribute is present then, those members are ignored during the model binding process:
public class Details
{
public Details()
{
IsAdmin = false;
}
[IgnoreDataMember]
public bool IsAdmin { get; set; }
...
}
Example 7: In ASP.NET Web API applications, the model classes bound to the HTTP request parameters can be annotated to control the binding process. For example, if the application is using JSON.NET for JSON serialization, the [JsonIgnore] attribute can be used to ignore certain attributes that should not be included in the serialization/deserialization process:
public class Details
{
public Details()
{
IsAdmin = false;
}
[JsonIgnore]
public bool IsAdmin { get; set; }
...
}
Example 8: In ASP.NET Web Form applications, this issue can be prevented using appropriate use of [BindNever] attribute, available under System.Web.ModelBinding namespace.
public class Employee
{
public Employee()
{
IsAdmin = false;
IsManager = false;
}
public string Name { get; set; }
public string Email { get; set; }
[BindNever]
public bool IsManager { get; set; }
[BindNever]
public bool IsAdmin { get; set; }
}
A different approach to protecting against mass assignment vulnerabilities is using a layered architecture where the HTTP request parameters are bound to DTO objects. The DTO objects are only used for that purpose, exposing only those attributes defined in the web forms or API contracts, and then mapping these DTO objects to Domain objects where the rest of the private attributes can be defined.
Tips:
1. This vulnerability category can be classified as a design flaw since accurately finding these issues requires understanding of the application architecture which is beyond the capabilities of static analysis. Therefore, it is possible that if the application is designed to use specific DTO objects for HTTP request binding, there will not be any need to configure the binder to exclude any attributes.
0 comments:
Post a Comment