Mass Assignment Insecure Binder Configuration Java

One of the scenarios that I always demonstrate during an ASP.NET MVC class is how to create a mass assignment vulnerability and then execute an over-posting attack. It is a mass assignment vulnerability that led to a severe problem on github last week.

Let's say you have the following model.

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

When you want to let a regular user change their first name, you give them the following form.

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

There is no input in the form to let a user set the IsAdmin flag, but this won't stop someone from crafting an HTTP request with IsAdmin in the query string or request body. Maybe they saw the "IsAdmin" name somewhere in a request displaying account details, or maybe they just got lucky and guessed the name.

If you use the MVC model binder with the above request and the previous model, then the model binder will happily move the IsAdmin value into the IsAdmin property of the model. Assuming you save the model values into a database, then any user can become an administrator by sending the right request. It's not enough to leave an IsAdmin input out of the edit form.

Fortunately, there are at least 6 different approaches you can use to remove the vulnerability. Some approaches are architectural, others just involve adding some metadata or using the right API.

Weakly Typed Approaches

The [Bind] attribute will let you specify the exact properties a model binder should include in binding (a whitelist).

[HttpPost] public ViewResult Edit([Bind(Include = "FirstName")]User user) { // ... }

Alternatively, you could use a blacklist approach by setting the Exclude parameter on the attribute.

[HttpPost] public ViewResult Edit([Bind(Exclude = "IsAdmin")] User user) { // ... }

If you prefer explicit binding with the UpdateModel and TryUpdateModel API, then these methods also support whitelist and blacklist parameters.

[HttpPost] public ViewResult Edit() { var user = new User(); TryUpdateModel(user, includeProperties: new[] { "FirstName" }); // ... }

Strongly Typed Approaches

TryUpdateModel will take a generic type parameter.  You can use the generic type parameter and an interface definition to restrict the model binder to a subset of properties.

[HttpPost] public ViewResult Edit() { var user = new User(); TryUpdateModel<IUserInputModel>(user); return View("detail", user); }

This assumes your interface definition looks like the following.

public interface IUserInputModel { string FirstName { get; set; } }

Of course, the model will also have to implement the interface.

public class User : IUserInputModel { public string FirstName { get; set; } public bool IsAdmin { get; set; } }

There is also a [ReadOnly] attribute the model binder will respect. ReadOnly metadata might be want you want to use if you never want to bind the IsAdmin property. (Note: I remember ReadOnly not working in MVC 2 or MVC 1, but it is working in 3 & 4 (beta)).

public class User { public string FirstName { get; set; } [ReadOnly(true)] public bool IsAdmin { get; set; } }

An Architectural Approach

One of many architectural approaches to solve the problem is to always put user input into a model designed for user input only.

public class UserInputViewModel { public string FirstName { get; set; } }

In this approach you'll never bind against business objects or entities, and you'll only have properties available for the input you expect. Once the model is validated you can move values from the input model to the object you use in the next layer of software.

Whatever approach you use, remember to treat any data in an HTTP request as malicious until proven otherwise.




Intro

If you don’t want to read all this text, you can watch video from the 29thmeeting of Defcon Russia Group (in Russian)

There is a not so well-known vulnerability type - "autobinding", or "mass assignment". The idea this type is based on a feature that is implemented in many frameworks. It allows a framework to automatically bind HTTP request parameters to objects and make them accessible to a developer. However, an attacker can add additional HTTP request params and they will possibly be bounded to an object. Depending on a victim software and its logic, the attacker can achieve some interesting results.

The autobinding feature is pretty widespread for frameworks, which makes attack surface rather wide. However, usually it's hard to find them without knowing source code and impact of a vuln strongly depends on an application.

You can read about this type of vulns on OWASP

There are also some simple examples, so if you are not familiar with it, I recommend that you look at it.

https://www.owasp.org/index.php/Mass_Assignment_Cheat_Sheet

A "real" example of such vulnerability and some additional information for Spring MVC framework was published by Ryan Berg and Dinis Cruz in 2011 -  https://o2platform.files.wordpress.com/2011/07/ounce_springframework_vulnerabilities.pdf

  


Something new

It's passed much time since that publication and Spring MVC now is not like it was before. It's much much cooler :)

When I was preparing tasks for the last ZeroNigths HackQuest, I wanted to provide one with an autobinding vuln to make people more familiar with this type of vulns. During the creation of the task, I've spotted an unknown/hidden variation of the autobinding vuln and I'd like to tell you about it.

As I wrote before, Spring MVC has changed. It's much smarter and has more features now. One of the new things is using annotations for doing "magic" things.

Because of them and some misunderstanding in minds, we can find an autobinding vuln in unexpected places.

Let's look at some of them and their official description (taken from here http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/mvc.html)


1) @ModelAttribute on a method argument

"An @ModelAttribute on a method argument indicates the argument should be retrieved from the model..."

2) @ModelAttribute on a method

