Inside the Grails dependency injection binding vulnerability

Posted by: on Mar 29, 2012 | 3 Comments

You may have seen the recently announced vulnerability in Grails binding relating to dependency injection.

I wanted to explain this in a little more depth so that everybody knows how to tell whether or not their current systems are vulnerable to it and what this might mean. It is worth noting that new releases of Grails 1.3.x and 2.0.x have already been made by the team – upgrading to those now and redeploying your app will close this particular hole for you.

To know if you must take some rapid action to address this issue, some detail is required on the nuance of the problem.

In summary: if you have a command or domain object that receives property values from param binding that is not protected adequately by include/exclude lists, and that command or domain receives dependency injected beans from the application context, you may be at risk.

There is an extra dimension here that further narrows down the risk, more of that in a moment, but suffice to say there are apps out there right now that can effectively be taken out of service by a single malicious request – sometimes only from a registered user of the site, but not exclusively. So yes, this is serious and yes you do need to understand it and audit your code if you are not in a position to immediately upgrade Grails and redeploy your app.

On to the details. Say you have a command or domain object that needs to store the current user id as a property of the object before saving. To do this you may inject a service and call a method on the service during a persistence event. The injection is the part that matters:

class UserProfile {
def securityService
...
}

Now it should be pretty obvious by now that there is the opportunity here to trash the value of the securityService field if the request includes a parameter with the same value.

As the property is untyped, binding can stick anything it likes in there, so you can replace the injected service with a String from the request params.

That’s actually not so terrible. Usually if you use the service it will crash with a missing method error.

If the injected property is explicitly typed nothing will happen at all as binding won’t know how to convert a String to that type. However that won’t save you from the real threat.

The threat comes from the fact that Spring beans injected like this are often singletons – there is just one shared instance in the whole app – and that beans often inject into themselves other beans.

So now imagine that our securityService also injects into itself a cacheService:


class SecurityService {
def cacheService
...
}

Because this is injected untyped, binding can reach this cacheService singleton bean and trash its value. All you have to do is pass in a query parameter like securityService.cacheService=boom and your security service bean is now trashed as any access to the cache service will likely result in missing method or missing property errors – for all future requests until your app is restarted.

This should show that actually the problem is not that common in code, and requires knowledge of your application to some extent, which mitigates risk. However if you use plugins that are open source and people can reasonably guess you used certain plugins / probe for them, then your risks are higher.

There is a final nuance to this. If the security service has public typed properties that can be bound from String i.e. booleans, numbers, dates and perhaps more, those values can be trashed on the singleton security service also – or worse changed without your knowledge.

Again, in terms of open source plugins this opens up risk – if you inject beans from plugins that have such fields, attackers can find out about this and use it.

Luckily the scope of this is realistically likely to be small, but it is sufficiently nuanced that the only recommendations at this time can be:

  1. read Jeff’s blog on binding safely
  2. upgrade to one of the new grails releases and redeploy now
  3. or remove all injected properties in commands and domains
  4. or use includes/excludes in every single binding call you make

Remember that you may use plugin controllers or domains that are also susceptible. For example Weceem is currently vulnerable but only where users have content edit rights, and apps using Spring Security Core may be vulnerable as it is not uncommon to inject springSecurityService into domains and that service has a number of corruptible dependencies injected.

The quick fix is to use option 2. Do it.

Thanks to the SpringSource guys for working so hard to get fixes in place. It is heartening that such efforts are taken to respect such problems and deal with them correctly when, truth be told, they are just really annoying and time consuming.

3 Comments

  1. Marc Palmer's Blog » Grails Platform Core 1.0.M1 Plugin – highlights
    March 30, 2012

    [...] few days ago we released Platform Core Plugin 1.0.M1 for Grails. The platform will provide APIs and utilities to help us take the Grails ecosystem to [...]

  2. TheCarlos
    April 9, 2012

    Whoa, while I was familiar with the vulnerability, somehow the implications for dependency injection had not occurred to me. Thanks so much for explaining it so clearly.

  3. Pascal DeMilly
    November 7, 2012

    I have been struggling getting a service auto injected into an object command instantiated in a controller. According to the doc it should work, but it is not for me and I am using grails 2.1.1. Is that why? Is it something that was removed from grails. If so how can I use a service from inside a custom validator.