Spring Framework RCE 早期公告
一、概述
Spring Framework 确认存在一个 RCE 漏洞,该漏洞尚未发布 CVE 报告。该问题于周二晚上首次报告给 VMware,周三,通过调查,分析,确定修复,测试,同时瞄准周四的紧急发布。与此同时,同样在周三,该漏洞已在线泄露,所以在提供更新之后 Spring 官方发布此 CVE 报告。
二、关于此 RCE
该漏洞会影响在 JDK 9+ 上运行的 Spring MVC 和 Spring WebFlux 应用程序。特定的漏洞需要将应用程序打包为WAR 并部署到 Apache Tomcat。这确实意味着该漏洞不会影响嵌入式 Tomcat 的 Spring Boot。但是,该漏洞的性质更为普遍,可能还有其他方法可以利用它。
三、我是否受到影响?
以下是报告中特定方案的要求:
- JDK 9 或更高版本
- Apache Tomcat as the Servlet container
- 打包为 WAR
但是,此漏洞的性质更为普遍,可能还有其他尚未报告的利用方法。
四、状态
Spring Framework 5.3.18 和 5.2.20 已经发布。相应的 Spring Boot 版本正在进行中。我们预计这些将在下一个小时内完成。
五、修复方案
注意:Spring Framework 版本 5.3.18 和 5.2.20 解决了这个漏洞,已经上传到 Maven Central。如果能够升级,则不需要以下解决方法。
泄露的报告建议通过以下方式进行设置:
@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);
}
}COPY
这通常有效,但作为集中应用的解决方法修复,可能会留下一些漏洞,特别是如果控制器通过其自己的方法在本地设置,这会覆盖全局设置。
为了以更安全的方式应用变通办法,应用程序可以扩展以在所有其他初始化后更新最后。为此,Spring Boot 应用程序可以声明一个 Bean (Spring MVC) 或一个 Bean (Spring WebFlux)。
例如,在 Spring MVC 中(在WebFlux中也是如此):
package car.app;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.annotation.InitBinderDataBinderFactory;
import org.springframework.web.method.support.InvocableHandlerMethod;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.ServletRequestDataBinderFactory;
@SpringBootApplication
public class MyApp {
public static void main(String[] args) {
SpringApplication.run(CarApp.class, args);
}
@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 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 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;
}
};
}
}
}
COPY
对于不带 Spring 启动的 Spring MVC,应用程序可以从直接切换到扩展,如中所述@EnableWebMvc``DelegatingWebMvcConfiguration
高级配置[1]部分,然后覆盖 createRequestMappingHandlerAdapter
方法 。
参考资料
[1]高级配置: https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-config-advanced-java