En

Commons Collections Java反序列化漏洞深入分析

作者:深夜饮酒公布时间:2015-11-23阅读次数:158669评论:4

分享


0x01 背景



今年目前为止Java方面影响力最大的漏洞莫过于这段时间持续火热的CommonsCollections反序列化漏洞了。

 

在2015年11月6日FoxGlove Security安全团队的@breenmachine 发布了一篇长博客里,借用Java反序列化和Apache Commons Collections这一基础类库实现远程命令执行的真实案例来到人们的视野,各大Java Web Server纷纷躺枪,这个漏洞横扫WebLogic、WebSphere、JBoss、Jenkins、OpenNMS的最新版。而在将近10个月前, Gabriel Lawrence 和Chris Frohoff 就已经在AppSecCali上的一个报告里提到了这个漏洞利用思路。

 

目前,针对这个“2015年最被低估”的漏洞,各大受影响的Java应用厂商陆续发布了修复后的版本,Apache Commons Collections项目也对存在漏洞的类库进行了一定的安全处理。

 

0x02 从Apache CommonsCollections 说起

Apache Commons Collections是一个扩展了Java标准库里的Collection结构的第三方基础库,它提供了很多强有力的数据结构类型并且实现了各种集合工具类。作为Apache开源项目的重要组件,Commons Collections被广泛应用于各种Java应用的开发。

 

Commons Collections实现了一个TransformedMap类,该类是对Java标准数据结构Map接口的一个扩展。该类可以在一个元素被加入到集合内时,自动对该元素进行特定的修饰变换,具体的变换逻辑由Transformer类定义,Transformer在TransformedMap实例化时作为参数传入。

 

我们可以通过TransformedMap.decorate()方法,获得一个TransformedMap的实例。



当TransformedMap内的key 或者 value发生变化时,就会触发相应的Transformer的transform()方法。另外,还可以使用Transformer数组构造成ChainedTransformer。当触发时,ChainedTransformer可以按顺序调用一系列的变换。而Apache Commons Collections已经内置了一些常用的Transformer,其中InvokerTransformer类就是今天的主角。

 

它的transform方法如下:



这个transform(Object input) 中使用Java反射机制调用了input对象的一个方法,而该方法名是实例化InvokerTransformer类时传入的iMethodName成员变量:




也就是说这段反射代码中的调用的方法名和Class对象均可控。于是,我们可以构造一个恶意的Transformer链,借用InvokerTransformer.transform()执行任意命令,测试代码如下:

 


以上代码中ConstantTransformer,顾名思义可以将待变换的对象,变为一个常量,它的transform()方法代码如下:

 


这样,这段恶意代码本质上就是利用反射调用Runtime() 执行了一段系统命令,作用等同于:

 


也就是说,一个精心构造的TransformedMap,在其任意键值被修改时,可以触发变换,从而执行任意命令。

 

那如何进行远程命令执行的利用呢?

 

0x03 使用Java反序列化实现RCE


Java
序列化是指把Java对象转换为字节序列的过程;而Java反序列化是指把字节序列恢复为Java对象的过程。很多Java应用会使用序列化的方式传递数据,应用程序接收用户传入的一个字节序列,将其反序列化恢复为Java对象。

 

这里,如果Java应用没有对传入的序列化数据进行安全性检查,我们可以将恶意的TransformedMap序列化后,远程提交给Java应用,如果Java应用可以触发变换,即可成功远程命令执行。那如何让Java应用触发Transformer的变换呢?

 

在进行反序列化时,我们会调用ObjectInputStream类的readObject()方法。如果被反序列化的类重写了readObject(),那么该类在进行反序列化时,Java会优先调用重写的readObject()方法。

 

结合前述Commons Collections的特性,如果某个可序列化的类重写了readObject()方法,并且在readObject()中对Map类型的变量进行了键值修改操作,并且这个Map变量是可控的,就可以实现我们的攻击目标了。

 

于是找到了这个类:AnnotationInvocationHandler。该类的代码如下:

 


简直完美。它的成员变量memberValue为Map<String, Object> 类型,并且在重写的readObject()方法中有memberValue.setValue()的操作。

 

我们可以实例化一个AnnotationInvocationHandler类,将其成员变量memberValues赋值为精心构造的恶意TransformedMap对象。然后将其序列化,提交给未做安全检测的Java应用。Java应用在进行反序列化操作时,则会触发TransformedMap的变换函数,执行预设的命令。

      

0x04 Jenkins利用详细分析

想要使用这个漏洞利用Java应用,则需要找一个序列化对象的接收入口,并且这个Java应用使用了Commons Collections库。

 

从流量上分析,java序列化的数据为以标记(ac ed 00 05)开头,base64编码后的特征为rO0AB。从代码上分析,可以关注readObject()方法的使用点。

 

在foxglovesecurity.com发布的文章中,受影响的Java应用程序就已经包括了WebLogic, WebSphere, JBoss, Jenkins, OpenNMS等等。


