Spring Framework RCE 早期公告
一、概述
Spring Framework 確認(rèn)存在一個(gè) RCE 漏洞,該漏洞尚未發(fā)布 CVE 報(bào)告。該問題于周二晚上首次報(bào)告給 VMware,周三,通過調(diào)查,分析,確定修復(fù),測試,同時(shí)瞄準(zhǔn)周四的緊急發(fā)布。與此同時(shí),同樣在周三,該漏洞已在線泄露,所以在提供更新之后 Spring 官方發(fā)布此 CVE 報(bào)告。
二、關(guān)于此 RCE
該漏洞會(huì)影響在 JDK 9+ 上運(yùn)行的 Spring MVC 和 Spring WebFlux 應(yīng)用程序。特定的漏洞需要將應(yīng)用程序打包為WAR 并部署到 Apache Tomcat。這確實(shí)意味著該漏洞不會(huì)影響嵌入式 Tomcat 的 Spring Boot。但是,該漏洞的性質(zhì)更為普遍,可能還有其他方法可以利用它。
三、我是否受到影響?
以下是報(bào)告中特定方案的要求:
- JDK 9 或更高版本
- Apache Tomcat as the Servlet container
- 打包為 WAR
但是,此漏洞的性質(zhì)更為普遍,可能還有其他尚未報(bào)告的利用方法。
四、狀態(tài)
Spring Framework 5.3.18 和 5.2.20 已經(jīng)發(fā)布。相應(yīng)的 Spring Boot 版本正在進(jìn)行中。我們預(yù)計(jì)這些將在下一個(gè)小時(shí)內(nèi)完成。
五、修復(fù)方案
注意:Spring Framework 版本 5.3.18 和 5.2.20 解決了這個(gè)漏洞,已經(jīng)上傳到 Maven Central。如果能夠升級,則不需要以下解決方法。
泄露的報(bào)告建議通過以下方式進(jìn)行設(shè)置:
@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
這通常有效,但作為集中應(yīng)用的解決方法修復(fù),可能會(huì)留下一些漏洞,特別是如果控制器通過其自己的方法在本地設(shè)置,這會(huì)覆蓋全局設(shè)置。
為了以更安全的方式應(yīng)用變通辦法,應(yīng)用程序可以擴(kuò)展以在所有其他初始化后更新最后。為此,Spring Boot 應(yīng)用程序可以聲明一個(gè) Bean (Spring MVC) 或一個(gè) 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 啟動(dòng)的 Spring MVC,應(yīng)用程序可以從直接切換到擴(kuò)展,如中所述@EnableWebMvc``DelegatingWebMvcConfiguration高級配置[1]部分,然后覆蓋 createRequestMappingHandlerAdapter ?方法 。
參考資料
[1]高級配置: https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-config-advanced-java
