安全通告
Spring 框架 RCE 漏洞安全风险通告
发布日期:2022-3-31
漏洞描述
近日,监测到Spring框架曝出RCE漏洞。经研究,已经证实由于SerializationUtils#deserialize 基于 Java 的序列化机制,可导致远程代码执行 (RCE),使用 JDK9 及以上版本皆有可能受到影响。
Spring是一个开放源代码的设计层面框架,是为了解决企业应用开发的复杂性而创建的。它解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。当用到Spring的参数绑定功能,同时Spring core运行在jre/jdk/openjdk 9以上的版本时,class新增了getModlue()方法,可以通过其来获取classLoader,从而绕过现有的spring的java.lang.class.classLoader 黑名单防御机制,达到调用 classLoader 的目的,配合不同的 Loader 的 setter、getter 方法,达到命令执行或任意文件读写等一系列效果。
考虑到 Spring 框架的广泛应用,漏洞利用整个过程操作简单,该漏洞可能已被远程攻击者利用。建议相关用户及时开展安全自查,做好相关防护措施,避免被外部攻击者入侵。
漏洞危害
未经授权的远程攻击者可以利用该漏洞达到命令执行或任意文件读写等一系列效果。
漏洞等级
高危
漏洞利用条件
- JDK/JRE/OpenJDK 版本: 9 及以上;
- 使用了 Spring-beans 包;
- 使用了 Spring 参数绑定;
- Spring 参数绑定使用的是非基本参数类型,例如一般的 POJO 即可;
注:不是 java+Spring 就一定存在漏洞,还要根据具体业务代码来进一步判断。
自查措施
JDK版本号排查
在业务系统的运行服务器上,执行“java -version”命令查看运行的JDK版本,如果版本号小于等于8,则不受漏洞影响。
Spring框架使用情况排查
一、如果业务系统项目以war包形式部署,按照如下步骤进行判断:
- 解压war包:将war文件的后缀修改成.zip ,解压zip文件;
- 在解压缩目录下搜索是否存在 spring-beans-*.jar 格式的jar文件(例如spring-beans-5.3.16.jar),如存在则说明业务系统使用了spring框架进行开发;
- 如果spring-beans-*.jar 文件不存在,则在解压缩目录下搜索class 文件是否存在,如存在则说明业务系统使用了Spring框架开发。
二、如果业务系统项目以jar包形式直接独立运行,按照如下步骤进行判断:
- 解压jar包:将jar文件的后缀修改成.zip,解压zip文件;
- 在解压缩目录下搜索是否存在spring-beans-*.jar 格式的jar文件(例如spring-beans-5.3.16.jar),如存在则说明业务系统使用了spring框架进行开发;
- 如果spring-beans-*.jar 文件不存在,则在解压缩目录下搜索class 文件是否存在,如存在则说明业务系统使用了spring框架进行开发。
修复建议
官方暂时还未进行任何更新,临时建议:
- 在应用组全局搜索@InitBinder 注解,看看方法体内是否调用dataBinder.setDisallowedFields 方法,如果发现此代码片段的引入,则在原来的黑名单中添加{“class.*”,”Class.*”,”*.class.*”,”*.Class.*”}。(注:如果此代码片段使用较多,则需要每个地方都追加)
- 在应用系统的项目包下新建以下全局类,并保证这个类被 Spring 加载到(推荐在Controller 所在的包中添加)。完成类添加后,需对项目进行重新编译打包和功能验证测试,并重新发布项目。
import org.springframework.core.annotation.Order
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.InitBinder;
@ControllerAdvice
@Order(10000)
public class GlobalControllerAdvice {
@InitBinder
public void setAllowedFields(WebDataBinder dataBinder) {
String[] abd = new String[]{“class.*”, “Class.*”, “*.class.*”, “*.Class.*”}
dataBinder.setDisallowedFields(abd);
}
}