"An @ModelAttribute on a method indicates the purpose of that method is to add one or more model attributes. @ModelAttribute methods in a controller are invoked before @RequestMapping methods"

3) @SessionAttribute for controller

"The type-level @SessionAttributes annotation declares session attributes used by a specific handler. This will typically list the names of model attributes or types of model attributes which should be transparently stored in the session"

4) FlashAttribute

"Flash attributes provide a way for one request to store attributes intended for use in another."

If you are not familiar with them or don't know spring at all, don't panic, because it will be clearer with further examples :)

What do the examples 2-4 have in common? They are all somehow related to  "passing" data between methods.

One of the ways to get data that was passed to the method is to use @ModelAttribute on a method argument (look at 1). However, it could lead to autobinding vuln. Why? Because @ModelAttribute is pretty “smart”. Let's look at a full description of it.

"An @ModelAttribute on a method argument indicates the argument should be retrieved from the model. If not present in the model, the argument should be instantiated first and then added to the model. Once present in the model, the argument's fields should be populated from all request parameters that have matching names."

So, first, @ModelAttribute retrieves an object from the model (or somewhere else) and then it populates the object with a user request. Therefore, a coder expects trusted data (the object) from the model, but an attacker can change it by just sending a specially crafted request.

I've made 2 tasks for ZN HQ, and both of them contain variations of autobinding vulns. Let's have a look  at what's going on there.


Sources of the tasks - https://github.com/GrrrDog/ZeroNights-HackQuest-2016

The First School of Bulimia “Edik”

The application consists of 3 "pages": registration, authentication, home page. The goal is to perform an expression language injection in the home page. The obstacle is that a user can set values only during registration process...

There is a class of User and it has 3 fields (name, password, weight) in the application.

The registration controller looks like that:




As we can see, the controller gets User object from a user request, validates it, and if the object is validated, the controller puts it in "DB".

The validating process is very strict. Because of whitelisting, we can use only figures or symbols, but we need to put special symbols in the user object! How? There is no way for the registration controller.


So, what can we do as attackers? Let's take a look at the authentication and home controller.

Authentication and home controller:

Authentication method does pretty simple things:

1) gets a username and password from a request;

2) gets a user object from the db using the username and password;

3) puts the user object in FlashAttribute and redirects to home method (sends redirect response to "/home");

So, there is no way to change the user object too.



 What about the home method?

It just gets the user object from the flash attribute and shows it to us.

@modelAttribute is used in this case to get the user object, but it also can populate the user object with incoming request params! So, we can change values in the user object!

All we need to do is to authenticate (send a request to the authenticate method) and add an additional HTTP param during redirection.

So, our request will look like:


/home?name=${We_Can_Write_Here_wharever_we_want} 

The goal is achieved.


Populating

There is an interesting and maybe not so obvious fact about autobinding. During populating data, Spring MVC makes changes on a field basis; it doesn't create a new object if something comes from an HTTP request. It means if there is an object from the model and only one param is received from an HTTP request, the value of only one field (with the same name as the HTTP param) will be changed and other fields will stay the same.



Justice League

Another task. Actually, solution for this task doesn't involve using an autobinding vuln, but there is one.

The application consists of registration, authentication, home, and password recovering "pages". The latter is only one that is important for us.

Actually, recovering page is just one controller with several methods and it represents a way of creating "wizards" (multi-step forms).

Our goal for this task is to bypass authentication.

Overall logic is the following.

