搶佔先機
VMware 提供培訓和認證,助力您快速提升。
瞭解更多更新
disallowedFields
臨時解決方案中的小問題。我在此宣佈 Spring Framework 中存在一個 RCE 漏洞,該漏洞在 CVE 釋出之前被提前洩露。該問題最早於格林威治時間週二深夜接近午夜時由螞蟻集團 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 產生了混淆。它也與此無關。