Spring框架远程代码执行漏洞(CVE-2022-22965)处置手册
2022-3-31 22:31:59 Author: blog.nsfocus.net(查看原文) 阅读量:23 收藏

阅读: 154

一、漏洞概述

近日,绿盟科技CERT监测到Spring相关框架存在远程代码执行漏洞,未经授权的远程攻击者可构造HTTP请求在目标系统上写入恶意程序从而执行任意代码,此漏洞为Spring framework远程代码执行漏洞(CVE-2010-1622)的绕过利用,但影响范围更为广泛,官方已于3.31号下午发布了5.2.20.RELEASE与5.3.18版本修复此漏洞,目前PoC已公开,请相关用户尽快采取措施进行排查与防护。

绿盟科技已成功复现该漏洞:

参考链接:https://spring.io/blog/2022/03/31/spring-framework-rce-early-announcement

二、影响范围

受影响范围

  • Spring Framework < 5.3.18
  • Spring Framework < 5.2.20

及其衍生产品

  • JDK ≥ 9
  • JRE ≥ 9

不受影响版本

  • Spring Framework = 5.3.18
  • Spring Framework = 5.2.20

  • JDK < 9
  • JRE < 9

三、漏洞检测

3.1 漏洞排查

根据漏洞利用条件,可通过以下顺序进行逐项排查:

1. 检测是否使用Spring框架,若未使用,则不存在该漏洞。

由于Java项目存在打包方式各异、Spring Bean常作为基础组件Lib进行打包、非范性命名等情况,推荐使用自动化迭代解压jar的方式同时对spring-beans-*.jar与CachedIntrospectionResults.class进行匹配式搜索。如果存在匹配,则说明使用了Spring框架。

推荐使用绿盟科技CERT提供的D-Eyes工具进行自动化扫描。

目前已根据漏洞信息紧急开发了本地检查工具《D-Eyes应急响应工具spring漏洞排查专版》,适配于Windows与Linux系统使用,相关客户请联系当地服务同事获取。

2. 检查项目是否使⽤Spring参数绑定,若未使用,则不存在该漏洞。

由于该漏洞需要利用SpringMVC的参数绑定,因此项目相关开发人员若未使用参数绑定,则不受该漏洞影响。

3. 检查中间件使用的JDK版本,若版本号小于9,则不存在该漏洞。

首先通过系统进程,确认中间件使用的JDK路径,并在命令行执行“java -version”获取当前使用的JDK版本。

4. 检查当前使用的中间件是否为Tomcat,若未使用Tomcat,则暂不受该漏洞影响。

目前公开的漏洞利用代码只针对Tomcat中间件,但不排除后续有新的利用代码出现,因此非Tomcat中间件,仍存在风险可能性。

5. 检查Tomcat是否启用了AccessLog,若未启用,则暂不受该漏洞影响。

目前公开的漏洞利用代码是通过覆盖Tomcat的日志相关配置实现后门文件写入,因此若未启用AccessLog,则暂不受该漏洞影响,但不排除后续有新的利用方式出现。

在server.xml配置文件中,通过org.apache.catalina.valves.AccessLogValve关键字可定位到AccessLog相关配置。

3.2 产品检测

绿盟科技远程安全评估系统(RSAS)、WEB应用漏洞扫描系统(WVSS)、综合威胁探针(UTS)与智能安全运营平台(ISOP)已具备对此次漏洞的扫描与监测能力,请有部署以上设备的用户升级至最新版本。

四、攻击排查

若通过上述检测,若确认存在该漏洞,可通过以下方法排查是否遭受攻击。

1. 异常字段检测

由于目前公开的漏洞利用代码会影响AccessLogValve、 StandardHost的部分字段,可通过在Tomcat下执行绿盟科技CERT提供的脚本扫描相关字段,从而对攻击痕迹进行检测。

该检测方式仅限在JVM未重启或攻击者未对相关字段内容进行恢复的前提下有效。

正常业务扫描结果示例如下:

被攻击后扫描结果示例如下:

2. 日志与后门文件

目前公开的漏洞利用代码执行后,会导致Tomcat不再产生新的AccessLog,可通过排查最近的AccessLog是否存在缺失,来判断是否遭受攻击。

排查Tomcat相关web应用目录下是否存在可疑后门文件,由于攻击者修改了部分AccessLog配置字段,文件中可能存在大量-。

detect.jsp代码块:

<%@ page import="org.apache.catalina.connectorRequest" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.core.StandardHost" %>
<%@ page import="org.apache.catalina.AccessLog" %>
<%@ page import="java.util.*" %>