以Jenkins为例,Jenkins是一个开源的持续集成软件。Jenkins启动后会开放多个端口,除了Web控制台之外还有一个CLI端口。CLI端口为随机的高端口,通过jenkins目录下的WEB-INF/jenkins-cli.jar程序可以和CLI端口进行通信。分析通信数据包发现存在base64编码的Java序列化特征值rO0AB。




 

       于是我们可以将数据包中Base64编码的序列化数据 替换为我们构造的恶意数据,发送到Jenkins服务端,实现远程命令执行。

 

       直接使用wireshark抓取这段通信包时,会发现它是经过SSL加密的密文数据。

 

 

分析数据包发现,jenkins-cli.jar在与CLI端口通信之前,会先HTTP GET请求一下jenkins的Web控制台,从响应包中解析出CLI的端口,再做后续通信。

 

 

       如果未解析到X-Jenkins-CLI2-Port头,则会解析X-Jenkins-CLI-Port头,此时Jenkins-CLI通信协议自动降为Version1,并且无SSL加密。

 

       于是,我们可以通过BurpSuit来篡改通信中的HTTP响应包,删除X-Jenkins-CLI2-Port响应头,从而使wireshark可以抓到明文数据包。

 

       设置命令行终端的HTTP代理,一般可以使用环境变量http_proxy

 

export http_proxy=http://proxyaddress:port

      

       这里对于Java程序,需要_JAVA_OPTIONS进行设置

 

export_JAVA_OPTIONS='-Dhttp.proxyHost=127.0.0.1 -Dhttp.proxyPort=8080'

 

       再执行jenkins-cli.jar,篡改数据包后,即可使用wireshark抓到明文的Jenkins-CLI通信包。

java -jar jenkins-cli.jar -shttp://x.x.x.x:8888/

 

@breenmachine给出的完整的利用脚本如下:



用法为:

./jenkins.pyhost port /path/to/payload

 

该利用脚本模拟了与Jenkins-CLI端口通信的过程,其中payload就是精心构造的AnnotationInvocationHandler类的序列化字节数据,我们可以使用github上的ysoserial工具进行构造。

 

gitclone --depth=50 --branch=master https://github.com/frohoff/ysoserial.gitfrohoff/ysoserial

 

使用

mvn install -DskipTests=true -Dmaven.javadoc.skip=true -B –V

进行编译,得到ysoserial-0.0.2-SNAPSHOT-all.jar。生成payload的命令如下:

 

java-jar ysoserial-0.0.2-SNAPSHOT-all.jar CommonsCollections1 'echo  123>> /tmp/tmp_test' > tmp_test.ser

 

0x05 影响与修复


Apache CommonsCollections

Apache Commons Collections在3.2.2版本中做了一定的安全处理,对这些不安全的Java类的序列化支持增加了开关,默认为关闭状态。涉及的类包括CloneTransformer,ForClosure, InstantiateFactory, InstantiateTransformer, InvokerTransformer, PrototypeCloneFactory,PrototypeSerializationFactory, WhileClosure。

 

如,InvokerTransformer类重写了序列化相关方法writeObject()和 readObject()。

 

 

如果没有开启不安全类的序列化,则会抛出UnsupportedOperationException异常:

 



Jenkins

       Jenkins 发布了安全公告,并且在1.638版本中修复了这个漏洞。

Jboss

       RedHat发布JBoss相关产品的解决方案:https://access.redhat.com/solutions/2045023

       受影响的JBoss产品有:

 


Weblogic

Oracle也发布了安全告警:http://www.oracle.com/technetwork/topics/security/alert-cve-2015-4852-2763333.html

 

影响版本包括:Oracle WebLogic Server, 10.3.6.0, 12.1.2.0, 12.1.3.0, 12.2.1.0 版本。

 

Websphere

IBM发布的Websphere安全公告:http://www-01.ibm.com/support/docview.wss?uid=swg21970575

 

受影响的 WebSphere Application Server 和 IBMWebSphere Application Server Hypervisor Edition 版本有:

 

Version8.5 and 8.5.5 Full Profile and Liberty Profile

Version8.0

Version7.0

 

0x06 相关CVE

 

CVE-2015-7501

CVE-2015-4852(Weblogic)

CVE-2015-7450(Websphere)

 

0x06 参考资料


foxglovesecblog: http://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability/#background

 

foxglovesecexploit: https://github.com/foxglovesec

 

ApacheCommons Collections Issue: https://issues.apache.org/jira/browse/COLLECTIONS-580


appseccali-2015-marshalling-pickles:http://www.slideshare.net/codewhitesec/exploiting-deserialization-vulnerabilities-in-java-54707478

 

RedHat JBoss products solution: https://access.redhat.com/solutions/2045023

 

评论留言

提交评论 您输入的漏洞名称有误,请重新输入