领先一步
VMware 提供培训和认证,助您加速进步。
了解更多更新
disallowedFields 变通方法中的小问题我想宣布 Spring Framework 中存在一个 RCE 漏洞,该漏洞在 CVE 发布之前泄露。该问题最初是由 AntGroup FG 的 codeplutos, meizjm3i 在格林威治标准时间周二晚上接近午夜时向 VMware 报告的。周三,我们进行了调查、分析、确定修复方案、测试,并计划在周四紧急发布。与此同时,周三,详细信息已在线完全泄露,这就是我们提前发布此更新和 CVE 报告的原因。
该漏洞影响运行在 JDK 9+ 上的 Spring MVC 和 Spring WebFlux 应用程序。特定的漏洞利用需要应用程序作为传统 WAR 包部署在 Servlet 容器上。如果应用程序作为 Spring Boot 可执行 jar 部署(即默认情况),则不受此漏洞利用的影响。但是,该漏洞的性质更普遍,可能存在其他利用方式。
报告中特定场景的要求如下:
spring-webmvc 或 spring-webflux 依赖项。附加说明
ClassLoader 访问,并取决于所使用的实际 Servlet 容器。Tomcat 10.0.19、9.0.61、8.5.77 及更早版本已知存在漏洞。Payara 和 Glassfish 也已知存在漏洞。其他 Servlet 容器也可能存在漏洞。@ModelAttribute 注解或可选地不带注解且不带任何其他 Spring Web 注解的控制器方法参数。@RequestBody 控制器方法参数(例如 JSON 反序列化)无关。但是,如果此类方法具有通过数据绑定从查询参数填充的另一个方法参数,它们仍然可能存在漏洞。首选的响应是更新到 Spring Framework 5.3.18 和 5.2.20 或更高版本。如果已完成此操作,则无需任何变通方法。但是,有些人可能无法快速进行升级。因此,我们提供了以下一些变通方法。
请注意,变通方法不一定是互斥的,因为安全最好“深入”完成。
对于在 Tomcat 上运行且使用不受支持的 Spring Framework 版本的旧应用程序,升级到 Apache Tomcat 10.0.20、9.0.62 或 8.5.78 可提供足够的保护。然而,这应被视为一种战术解决方案,主要目标应是尽快升级到当前受支持的 Spring Framework 版本。如果采用此方法,还应考虑设置禁止字段以进行深度防御。
如果既无法升级 Spring Framework 也无法升级 Apache Tomcat,则降级到 Java 8 是一个可行的变通方法。
另一个可行的变通方法是通过全局设置 WebDataBinder 上的 disallowedFields 来禁用特定字段的绑定。
@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);
}
}
这通常有效,但作为集中应用的变通修复,可能会留下一些漏洞,特别是如果控制器通过其自己的 @InitBinder 方法在本地设置 disallowedFields,这将覆盖全局设置。
为了以更安全的方式应用变通方法,应用程序可以扩展 RequestMappingHandlerAdapter,以便在所有其他初始化之后更新 WebDataBinder。为此,Spring Boot 应用程序可以声明一个 WebMvcRegistrations bean (Spring MVC) 或一个 WebFluxRegistrations 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<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;
}
};
}
}
}
对于没有 Spring Boot 的 Spring MVC,应用程序可以从 @EnableWebMvc 切换到直接扩展 DelegatingWebMvcConfiguration,如文档的高级配置部分所述,然后覆盖 createRequestMappingHandlerAdapter 方法。
有人猜测关于弃用 SerializationUtils 的提交。该类在框架中只有一个用法,并且不暴露给外部输入。弃用与此漏洞无关。
这与在此漏洞报告发布前发布的Spring Cloud Function 的 CVE 存在混淆。两者也无关。