CVE-2022-22965分析复现

admin 2025年2月16日00:37:48评论30 views字数 4694阅读15分38秒阅读模式

声明

以下内容,均为文章作者原创,由于传播,利用此文所提供的信息而造成的任何直接或间接的后果和损失,均由使用者本人负责,长白山攻防实验室以及文章作者不承担任何责任。

长白山攻防实验室拥有该文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的副本,包括版权声明等全部内容。声明长白山攻防实验室允许,不得任意修改或增减此文章内容,不得以任何方式将其用于商业目的。

0x01 前置知识

Introspector类

javabean通常是用来做数据封装的java类,为了方便数据的读取与写入,会有getter/setter方法来对数据进行操作,在jdk中有一个Introspector类,通过该类的方法可以获取javabean的相关信息,包括javabean中的属性值,以及属性值对应的getter/setter方法。

对于属性的获取,其实是通过对应的getter/setter方法来确定的,如果存在对应的getter/setter方法或其中的一个,都会认为存在对应的属性,下面通过例子来了解下其他的特性。

新建两个javabean

//OrgBean.javapackage com.example.demo.model;public class OrgBean {private String orgname;public String getOrgname() {return orgname;}public void setOrgname(String orgname) {this.orgname = orgname;}}//TestBean.javapackage com.example.demo.model;public class TestBean extends OrgBean{public String getTestbeanName() {return testbeanName;}public void setTestbeanName(String testbeanName) {this.testbeanName = testbeanName;}public String testbeanName;}//Test.javapackage com.example.demo.model;import java.beans.BeanInfo;import java.beans.Introspector;public class Test {public static void main(String[] args) throws Exception {BeanInfo beanInfo = Introspector.getBeanInfo(TestBean.class);System.out.println(beanInfo);}}

运行Test.java,会发现beanInfo中的properties中存在着三个属性。

CVE-2022-22965分析复现

testbeanName是TestBean中的属性,orgname是TestBean继承的OrgBean类中的属性,那class属性是从何而来?

通过前两个属性可以看出getBeanInfo会同时获取到目标类所继承类的属性,而所有java类是继承与Object类的,Object存在着一个名为getClass的方法,所以会识别到class属性,这个class属性也是后面的关键。

点号赋值的过程

使用项目

https://github.com/DDuarte/springshell-rce-poc 来进行测试,稍微改动下代码,新增一个CommBean。

package com.example.demo.model;public class CommBean {public String age ;public CommBean() {System.out.println("CommBean init");}public void setAge(String age) {System.out.println("commbean setage");this.age = age;}public String getAge() {System.out.println("commbean GETage");return age;}}

改动下EvalBean

package com.example.demo.model;public class EvalBean {public EvalBean() throws ClassNotFoundException {System.out.println("[+] EvalBean.EvalBean");}public CommBean name = new CommBean();public CommBean getName() {System.out.println("[+] EvalBean.getName");return name;}public void setName(CommBean name) {System.out.println("[+] EvalBean.setName");this.name = name;}}

在controller中绑定了EvalBean之后,可以通过如下方式来对CommBean中的age赋值

http://127.0.0.1:8080/index?name.age=xxx 下图是控制台打印结果

CVE-2022-22965分析复现

下面来分析下是如何设置值的,根据控制台打印的调用顺序,在getName方法处断点,向上寻找会发现在

org.springframework.beans.AbstractNestablePropertyAccessor#getPropertyAccessorForPropertyPath方法中会以点为分割,来解析属性

CVE-2022-22965分析复现

在解析到最后一个属性前都会进入if分支内,一路会跟到

org.springframework.beans.AbstractNestablePropertyAccessor#getPropertyValue(org.springframework.beans.AbstractNestablePropertyAccessor.PropertyTokenHolder)方法。

该方法会去获取name属性对应的值,其中调用了getLocalPropertyHandler方法,跟进去到

org.springframework.beans.CachedIntrospectionResults#CachedIntrospectionResults方法中。

CVE-2022-22965分析复现