<head><title>Spring RCE Attack Trail Detection</title></head>
<%
        // AccessLog
        Field requestF = request.getClass().getDeclaredField("request");
        requestF.setAccessible(true);
        Request req = (Request)requestF.get(request);
        StandardHost standardHost = (StandardHost)req.getMappingData().host;
        AccessLog[] logs = (AccessLog[])getFieldValue(standardHost.getAccessLog(), "logs");
        Field[] fs =logs[0].getClass().getDeclaredFields();
        Field sf =logs[0].getClass().getSuperclass().getDeclaredField("pattern");
        sf.setAccessible(true);
        out.println("<font color=\"red\">"+sf.getName()+" : "+sf.get(logs[0]).toString()+"</font>"+"</br>");
        List<String> myList = Arrays.asList("directory","prefix","suffix","currentLogFile");
        for (Field f:fs) {
                f.setAccessible(true);
                if (f.get(logs[0])!=null){
                        if(myList.contains(f.getName())){
                                out.println("<font color=\"red\">"+f.getName()+" : "+f.get(logs[0]).toString()+"</font>"+"</br>");
                        }else {
                                out.println(f.getName()+" : "+f.get(logs[0]).toString()+"</br>");
                        }
                }
        }
        // AppBase
        Field appBaseF = standardHost.getClass().getDeclaredField("appBase");
        appBaseF.setAccessible(true);
        out.println("<font color=\"red\">"+appBaseF.getName()+" : "+appBaseF.get(standardHost).toString()+"</font>"+"</br>");
        out.println("</br>Scanning completed. @NSFOCUS CERT</br>");
%>
<%!
        public static Object getFieldValue(Object obj, String fieldName) throws Exception {
                Field f = obj.getClass().getDeclaredField(fieldName);
                f.setAccessible(true);
                return f.get(obj);
        }
%>

五、漏洞防护

5.1 官方升级

目前官方已发布新版本5.2.20.RELEASE与5.3.18修复此漏洞,请受影响的用户尽快更新进行防护,下载链接:https://github.com/spring-projects/spring-framework/releases

5.2 产品防护

针对上述漏洞,绿盟科技Web应用防护系统(WAF)与网络入侵防护系统(IPS)已发布规则升级包,请相关用户升级规则包至最新版,以形成安全产品防护能力。安全防护产品规则编号如下:

注意:如果要应用规则,请为防护站点勾选上述对应的规则编号。

使用web服务器/插件防护规则,WAF默认即可对此漏洞进行防护:

产品规则升级的操作步骤详见如下链接:

WAF:https://mp.weixin.qq.com/s/7F8WCzWsuJ5T2E9e01wNog

IPS:https://mp.weixin.qq.com/s/DxQ3aaap8aujqZf-3VbNJg

其他相关用户可在WAF等网络防护设备上,根据实际部署业务的流量情况,实现对“class. * ” ,“Class.*”,“*.class.*”,“*.Class.*”等字符串的规则过滤,并在部署过滤规则后,对业务运行情况进行测试,避免产生额外影响。

5.3 其他防护措施

受影响用户可使用下列措施对漏洞进行修复:

1、在项目中全局搜索setDisallowedFields方法

2、若找到setDisallowedFields,则在Controller中加入如下代码:

3、若未找到setDisallowedFields,则引入全局的Controller,并使用ControllerAdvice注解实现全局异常拦截,代码如下:

注意:项目源码中,尽量不要重复使用setDisallowedFields方法,否则会导致全局Controller失败。

参考代码块:

import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.InitBinder;

@ControllerAdvice
public class GlobalController {

    @InitBinder
    public void setAllowedFields(WebDataBinder dataBinder) {
        dataBinder.setDisallowedFields("class.*", "*.class.*", "Class.*", "*.Class.*");
    }
}

声明

本安全公告仅用来描述可能存在的安全问题,绿盟科技不为此安全公告提供任何保证或承诺。由于传播、利用此安全公告所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,绿盟科技以及安全公告作者不为此承担任何责任。

绿盟科技拥有对此安全公告的修改和解释权。如欲转载或传播此安全公告,必须保证此安全公告的完整性,包括版权声明等全部内容。未经绿盟科技允许,不得任意修改或者增减此安全公告内容,不得以任何方式将其用于商业目的。


文章来源: http://blog.nsfocus.net/cve-2022-22965/
如有侵权请联系:admin#unsafe.sh