[Java反序列化]JDK7U21原生反序列化利用链分析

写在前面

这段时间看了也跟踪了CC链,CB链,也跟踪调试了shiro的两个链子,XMLDecoder等,就用JDKK7U21原生反序列化利用链来暂时结束下最近的学习

利用链

LinkedHashSet.readObject()
  LinkedHashSet.add()
    ...
      TemplatesImpl.hashCode() (X)
  LinkedHashSet.add()
    ...
      Proxy(Templates).hashCode() (X)
        AnnotationInvocationHandler.invoke() (X)
          AnnotationInvocationHandler.hashCodeImpl() (X)
            String.hashCode() (0)
            AnnotationInvocationHandler.memberValueHashCode() (X)
              TemplatesImpl.hashCode() (X)
      Proxy(Templates).equals()
        AnnotationInvocationHandler.invoke()
          AnnotationInvocationHandler.equalsImpl()
            Method.invoke()
              ...
                TemplatesImpl.getOutputProperties()
                  TemplatesImpl.newTransformer()
                    TemplatesImpl.getTransletInstance()
                      TemplatesImpl.defineTransletClasses()
                        ClassLoader.defineClass()
                        Class.newInstance()
                          ...
                            MaliciousClass.<clinit>()
                              ...
                                Runtime.exec()

JDK7U21原生反序列化利用链分析

JDK7u21的核心点就是sun.reflect.annotation.AnnotationInvocationHandler,我们来看看AnnotationInvocationHandler这个方法

在这里插入图片描述

再看
在这里插入图片描述
可以很清楚的分析到equalsImpl这个方法
首先是利用反射获取this.type中的所有方法,之后进行遍历其中的方法并执行,如果我们把this.type赋为一个类,岂不是能调用里面的所有方法了,还记得那个TemplatesImpl对象么,我们就可以利用它来进行字节码的加载执行了
接下来我们发现在AnnotationInvocationHandler下面的invoke方法
在这里插入图片描述
这里我们其实发现,它实现了InvocationHandler
在这里插入图片描述
因此我们不难想到一个东西,动态代理,当调用equal方法时,就能实现完整的利用链,这里前辈们想到的是利用HashSet,因为HashSet中储存的对象不允许重复,所以在添加对象的时候,势必会涉及到比较操作。
可以看到在HashSetreadObject方法
在这里插入图片描述
这里调用了equal方法,但是从函数当中也能看出前提是他们的hash值相等
在这里插入图片描述
接下来我们就要让proxy对象的哈希值,等于TemplateImpl对象的哈希值,我们来看看hash的计算方法
我们来看看这里面的hash方法
在这里插入图片描述
这里我们发现主要是对象的hashCode方法
在这里插入图片描述
那我们就来看看这两个方法,首先是TemplatesImplhashcode方法,无法Debug调试跟踪,最后网上说是一个Native方法,难怪,但是我们不难发现每一次运行都在变,如何处理看后面分析
在这里插入图片描述
而看看我们代理的HashCode呢,会通过AnnotationInvocationHandlerinvoke ,进而调用到AnnotationInvocationHandlerhashCodeImpl
我们看看hashCodeImpl,它遍历memberValues中的每个keyvalue,计算 (127 * key.hashCode()) ^ value.hashCode()并求和

private int hashCodeImpl() {
        int var1 = 0;

        Entry var3;
        for(Iterator var2 = this.memberValues.entrySet().iterator(); var2.hasNext(); var1 += 127 * ((String)var3.getKey()).hashCode() ^ memberValueHashCode(var3.getValue())) {
            var3 = (Entry)var2.next();
        }

        return var1;
    }

再来看这个当只有一个keyvalue时,简化成 了(127 * key.hashCode()) ^ value.hashCode()在这里插入图片描述
因此不难想到当key.hashCode()等于0时,任何数异或0的结果仍是他本身,所以该哈希简化成value.hashCode()value 就是TemplateImpl对象时,这两个哈希就变成完全相等,因此我们只需要拿到一个hashCode是0的对象,网上给跑出来的是字符串f5a5a608

我们整理下利用思路

  1. 构造TemplatesImpl并将执行的字节码赋值
  2. 实例化一个HashMap,并添加keyf5a5a608,恶意构造好的TemplatesImpl加入到map中
  3. 利用反射实例化AnnotationInvocationHandler
  4. AnnotationInvocationHandler对象设置动态代理
  5. 实例化HashSet,并将TemplatesImpl设置的代理这两个对象放进去

流程跟踪

首先通过readObject调用,之后

在这里插入图片描述

跟进去看看,首先第一个对象Hash计算完添加

在这里插入图片描述

由于第二个对象hash与第一个相同,调用equal方法
在这里插入图片描述
通过动态代理触发equalsImpl的调用
在这里插入图片描述
接下来就是遍历Template里面的方法并通过反射执行,可以看到这里有执行newTransformer

在这里插入图片描述
调用getTransletInstance方法
在这里插入图片描述

继续跟踪调用defineTransletClasses方法
在这里插入图片描述

跟入defineClass
在这里插入图片描述
加载字节码
在这里插入图片描述
别忘了这里有一个验证加载的字节码的对象必须是class com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet的子类哦

在这里插入图片描述
实例化
在这里插入图片描述
成功弹出计算器
在这里插入图片描述

参考文章

动态代理
JavaThings/JDK7u21
【技术分享】JDK7u21反序列化
jdk7u21反序列化调试

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值