概述
Java 反序列化漏洞,序列化就是把对象转换成字节流,便于保存在内存、文件、数据库中;反序列化即逆过程,由字节流还原成对象。
序列化与反序列化
|
|

|
|
最后输出为hello, world! This is a test!。
Commons Collections Java
Apache Commons Collections是一个扩展了Java标准库里的Collection结构的第三方基础库,它提供了很多强有力的数据结构类型并且实现了各种集合工具类。作为Apache开源项目的重要组件,Commons Collections被广泛应用于各种Java应用的开发。当然Java反序列化的问题就是出在org.apache.commons.collections这个库,这个库里的Package如下图所示:
|
|
里面主要涉及到的类有ConstantTransformer、InvokerTransformer等
整个poc的逻辑可以这么理解,构建了BeforeTransformerMap的键值对,为其赋值,利用TransformedMap的decorate方法,可以对Map数据结构的key,value进行transforme。
TransformedMap.decorate方法,预期是对Map类的数据结构进行转化,该方法有三个参数。第一个参数为待转化的Map对象,第二个参数为Map对象内的key要经过的转化方法(可为单个方法,也可为链,也可为空),第三个参数为Map对象内的value要经过的转化方法。
TransformedMap.decorate(目标Map, key的转化对象(单个或者链或者null), value的转化对象(单个或者链或者null));
poc中对BeforeTransformerMap的value进行转换,当BeforeTransformerMap的value执行完一个完整转换链,就完成了命令执行。
在进行反序列化时,我们会调用ObjectInputStream类的readObject()方法。如果被反序列化的类重写了readObject(),那么该类在进行反序列化时,Java会优先调用重写的readObject()方法。
结合前述Commons Collections的特性,如果某个可序列化的类重写了readObject()方法,并且在readObject()中对Map类型的变量进行了键值修改操作,并且这个Map变量是可控的,就可以实现我们的攻击目标了。
因此我们在poc中看见了下行的代码。
|
|
如果要实现一个可控的poc,需要对transformer链的构造进行理解。首先来看InvokerTransformer。
|
|
这样,这段恶意代码本质上就是利用反射调用Runtime() 执行了一段系统命令,作用等同于:
|
|
其对应关系如下:

|
|
JBoss
JBoss JMXInvokerServlet 反序列化
JBoss JMXInvokerServlet 存在反序列化漏洞。invoker/JMXInvokerServlet
可直接向http://192.168.111.145:8080/invoker/JMXInvokerServlet发送特殊构造的恶意代码,但是由于这个漏洞本身不回显,漏洞一开始并不好利用。后来大佬们通常先上传一个jar文件,然后通过加载Jar的方式进行异常封装,从而解决了回显的问题,具体poc如下:
|
|

JBoss CVE-2017-12149
JBoss /invoker/readonly 存在反序列化漏洞,即没有对数据进行任何的安全处理便进行了反序列化处理,造成了漏洞的形成。
访问服务器的/invoker/readonly页面,服务器返回500错误

这个漏洞的POC和前一个JBoss反序列化漏洞基本相同,所以这里就不贴代码了。
发送payload后服务端的日志如下:

Weblogic
因为weblogic会把异常直接打印到服务器端的控制台上,所以在jboss中通过异常封装回显的方法在weblogic上并不适用。但是weblogic有更方便的方法,weblogic是通过T3协议来传输序列化的类,那我们就可以通过T3协议来实现exploit和server的通信,因为weblogic的T3协议和WEB协议共用同一个端口,所以只要能访问weblogic,就可以利用,不需要加载远程类,因此对服务器能否连外网没有要求。
T3 协议
这里主要介绍下T3协议,不想看的可以跳过这里。T3 也称为丰富套接字,是BEA内部协议,功能丰富,可扩展性好。T3是多工双向和异步协议,经过高度优化,只使用一个套接字和一条线程。WebLogic Server 中的 RMI(远程方法调用) 通信使用 T3 协议在 WebLogic Server 和其他 Java 程序(包括客户端及其他 WebLogic Server 实例)间传输数据。服务器实例将跟踪所连接的每个 Java 虚拟机(Java Virtual Machine,简称 JVM),并创建单个 T3 连接以承担 JVM 的所有流量。请参阅“管理控制台联机帮助”中的配置 T3 协议。
使用T3协议向服务器发送数据:
第一行为t3加weblogic客户端的版本号。
weblogic服务器的返回数据为:
第一行为HELO:加weblogic服务器的版本号。
weblogic客户端与服务器发送的数据均以\n\n结尾。
经测试,使用
字符串作为T3的协议头发送给weblogic9、weblogic10g、weblogic11g、weblogic12c均合法。
在收到服务器的返回数据包后,就可了发送poc了。
poc的结构为:发送的数据长度 + weblogic的固定数据 + 反序列化的恶意代码 + 其他数据,具体如下:

即可触发漏洞。
CVE-2015-4852
这个版本没有任何的过滤,可直接利用。
CVE-2016-0638、CVE-2016-3510、CVE-2017-3248
因为weblogic的补丁是采用黑名单的过滤方式进行修补,容易有绕过的方式,下面就是大佬们的相关脚本:
|
|
WebSphere
CVE-2015-4852
WebSphere的反序列化漏洞发生的位置在SOAP的通信端口8880,使用的通信协议是https,发送的数据是XML格式的数据。

这个版本的Websphere没进行任何的过滤处理,直接进行了反序列化。
所以只要把恶意代码(和之前jboss的攻击方式一样)base64编码后通过SOAP协议发送至有漏洞的服务器即可命令执行。

Jenkins
CVE-2015-8103
想要使用这个漏洞利用Java应用,则需要找一个序列化对象的接收入口,并且这个Java应用使用了Commons Collections库。Jenkins是一个开源的持续集成软件。Jenkins启动后会开放多个端口,除了Web控制台之外还有一个CLI端口。CLI端口为随机的高端口,通过jenkins目录下的WEB-INF/jenkins-cli.jar程序可以和CLI端口进行通信。分析通信数据包发现存在base64编码的Java序列化特征值rO0AB。
jenkins-cli.jar在与CLI端口通信之前,会先HTTP GET请求一下jenkins的Web控制台,从响应包中解析出CLI的端口,再做后续通信。
从下图的head头部可以看到随机的序列化对象的接收入口。

X-Jenkins-CLI2-Port是采用SSL加密通信,而如果未解析到X-Jenkins-CLI2-Port头,则会解析X-Jenkins-CLI-Port头,此时Jenkins-CLI通信协议自动降为Version1,并且无SSL加密。
只要将恶意代码序列化后进行base64加密(base64编码后不能有换行),并代替掉之前截到的数据包中的base64字段即可。

由于此漏洞的命令执行结果也是不回显的,上传jar包的方式也只能打印到控制台,依旧不能解决回显问题。如果采用nslookup等方式来检测漏洞也常有漏网之鱼(如果服务器不能主动向外发包)。
总结
花了几天时间复现了这些著名的漏洞,颇有收获,稍微了解了各个中间件的一些情况以及的反序列化漏洞的触发方式。