这个方法是用来创建javabean信息缓存的,其中调用的getBeanInfo方法就利用了Introspector类来获取javabean的信息。

CVE-2022-22965分析复现

当类的缓存创建后,再次用到该类时就会直接利用缓存的信息,不会再经过该方法,具体的逻辑在

org.springframework.beans.CachedIntrospectionResults#forClass方法中;回到CachedIntrospectionResults方法中,可以看到beaninfo中的properties存储了class,name两个属性。

CVE-2022-22965分析复现

回到getPropertyValue方法,在获取了类的相关信息后,会调用getvalue方法去掉用对应的getter方法。

CVE-2022-22965分析复现

本例中会调用getName,然后接着会进行递归的取值,在解析到最后一个属性后,会进入getPropertyAccessor-ForPropertyPath的else分支,return到向上的调用代码。

回退到

org.springframework.beans.AbstractNestablePropertyAccessor#setPropertyValue(org.springframework.beans.PropertyValue)方法中。

CVE-2022-22965分析复现

nestedPa即为刚刚递归调用的返回值,是一个接着会获取age属性的tokens,

接着调用nestedPa.setPropertyValue来对属性进行赋值,赋值会调用setter方法,对应着本例中的setAge。

总结一下,对于aaa.bbb.ccc的传入,会依次调用getaaa->getbbb->setccc方法,同时aaa属性需要是对应绑定的javabean中的属性。

再思考一下,在上面的分析中,我们看到在生成javabean缓存时,会多出一个class属性,是由于javabean默认继承Object进而识别getClass方法所获得。

那么其实当我们传入class.xxx.yyy时,就会调用getClass->getxxx->setyyy 这也是本次漏洞的起因。

0x02 漏洞分析

本次漏洞其中一部分是对 CVE-2010-1622 的绕过,详细信息参考:

http://rui0.cn/archives/1158 

该漏洞主要是利用上文中的class属性来获取到classloader,进而来修改运行时态的某些属性的值。

为了修复该漏洞,spring在前面分析的CachedIntrospectionResults方法

中添加了一些限制。

CVE-2022-22965分析复现

这导致我们无法通过下面两种方式来获取到classloader

class.protectionDomain.classLoaderclass.classLoader

然而在jdk9以上,jdk中的Class类多了一个module属性。

CVE-2022-22965分析复现

Module类中存在着getClassLoader方法。

CVE-2022-22965分析复现

那么我们就可以绕过前面

CachedIntrospectionResults中的限制用class.module.classLoader来调用到

getClassLoader方法拿到classloader对象,接着就是寻找利用方法,可以参考S2-020在Tomcat 8下的利用方法。

参考https://nmap.cc/jsjl/41.html 

在Spring MVC+Tomcat的环境下可以通过控制access log文件的文件名和内容,来写入shell。

完整的exp可参考:

https://github.com/Mr-xn/spring-core-rce

0x03 漏洞修复

参考:

https://github.com/spring-projects/spring-framework/commit/afbff391d8299034cd98af968981504b6ca7b38c

CVE-2022-22965分析复现

修补方式依然是对

CachedIntrospectionResults方法进行限制,当beanClass是Class类时,只能缓存Name为结尾的属性同时不会缓存ClassLoader与ProtectionDomain属性。

0x04 参考文章

  1. https://my.oschina.net/u/4547531/blog/4346472

  2. https://blog.csdn.net/qq_44973159/article/details/106090450

  3. https://nmap.cc/jsjl/41.html

  4. http://rui0.cn/archives/1158

  5. https://github.com/spring-projects/spring-framework/commit/afbff391d8299034cd98af968981504b6ca7b38c

CVE-2022-22965分析复现
CVE-2022-22965分析复现
CVE-2022-22965分析复现

▇ 扫码关注我们 ▇

长白山攻防实验室

学习最新技术知识

原文始发于微信公众号(长白山攻防实验室):CVE-2022-22965分析复现

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年2月16日00:37:48
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   CVE-2022-22965分析复现https://cn-sec.com/archives/1076278.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息