Security
Headlines
HeadlinesLatestCVEs

Headline

CVE-2021-27582: Autobinding vulns and Spring MVC

org/mitre/oauth2/web/OAuthConfirmationController.java in the OpenID Connect server implementation for MITREid Connect through 1.3.3 contains a Mass Assignment (aka Autobinding) vulnerability. This arises due to unsafe usage of the @ModelAttribute annotation during the OAuth authorization flow, in which HTTP request parameters affect an authorizationRequest.

CVE
#vulnerability#web#js#git#java#php#rce#oauth#auth

Intro

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.

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.

  1. @ModelAttribute on a method argument

“An @ModelAttribute on a method argument indicates the argument should be retrieved from the model…”

  1. @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”

  1. @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”

  1. 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".

  1. 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 :)

  1. 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

  1. 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

CVE: Latest News

CVE-2023-50976: Transactions API Authorization by oleiman · Pull Request #14969 · redpanda-data/redpanda
CVE-2023-6905
CVE-2023-6903
CVE-2023-6904
CVE-2023-3907