Does Spring4Shell impact embedded Tomcat?
Update: Spring Boot updates have dropped with mitigations. Check them out here
What's been going on?
There's currently a great deal of concern about the Spring4Shell vulnerability that dropped last night (read more here). Unfortunately, this has corresponded with another Spring Cloud CVE that is - afaik - unrelated, causing some confusion.
The LunaSec article above is a good write-up of what's been going on, but we wanted to flesh out the exploit from the perspective of running Spring Boot with embedded tomcat.
tl;dr: you're probably fine if you're not deploying a WAR to Tomcat, but should mitigate anyway.
Am I in trouble?
If you're deploying a Spring application as a WAR to Tomcat then the answer right now is an emphatic yes. By taking advantage of Spring's BeanWrapperImpl's approach to handling nested properties, an attacker can convince the framework to traverse an object graph like so:
- request the class property on the object being bound - this will exist because all objects in Java have a class property (a request param of class=x)
- via the module property on the Class, gain access to the ClassLoader - in this case the Tomcat WebAppClassLoader - ( request param is now class.module.classLoader
- traverse the object graph to gain access to Tomcat's internal resources (at this point, we might have a request parameter like: class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp)
- make changes to the internal state of the server to gain access to the shell.
This needs urgent mitigation - as recommended in this excellent Praetorian post.
We've been attempting to reproduce this for the setup that we use on our projects (embedded Tomcat on Spring Boot) and so far we've not managed to find anything that is obviously exploitable. When running in embedded mode, the application will be using the secure classloaders from the JDK which don't have the same issues as the Tomcat WebappClassLoader.
Should I still consider the mitigations? permalink
We can still access the class property when using the nested property accessor, but the classloader on the class, and on any child properties, seems to be null.
The internal JDK ClassLoaders look to be locked down tight - there are no obvious public properties or getters that I can exploit to get further along this path.
But this is still a little alarming. An attacker can pass in a request parameter that causes the framework to traverse the object graph along the internals of the application server. We can think of no sensible reason to allow an external request to interact with the internals of the system like this.
As such, we recommend implementing the mitigations recommended by this post. We're confident that the Spring team will publish a patch for this very soon, but we'll sleep easier knowing that we've taken a belt-and-braces approach to application security.
It's going to be a rough week ahead for any teams that are deploying a Spring-based WAR file to a Tomcat server on Java 9+. For those using the embedded version, we suspect that the vulnerability isn't immediately exploitable, but recommend applying the mitigations anyway.