转载

JDK7u21调用链分析

0×00.背景介绍

关于java反序列化漏洞,最为出名的大概应该是:15年的Apache Commons Collections 反序列化远程命令执行漏洞和 2016年Spring RMI反序列化漏洞 ,其中 15年的Apache Commons Collections 反序列化远程命令执行漏洞 影响范围包括:WebSphere、JBoss、Jenkins、WebLogic 和 OpenNMSd等。 近几年比较出名的: Jackson,FastJson

Java 十分受开发者喜爱的一点是其拥有完善的第三方类库,和满足各种需求的框架;但正因为很多第三方类库引用广泛,如果其中某些组件出现安全问题,那么受影响范围将极为广泛。本文我们将主要分析JDK7u21调用链。

0×01.准备阶段

之前的调用链基本都是围绕的Java第三方包中的一些内容,但是随着JDK7U21的出现,彻彻底底的说明了反序列化根本不需要使用第三方库的支持。 而且JDK7u21的利用过程十分精彩,使用HashSet,TemplatesImpl和AnnoationInvocationHandler,其中后两个调用链频繁的出现在Collections调用链中,也都是十分经典的调用链。

关于HashSet这个容器,实际上就是底层使用了Hash表来实现的,它不允许元素重复,但它不保证顺序,这是和List的最大区别。

这一篇文章中,小豹准备分析调试一下JDK7u21这个调用链。

这里面的代码是直接使用ysoserial项目生成,直接输出到jdk7u21.cer文件中,然后进行反序列化。

java -jar ysoserial.jar Jdk7u21 "open /Applications/Calculator.app" > jdk7u21.cer

JDK7u21调用链分析

注意这里的JDK版本。

./java -version

java version "1.7.0_21"

Java(TM) SE Runtime Environment (build 1.7.0_21-b12)

Java HotSpot(TM) 64-Bit Server VM (build 23.21-b01, mixed mode)

0×02.过程分析

当进行readObject操作的时候,发现它是一个HashSet,会直接调用HashSet的ReadObject。

JDK7u21调用链分析

在内部实现中使用了HashMap,这里在For循环中,会循环的进行反序列化,在ysoserial的payload中,实际上存储了2个对象,一个是恶意调用链TemplatesImpl,另一个是Proxy。所以这里的for循环会循环2次,每一次都put进HashMap中。 第一次反序列化是一个TemplatesImpl 然后put。

JDK7u21调用链分析

图中反序列化的e正是我们的TemplatesImpl,恶意代码存储在_bytecodes中。 然后进入put我们会发现,首先计算key的哈希,这个key就是我们上图中的e(TemplatesImpl),注意这个函数中还有个局部变量e,很容易混淆。 然后根据hash来计算在table中的索引。

JDK7u21调用链分析

由于现在第一次table中还没有数据,则e为空,不会进入到for循环,而是直接调用addEntry去添加元素。      

JDK7u21调用链分析

本次计算的hash索引都在上图中,后面会用到。然后put函数结束,回到第二层循环,这次反序列化的实际上是一个Proxy,这个Proxy用来代理TempLatesImpl,使用动态代理的时候会直接调用到Handler中的invoke函数。 回到第二层循环中

JDK7u21调用链分析

这里反序列化的结果实际上就是Proxy,payload中被强制转换成上图红线标注的类。然后进入put,来计算proxy的hash。这个proxy的handler是AnnoationInvocationHandler

JDK7u21调用链分析

进入hash函数,发现是调用hashcode。

JDK7u21调用链分析

这里面的k就是上面传进来的Proxy,这里会触发动态代理机制,进入到handler中的invoke方法。

JDK7u21调用链分析

原来是调用handler中的hashCodeImpl方法。

JDK7u21调用链分析

在hashCodeImpl方法中,首先获得handler中memberValues的迭代器。这个memberValues就是我们构造的hashmap,key为“f5a5a608”他的hashcode是0,value是templatesImpl恶意调用链,也就是我们第一次put进去的对象。

JDK7u21调用链分析

由于这个hashmap只有一个元素,所以迭代器这里只会循环一次,就出去了。所以0和X亦或,还是X。最终返回的是templatesImpl恶意调用链的hashcode。注意这里就是精华之处了。hashCodeImpl函数结束完毕,会逐层返回到put中的hash函数

JDK7u21调用链分析

你会惊奇的发现hash值和我们前面第一次put时候的hash一模一样。这就造成了hashset第一个元素的hash和第二个proxy的hash一样,于是他们获得的索引值i也就一样。

JDK7u21调用链分析

这里的i同样也是5。那现在和第一次执行put的时候完全情况就不一样了,第一次我们是由于table返回的e是空的,没有进入到循环中,直接进行add添加元素。这次i为5,正好e是TemplatesImpl对象。e不为空会进去到循环。

JDK7u21调用链分析

进入到循环之后,会调用key.equals函数。key的本质是proxy啊。会继续触发动态代理。
会去执行invoke,去调用equalsImpl方法。

JDK7u21调用链分析

equalsImpl方法会触发我们的恶意代码

JDK7u21调用链分析

首先获取所有的methods。然后循环的invoke。第一次invoke的函数是var5。我们可以看到第一个就是newTransformer函数。剩下就是TemplatesImpl子调用链的过程了,详细可以参考其他文章(关于TemplatesImpl调用链本文暂不调试)。newTransformer函数就会导致bytecodes的加载。

JDK7u21调用链分析

这个调用链的思路和collections差别挺大的。

原文  http://mp.weixin.qq.com/s?__biz=MzU5OTk1NDU5OQ==&mid=2247484193&idx=1&sn=a21130acc8d36da61d52620c1dc68912
正文到此结束
Loading...