坐标:
Springframework : Spring Web5.2.23.RELEASE
CVE:
CVE-2016-1000027
漏洞描述
Vmware Spring Framework是美国威睿(Vmware)公司的一套开源的Java、JavaEE应用程序框架。该框架可帮助开发人员构建高质量的应用。
Pivotal Software Spring Framework 4.1.4版本中存在安全漏洞。攻击者可利用该漏洞执行代码。
解决方案
相关commit:
漏洞补丁:
参考方案:
- 目前厂商暂未发布修复措施解决此安全问题,建议使用此软件的用户随时关注厂商主页或参考网址以获取解决办法:
https://pivotal.io/
组件例外修复分析:
https://blog.csdn.net/GalaxySpaceX/article/details/130063787
基础知识:
Markdown要想分析首先要了解什么是Spring HTTP Invoker,HttpInvoker是基于HTTP之上提供RPC,同时又使用了Java的对象序列化机制,实现了穿透防火墙或多系统之间的通信。具体的实现过程很复杂,我们不用太深入的去了解,只需要知道HttpInvoker主要是使用http协议通过传输序列化数据来实现通信,一旦传输序列化数据,如果使用不当就会产生反序列化漏洞。 |
漏洞成因:
漏洞版本:spring-web<6.0版本中漏洞发生在,HttpInvokerServiceExporter和RemoteInvocationSerializingExporter中,序列化数据未进行检测,当传输恶意序列化数据的时候,反序列化中就会执行恶意代码。首先查看漏洞的存在位置,这里可以看到执行的栈关系:调用层级如下所示,首先通过handleRequest接收发送来的数据,然后调用readRemoteInvocation,createObjectInputStream最后通过doReadRemoteInvocation的readObject实现反序列化。httpinvoker.HttpInvokerServiceExporter.handleRequesthttpinvoker.HttpInvokerServiceExporter.readRemoteInvocationRemoteInvocationSerializingExporter.createObjectInputStreamRemoteInvocationSerializingExporter.doReadRemoteInvocationRemoteInvocationSerializingExporter.readObject首先看 handleRequest,可以看到此处调用将获取到的response数据传输给readRemoteInvocation方法。查看readRemoteInvocation方法,可以看到post数据被分别传输给了createObjectInputStream和doReadRemoteInvocation,字面意思可以看到分别为创建对象流和执行远程调用查看doReadRemoteInvocation方法可以看到其中执行了readObject,进行反序列化操作。至此我们通过对代码的分析可以发现调用关系很简单,直接将传入的数据进行反序列化执行,但是并未进行安全检测或安全限制,这样如果接口被暴露在外部,则可以通过构造恶意cc链来实现反序列化执行系统命令。 |
漏洞复现:
首先-项目构建:
Markdown首先构建项目,这里我使用的是GitHub,前辈已经实现的测试代码,代码地址如下:https://github.com/artem-smotrakov/cve-2016-1000027-poc |
Markdown这里需要注意项目首先要启动server,这里会下载需要的jar包,等下载完成后启动服务器,可以看到如下界面: |
Markdown根据ysoserial帮助看到我们可以使用如下调用链,例子中给的是CommonsCollections3,但是我这里存在问题,我使用的是CommonsCollections6可以成功执行 |
Markdown使用如下的命令,将生成的CommonsCollections6.bin放在项目的目录中java -jar ysoserial-all.jar CommonsCollections6 "calc" > CommonsCollections6.bin |
漏洞测试:
Delphi执行后看我们发送的数据包,使用post方式,Content-Type: application/x-java-serialized-object,数据为我们刚才生成的打开计算器命令 |
Delphi执行成功,可以看到成功弹出计算器 |
漏洞并不复杂,主要是在反序列的过程中并未对数据进行检测和限制,如果接口开放到互联网暴露面就会被恶意利用。
漏洞修复:
Markdown漏洞修复其实直接升级到6.0版本就可以了,但是麻烦的点在于spring-web 6.0版本变动比较大,项目中使用的jBPM 6.2.0和Hibernate 4.2不兼容Spring Framework 6 ,Spring Framework 6需要JPA 2.2或更高版本,Hibernate 4.2也是基于JPA 2.0的,与Spring Framework 6不兼容。这样的话要想修复漏洞就不能采用升级的方式,只能手工修复:第一种方案就是添加执行限制,对序列化数据进行限制,如果存在调用恶意cc链就禁止,但是这样存在被绕过风险,并不安全第二种方案就是直接把HttpInvokerServiceExporter功能关闭,如果业务上没有使用并不会产生什么影响。这里就采用第二种方案,将handleRequest方法置空,关闭其回调。 |
修改后代码如下:
修改前代码如下:
首先使用命令解压项目:
jar -xf spring-web-5.3.22.jar
使用命令生成class文件,其中jar文件中为HttpInvokerServiceExporter.java所需要依赖的jar包。
javac -cp jar/* HttpInvokerServiceExporter.java
执行成功后,生成如下两个class文件:
之后将两个class文件与解压后的文件进行替换,并执行下面命令打包为jar包
jar -cvfm0 spring-web-5.3.22_20230410.jar META-INF/MANIFEST.MF ./
这就成功的打包了jar包,下面进行修复测试。 |
修复测试:
首先加载我们修改后的jar包,查看HttpInvokerServiceExporter,可以看到已经被修改 |
在执行Exploit,可以看到无法触发漏洞,漏洞修复成功。
总结:
最后做下总结:
Plain Text可以看到漏洞的原理其实很简单,就是spring为了方便开发者跨系统调用数据,采用序列化的方式实现数据的通信,但是未考虑到可能存在的反序列化漏洞,在6.0版本中已经废除了HttpInvokerServiceExporter这个类,整个的调用流程并不复杂,很快就可以分析出来。漏洞的利用我们这里采用的是CC链,其实也可以采用其他链,可以根据加载的jar版本自行编写,当然最好用的还是ysoserial,另外当一个调用链不行不要放弃,多尝试几个就行。漏洞修复中能升级到最新版最好,但是当一个项目很大的时候,各个版本的依赖就是一个很麻烦的事情,多数情况下不能升级,但是漏洞还是要修复,这个时候就要手工修改源码进行修复,可以根据实际情况选择最简单的方式进行修复。