領先一步
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 存在混淆。兩者也無關。