1) A user comes to a recovery page, inputs its username and send a request to submit the form

2) the resetHandler method receives the HTTP request. It gets a user object from the db using the username from the request. Then it puts the user object in the Model, and it automatically puts the object into a session (@SessionAttribute("user") for the controller). Then it redirects to next part of "wizard".

 

3) The user is redirected to the resetViewQuestionHandler method. Actually, the method takes the user object from the session (yeah-yeah, using @ModelAttribute). It requires that object because the method has to get a custom user security question and show it in a view (however, that hasn't been implemented :)





4) When the user sends an answer for the question, the resetQuestionHandler method handles it. The method gets the answer from "answerReset" param and compares with the value in answer field from the user object. If answers match, the method generates a new secure password and shows it to the user.

As you can see, there is no @ModelAttribute near User user (in the method argument). However, Spring MVC is smart and automatically gets value from the session. Actually, it uses the same logic: gets value from somewhere, populates it with a user request.

So, what we can do as attackers?

a) We can add "answer=any_value", when we send a request to resetViewQuestionHandler. Then our answer is populated with an object from a session. So, we can change a correct answer to any value and after that set the same value for the resetQuestionHandler method.

Therefore, we can start the recovery process for admin user, bypass answer checking, and get a new password for admin.

b) We can add "answer=any_value" on the last step too (resetQuestionHandler) and get the same results. Actually, we can change a whole object if we would like.


Session Puzzling

There is another interesting thing. When a method gets an object from a session and populates it with a user request, @SessionAttribute "forces" Spring to store this newly populated object in the session. Therefore, we are able to control values of the object that are stored in the session. How can we use it?

If there is another controller that uses the same name of session attribute and trusts it, then we can perform a Session Puzzling attack (Session Variable Overloading). https://www.owasp.org/index.php/Testing_for_Session_puzzling_(OTG-SESS-008) . As far as I remember, the documentation says that a session attribute (created using @SessionAttribute) is limited to a controller, but in practice, we can use it in other controllers too.


Real Examples

I was looking for real examples of such issues on GitHub and in articles about Spring MVC and even found some. But:

1) examples identified on GitHub look like someone’s experiments with Spring MVC (not like real stuff)

2) there are some articles that recommend "dangerous" using of @ModelAttribute, but their examples are too simple and there is no potential impact.

Detection

At first glance, finding autobinding vulns using the "blackbox" approach looks impossible. Nevertheless, both of tasks were solved, both autobinding vulns were found. Respect to these people :)

There are some things that can help us to find such type of vulns:

1) often, a param name is equal to the name of a field of an object (but not necessary, because it's configurable). As the fields are often named in specific way, we can distinguish them. Of note, autobinding can be used with hashmaps and arrays.

2) When autobinding in a controller's method is used and when we send two parameters with the same name, the value in the object will be a concatenation of parameters.

Example:

Request with params:

?name=text1&name=text2

Result:

ObjectWithNameField.name = text1,text2

3) As soon as we've collected all param names, we can send them to all entry points (URLs), even to those that, at first glance, don't accept params (like resetViewQuestionHandler), and check if replies are different or the same as without params.


Conclusion

I've not shown an example related to incorrect using of "@ModelAttribute on a method", but something similar could happen in this case too.

As you can see, the main idea,  is based on the fact that a programmer thinks that he or she gets an object from a trusted place, but in practice, the object can be modified by an attacker.

I'm not sure, that I’ve correctly described causes of such a vuln, why and how Spring MVC behaves in this way.

It's hard to say exactly how common this variation of autobinding vuln is (but it definitely can be somewhere ;) . In general, autobinding vulns are pretty widespread, because of the feature they are based on. Moreover, the autobinding is not just about HTTP params, theoretically, any incoming data (e.g. JSON or XML) can be converted and then populated. However, a possibility of exploitation and impact strongly depend on many things ranging from using annotations and names of attributes to business logic of an application. 


Sources of the tasks - https://github.com/GrrrDog/ZeroNights-HackQuest-2016


0 Replies to “Mass Assignment Insecure Binder Configuration Java”

Lascia un Commento

L'indirizzo email non verrà pubblicato. I campi obbligatori sono contrassegnati *