Update Log:


This security alert is in response to CVE-2022-22965 - "Spring4Shell" in Spring Core that has been confirmed by several sources that leverage class injection (very severe),


Based on the information available from the Spring team, the following notes represent the known scenarios where this vulnerability can be exploited as well as ways to remediate it:


  • JDK 9 or higher
  • Apache Tomcat as the Servlet container
  • Packaged as WAR
  • spring-webmvc or spring-webflux dependency

Spring does caution that there may be other ways to exploit it that have not been reported yet.


Spring Framework versions 5.3.18 and 5.2.20 have been released which address this vulnerability.


Based on the information available, the following are actions that should be taken to secure Broadleaf Commerce Framework implementations:


Broadleaf Monolith Deployments

Broadleaf Monolith version 6.0 and older only support JDK 1.8 or less. Those versions of the framework should not be impacted so long as you are running JDK 1.8 or less.


Broadleaf Monolith version 6.1 is on Spring Framework version 5.1.x. If you are running the application as a Spring Boot executable jar, no mitigation is required. Clients that are running 6.1.x with Apache Tomcat, packaging using a WAR, and running JDK 9+ will require mitigation


Broadleaf Monolith version 6.2+ is on Spring Framework version 5.3.x. Broadleaf has released patches for all 6.2.x versions containing the upgrade to Spring Framework 5.3.18 and to Spring Boot 2.5.12 which contains the fix for the exploit. The recommendation for all 6.2.x clients is to apply the appropriate patch. Patch release versions are :

  • 6.2.0.1-GA
  • 6.2.1.5-GA
  • 6.2.2.1-GA

Suggested Manual Mitigation Steps If Upgrading Spring Is Not Feasible

For 6.1.x implementations of Broadleaf Monolith that are impacted by this exploit a mitigation approach is required. Below are the steps suggested:


WebDataBinder Patch

One recommended patch is to `disallowedFields` on `WebDataBinder` through a @ControllerAdvice. This would be added to your site, admin, and API applications.

//Code
@ControllerAdvice
@Order(Ordered.LOWEST_PRECEDENCE)
public class BinderControllerAdvice {
    @InitBinder
    public void setAllowedFields(WebDataBinder dataBinder) {
         String[] denylist = new String[]{"class.*", "Class.*", "*.class.*", "*.Class.*"};
         dataBinder.setDisallowedFields(denylist);
    }
}
//

This is the easiest approach but may leave holes in your application if your application has a controller that sets `disallowedFields` locally through its own `@InitBinder` method overriding the global ControllerAdvice. It is recommended to review your codebase for `disallowedFields` and verify that the global @ControllerAdvice would not be overridden.


Extending RequestMappingHandlerAdapter

A second recommendation is to extend the RequestMappingHandlerAdapter to update the WebDataBinder at the end after all other initialization. This approach is good if the global @ControllerAdvice will not work. In order to use this approach, a Spring Boot application can declare a WebMvcRegistrations bean (Spring MVC). Here is an example:


//code
@SpringBootApplication
@EnableAutoConfiguration
public class SiteApplication extends SpringBootServletInitializer {
    @Configuration
    @EnableBroadleafSiteAutoConfiguration
    public static class BroadleafFrameworkConfiguration {}
    public static void main(String[] args) {
        SpringApplication.run(SiteApplication.class, args);
    }
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(SiteApplication.class);
    }
    @Bean
    public WebMvcRegistrations mvcRegistrations() {
        return new WebMvcRegistrations() {
            @Override
            public RequestMappingHandlerAdapter getRequestMappingHandlerAdapter() {
                return new ExtendedRequestMappingHandlerAdapter();
            }
        };
    }
    private static class ExtendedRequestMappingHandlerAdapter extends RequestMappingHandlerAdapter {
        @Override
        protected InitBinderDataBinderFactory createDataBinderFactory(List<InvocableHandlerMethod> methods) {
            return new ServletRequestDataBinderFactory(methods, getWebBindingInitializer()) {
                @Override
                protected ServletRequestDataBinder createBinderInstance(
                        Object target, String name, NativeWebRequest request) throws Exception {
                    ServletRequestDataBinder binder = super.createBinderInstance(target, name, request);
                    String[] fields = binder.getDisallowedFields();
                    List<String> fieldList = new ArrayList<>(fields != null ? Arrays.asList(fields) : Collections.emptyList());
                    fieldList.addAll(Arrays.asList("class.*", "Class.*", "*.class.*", "*.Class.*"));
                    binder.setDisallowedFields(fieldList.toArray(new String[] {}));
                    return binder;
                }
            };
        }
    }
}
//

Broadleaf Microservices Deployments

All of the Broadleaf Microservices are deployed using Spring Boot executable jars. This exploit does not impact this deployment approach. Nonetheless, our next patch release train (1.7.2-GA) will contain a Spring Framework upgrade to version 5.2.20 (from 5.2.19). Also, if desired, you can manually update the spring dependency version in your own pom. If your project pom inherits from spring boot parent pom, then you can declare a property in your pom to override the spring version:


<properties>

<spring-framework.version>5.2.20.RELEASE</spring-framework.version>

</properties>


Or, if you are consuming the microservices framework at versions 1.7+ and using the newer pom model, you may declare a dependency on the updated spring framework bom at an early point in the pom. The key point here is to declare prior to the broadleaf release train:

<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-framework-bom</artifactId>
                <version>5.2.20.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.broadleafcommerce.microservices</groupId>
                <artifactId>broadleaf-microservices-release-train</artifactId>
                <version>${blc.release.train}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
In either case, examine the build output of your project and confirm spring framework 5.2.20 versions are being resolved.