Spring Framework RCE 早期公告

JAVA架构日记

共 3429字,需浏览 7分钟

 ·

2022-04-20 21:20

一、概述

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.185.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.classargs);
 }


 @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

浏览 15
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报