【最新漏洞预警】CVE-2022-22965 Spring核心框架Spring4Shell远程命令执行漏洞原理与修复方式分析

渗透技巧 2年前 (2022) admin
698 0 0
漏洞信息
Spring是目前全球最受欢迎的Java轻量级开源框架。近日网上爆出Spring核心框架存在RCE漏洞(编号CVE-2022-22965)。在野曝光一段时间后,与近几年流行的高危漏洞命名方式类似(比如ProxyShell、log4jShell等),这个漏洞被称为Spring4Shell。3月31日官方终于发布了漏洞信息,并在新版本v5.3.18和v5.2.20中修复了漏洞。(官方不发补丁我也不敢公开发布文章呀!【最新漏洞预警】CVE-2022-22965 Spring核心框架Spring4Shell远程命令执行漏洞原理与修复方式分析
分析后发现漏洞结合了JDK9及以上版本一个新的属性,成功绕过历史漏洞CVE-2010-1622修复补丁,同时结合Tomcat容器的一些操作属性,可以实现GetShell。当然Weblogic、Jetty等其他Java中间件或应用程序也可能构建出完整利用链,但从目前研究进度来看,漏洞触发需要至少满足以下条件:
  • JDK9或以上版本系列
  • Spring框架或衍生的SpringBoot等框架,版本小于v5.3.18或v5.2.20
  • Spring JavaBean表单参数绑定需要满足一定条件
  • 部署在Tomcat容器中,且日志记录功能开启(默认状态)
环境搭建

 

新建SpringBoot工程:

 

【最新漏洞预警】CVE-2022-22965 Spring核心框架Spring4Shell远程命令执行漏洞原理与修复方式分析

 

添加实体类`User`:

 

【最新漏洞预警】CVE-2022-22965 Spring核心框架Spring4Shell远程命令执行漏洞原理与修复方式分析

 

添加`LoginController`:

 

【最新漏洞预警】CVE-2022-22965 Spring核心框架Spring4Shell远程命令执行漏洞原理与修复方式分析

 

生成war包并部署到Tomcat容器中启动。

 

JavaBean参数绑定分析

 

JavaBean是一种特殊的类,主要用于传递数据信息,这种类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。如果在两个模块之间传递信息,可以将信息封装进JavaBean中。比如在`User`类中再添加一个新类`Test`:

 

【最新漏洞预警】CVE-2022-22965 Spring核心框架Spring4Shell远程命令执行漏洞原理与修复方式分析

 

构建如上所示的研究环境,当我们发送如下请求时:

 

【最新漏洞预警】CVE-2022-22965 Spring核心框架Spring4Shell远程命令执行漏洞原理与修复方式分析

 

Spring会将参数用`.`进行分割,前面的参数会自动调用`get***`,最后一个参数会自动调用`set***`,依次执行为:

 

...User->getTest    Test->setT...

 

通过上面这种链式的参数解析规则,我们可以`set***`实现修改Spring框架中某些类的属性。通过深入分析,发现当在`Controller`的参数前加上注解之类,比如`@RequestBody`,将不会进行链式解析,这也是限制适用范围的其中一个关键因素。

 

【最新漏洞预警】CVE-2022-22965 Spring核心框架Spring4Shell远程命令执行漏洞原理与修复方式分析

CVE-2010-1622漏洞补丁分析

 

Spring历史上曾经爆出一个漏洞CVE-2010-1622,原理就是基于上面的JavaBean赋值规则。可以通过提交`class.classLoader`参数,最终执行`getClassLoader`函数获取`ClassLoader`对象,从而可以导致RCE。CVE-2010-1622漏洞补丁位于`CachedIntrospectionResults`:

 

【最新漏洞预警】CVE-2022-22965 Spring核心框架Spring4Shell远程命令执行漏洞原理与修复方式分析

 

CVE-2010-1622补丁通过将`classLoader`加入黑名单,导致无法加入解析属性列表。

JDK 9 Module分析

 

在JDK9及以上版本的JDK中,`java.lang.Class`类中新增了一个私有变量`module`以及函数`getModule`:

 

【最新漏洞预警】CVE-2022-22965 Spring核心框架Spring4Shell远程命令执行漏洞原理与修复方式分析

 

进入`Module`类,发现存在`loader`变量和函数`getClassLoader`:

 

【最新漏洞预警】CVE-2022-22965 Spring核心框架Spring4Shell远程命令执行漏洞原理与修复方式分析

 

也就是说,通过`Module`可以获取Web Context上下文环境的`ClassLoader`对象。

漏洞分析

 

通过前面的分析,我们在Tomcat+Spring+JDK11环境中构建研究环境,提交`class.module.classLoader`参数同样可以获取`ClassLoader`对象,调试发现在对BeanInfo赋值过程中,`CachedIntrospectionResults`中会加载`class org.apache.catalina.loader.ParallelWebappClassLoader`对象,可以绕过黑名单检查:

 

【最新漏洞预警】CVE-2022-22965 Spring核心框架Spring4Shell远程命令执行漏洞原理与修复方式分析

 

`ParallelWebappClassLoader`位于Tomcat环境中,获取`ParallelWebappClassLoader`对象后,就可以在此基础上继续寻找可利用链。

 

可以尝试采用递归方式搜索所有满足`class.module.classLoader`条件的链式调用的属性,加入一个`help.jsp`文件(脚本参考只考虑int、string与boolean这些基本属性)。访问后,可以获取所有潜在可操控的属性,结果如下:

 

【最新漏洞预警】CVE-2022-22965 Spring核心框架Spring4Shell远程命令执行漏洞原理与修复方式分析

 

一共找到300个符合条件的属性可以操控(实际应该更多)。其中的`class.module.classLoader.resources.context.parent.pipeline.first.*`对应于`AccessLogValve`类,主要存放Tomcat日志操作的相关属性:

 

...class.module.classLoader.resources.context.parent.pipeline.first.directory         //日志保存目录默认为logsclass.module.classLoader.resources.context.parent.pipeline.first.prefix            //日志文件名前缀默认为localhost_access_logclass.module.classLoader.resources.context.parent.pipeline.first.suffix            //日志文件名后缀默认为.txtclass.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat    //日志文件名日期格式默认为.yyyy-mm-dd...

 

链式调用过程如下:

 

getClass()->LoginControllergetModule()->ModulegetClassLoader()->ParallelWebappClassLoadergetResources()->StandardRootgetContext()->StandardContextgetParent()->StandardEnginegetPipeline()->PipelinegetFirst()->AccessLogValve...

 

【最新漏洞预警】CVE-2022-22965 Spring核心框架Spring4Shell远程命令执行漏洞原理与修复方式分析

 

默认情况下日志目录为`logs`,文件名称为`localhost_access_log.yyy-mm-dd.txt`,可以通过构造请求修改日志存储路径、日志文件名称、后缀名属性值。

 

【最新漏洞预警】CVE-2022-22965 Spring核心框架Spring4Shell远程命令执行漏洞原理与修复方式分析

 

【最新漏洞预警】CVE-2022-22965 Spring核心框架Spring4Shell远程命令执行漏洞原理与修复方式分析

 

通过修改日志后缀名、文件名称、存放位置等属性,可以写入jsp的webshell。需要注意的是,由于Tomcat稍微新一点的版本出于安全性考虑,无法直接在URL中携带`<`、`{`等特殊字符(否则返回400),我们可以通过`class.module.classLoader.resources.context.parent.pipeline.first.pattern`属性来修改日志记录的格式,从而变向写入webshell。

 

参考`AbstractAccessLogValve`类使用说明:

 

【最新漏洞预警】CVE-2022-22965 Spring核心框架Spring4Shell远程命令执行漏洞原理与修复方式分析

比如,可以将敏感字符放到HTTP请求头中(格式:`%{xxx}i`)。最终实现在`webapps`目录下写入webshell,名称为`localhost_access_log123.jsp`:

 

【最新漏洞预警】CVE-2022-22965 Spring核心框架Spring4Shell远程命令执行漏洞原理与修复方式分析

修复方式

 

在官方没有发布新版本前,可以通过在WAF中加入对`Class.*`等恶意字符串的过滤,或者在Spring应用程序中新建一个全局类实现对恶意字符串的过滤,同时保证这个类被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 a{    @InitBinder    public void setAllowedFields(WebDataBinder dataBinder) {        String[] abd = new String[]{"class.*", "Class.*", "*.class.*", "*.Class.*"};        dataBinder.setDisallowedFields(abd);        }}

 

3月31日,官方在`v5.3.18`和`v5.2.20`版本中修复了漏洞,我们看下关键补丁:

 

【最新漏洞预警】CVE-2022-22965 Spring核心框架Spring4Shell远程命令执行漏洞原理与修复方式分析

 

相比CVE-2010-1622漏洞补丁,新补丁对类型限制更为严格,只允许所有类中的`name`属性合法通过。

小结

 

漏洞通过`class.module.classLoader`在Web Context上下文环境中找到合适的类属性进行控制从而实现Getshell,理论上漏洞利用链不局限于Tomcat,类似Weblogic、Jetty等其他的Java中间件是否可以利用不好下结论,可以尝试利用`help.jsp`来寻找潜在的利用点,这方面感兴趣的小伙伴可以关注公众号后与本人深入交流【最新漏洞预警】CVE-2022-22965 Spring核心框架Spring4Shell远程命令执行漏洞原理与修复方式分析

 

 

由于传播、利用此文档提供的信息而造成任何直接或间接的后果及损害,均由使用本人负责,且听安全团队及文章作者不为此承担任何责任。

 

 

点关注,不迷路!

【最新漏洞预警】CVE-2022-22965 Spring核心框架Spring4Shell远程命令执行漏洞原理与修复方式分析

原文始发于微信公众号(且听安全):【最新漏洞预警】CVE-2022-22965 Spring核心框架Spring4Shell远程命令执行漏洞原理与修复方式分析

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...