I recently went through a live training session, and some videos involving Grails. I was surprised to see that bulk assignment to domain objects appeared to be common practice in the training materials. In other words,
account.properties = params appeared to be the idiomatic way to update a domain object with new values from a web request. The problem with doing that, of course, is that an end-user can submit whatever form fields they choose, and easily change database fields you hadn’t intended for them to change. Fundamentally, this is the same problem PHP was accused of being very insecure for: In the earliest versions of PHP, form values were automatically bound to global variable, so <input name=”email”> on your webform could easily be referred to as $email in your php code. The register_globals parameter was introduced, set to off by default, and eventually removed entirely in order to deal with the security implications. With the PHP globals, you had to be using a poor programming practice(specifically, not initializing a variable before using it) in order to be affected. With an MVC framework, initializing the fields from the persistent record in the database and then changing any which are submitted is considered a feature.
The obvious solution to this issue is to not use bulk assignment, of course and assign values you wish to update individually, and I mistakenly assumed that would be the case in most instances in real life. Then the other week, GitHub was hacked, and a known mass-assignment vulnerability in Ruby on Rails was the cause. So much for that theory. Assigning values manually can get fairly tedious though, so it’s understandable developers would want some sort of shortcut.
A lazier solution than single assignment would seemingly be to implement some sort of filter, explicitly disallowing certain controllers from updating certain database fields. That’s an okay solution until your data model changes, and you forget to blacklist the new fields your old controller doesn’t need to interact with. So filtering isn’t a stellar idea. Whitelisting fields through individual assignment or some other means would appear to be the best solution.
This is where a little Microsoft style thinking actually comes in handy. In fact, bulk assignment to a view-model in ASP.NET MVC is recommended. In it’s simplest form, a view-model would be an object used by one or more controller actions which encapsulates a domain object and allows writing only to the properties actually available to those actions. Essentially, a whitelist. So adding a bit of MVVM to an MVC framework is a pretty clever way of avoiding a potentially serious security pitfall, but there are other benefits to including a view-model layer:
At first glance, adding a view-model layer to an MVC framework seems superfluous, but the advantages in terms of security and separation of concerns make the endeavor worthwhile.