10

I'm working on page that allows users to edit profile info. I want them to be able to edit their public info, but not allow them to change system flags such as their user type.

This is implemented with Spring MVC (3.0). The User object has typical fields such as firstName, lastName, email (all should be editable) and a boolean administrator (which should not be editable.

My method looks something like this:

@RequestMapping(method = RequestMethod.POST)
public String doEdit(
        @ModelAttribute("user") User user,
        BindingResult result,
        ModelMap model)
throws IOException
{
      // validate, blah blah
      // save user object
      // return page

}

My form includes fields firstName, lastName etc and seemed to work fine.

The problem is that if a malicious user posts a query with the parameter administrator as "true" they can set this field when they shouldn't.

I know I can create a separate "form" object with just the fields I want to change and use that for the automatic binding. (the copy over the data). The problem is that I have a lot of places which use this technique. (for the user and other objects). It'd be a hassle to maintain when I want to add fields.

Is there a way to use annotations or other techniques in Spring MVC to whitelist parameters and prevent changes to arbitrary domain object properties?

Will Glass
  • 4,800
  • 6
  • 34
  • 44
  • 4
    just a historic anecdote, Spring was so loose in this area, that a malicious user could inject "class.classLoader.URLs[]" to any model object, completely taking control of the server. http://www.springsource.com/security/cve-2010-1622 – irreputable Feb 16 '11 at 22:38
  • 2
    I am flabbergasted. I just upgraded from Spring 3.0.2 to Spring 3.0.5 in production last week. – Will Glass Feb 17 '11 at 01:14

3 Answers3

12

The DataBinder has two properties named allowedFields and disallowedFields that define what to (dis)allow for binding. Just use that in your @InitBinder method:

@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.setDisallowedFields("administrator");
}
Costi Ciudatu
  • 37,042
  • 7
  • 56
  • 92
3

You could filter the request with the "!myParam" style expressions, to indicate that the specified parameter is not supposed to be present in the request.

@RequestMapping(params="!administrator")
Julian Bonilla
  • 243
  • 3
  • 8
-3

Don't send this administrator parameter to the client side, controll it in the server side.

Iogui
  • 1,526
  • 1
  • 17
  • 28
  • it's not a parameter in itself, it's a property of the User object. My question asks if there is a way to ignore this property. – Will Glass Feb 17 '11 at 01:11
  • Your user model object is tied on the view layer? Some people think it is good. I think not. However this is controversial question. See http://stackoverflow.com/questions/2680071/dto-or-domain-model-object-in-the-view-layer . My comment goes on when you use DTOs in oposite of domain objects. – Iogui Feb 17 '11 at 02:29
  • The problem with this solution is someone could still maliciously add the parameter to the form and control it's value. Sure, you could override whatever was sent over, but it's easy to forget to override a property so it's better to just whitelist allowed properties. – Addison Jul 01 '19 at 15:08