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

http://www.myhack58.com/Article/html/3/62/2015/69493.htm

今年目前为止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方法如下: 
Commons Collections Java反序列化漏洞深入分析_第1张图片


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

Commons Collections Java反序列化漏洞深入分析_第2张图片

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


Commons Collections Java反序列化漏洞深入分析_第3张图片


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


Commons Collections Java反序列化漏洞深入分析_第4张图片

这样,这段恶意代码本质上就是利用反射调用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。该类的代码如下:


Commons Collections Java反序列化漏洞深入分析_第5张图片


简直完美。它的成员变量memberValue为Map 类型,并且在重写的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。

Commons Collections Java反序列化漏洞深入分析_第6张图片

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

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

Commons Collections Java反序列化漏洞深入分析_第7张图片

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

Commons Collections Java反序列化漏洞深入分析_第8张图片

如果未解析到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

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

Commons Collections Java反序列化漏洞深入分析_第9张图片

用法为:

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

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

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

使用

mvninstall -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()。

Commons Collections Java反序列化漏洞深入分析_第10张图片


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

Commons Collections Java反序列化漏洞深入分析_第11张图片

Jenkins

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

Jboss

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

受影响的JBoss产品有:

Commons Collections Java反序列化漏洞深入分析_第12张图片

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


你可能感兴趣的:(java)