Spring Framework RCE,提前公告

工程 | Rossen Stoyanchev | 2022年3月31日 | ...

更新

目錄

概述

我想宣佈 Spring Framework 中存在一個 RCE 漏洞,該漏洞在 CVE 釋出之前洩露。該問題最初是由 AntGroup FG 的 codeplutos, meizjm3i 在格林威治標準時間週二晚上接近午夜時向 VMware 報告的。週三,我們進行了調查、分析、確定修復方案、測試,並計劃在週四緊急釋出。與此同時,週三,詳細資訊已線上完全洩露,這就是我們提前釋出此更新和 CVE 報告的原因。

漏洞

該漏洞影響執行在 JDK 9+ 上的 Spring MVC 和 Spring WebFlux 應用程式。特定的漏洞利用需要應用程式作為傳統 WAR 包部署在 Servlet 容器上。如果應用程式作為 Spring Boot 可執行 jar 部署(即預設情況),則不受此漏洞利用的影響。但是,該漏洞的性質更普遍,可能存在其他利用方式。

我是否受到影響?

報告中特定場景的要求如下:

附加說明

  • 該漏洞涉及 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 已釋出。
  • 依賴於 Spring Framework 5.3.18 的 Spring Boot 2.6.6 和 2.5.12 已釋出。
  • CVE-2022-22965 已釋出。
  • Apache Tomcat 已釋出 10.0.20、9.0.62 和 8.5.78 版本,這些版本在 Tomcat 端關閉了攻擊向量,請參閱Spring Framework RCE,緩解措施替代方案

建議的變通方法

首選的響應是更新到 Spring Framework 5.3.185.2.20 或更高版本。如果已完成此操作,則無需任何變通方法。但是,有些人可能無法快速進行升級。因此,我們提供了以下一些變通方法。

請注意,變通方法不一定是互斥的,因為安全最好“深入”完成。

升級 Tomcat

對於在 Tomcat 上執行且使用不受支援的 Spring Framework 版本的舊應用程式,升級到 Apache Tomcat 10.0.209.0.628.5.78 可提供足夠的保護。然而,這應被視為一種戰術解決方案,主要目標應是儘快升級到當前受支援的 Spring Framework 版本。如果採用此方法,還應考慮設定禁止欄位以進行深度防禦。

降級到 Java 8

如果既無法升級 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 存在混淆。兩者也無關。

獲取 Spring 新聞通訊

透過 Spring 新聞通訊保持聯絡

訂閱

領先一步

VMware 提供培訓和認證,助您加速進步。

瞭解更多

獲得支援

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位制檔案,只需一份簡單的訂閱。

瞭解更多

即將舉行的活動

檢視 Spring 社群所有即將舉行的活動。

檢視所有