commoncollections1反序列化调试(基础知识)

Java安全之commonscollections1链分析(一)

0x00 前言

本篇文章记录一下commoncollections1链反序列化执行命令的原理,由于涉及到的分析基础相对于URLDNS链略显复杂,这里先整理一下cc1链构造的知识基础。

0x01 前置知识

1.Transformer

这里可以看到Transformer是cc链中提供的一个接口,其中有一个方法叫做transform。

2.ConstantTransformer

看一下源码实现,这里可以看到ConstantTransformer实现了Transformer接口,并且重写了transform方法。实际就是把传递给ConstantTransformer的值封装一下返回。

3.InvokerTransformer

源码中InvokerTransformer构造方法用来赋值,重写的transform方法使用反射调用并执行命令,并返回执行结果。

4.ChainedTransformer

这里ChainedTransformer方法实际上做了链式操作,将一个执行完重写transform方法的返回值作为下一个执行transform方法的形参,最后返回链式操作的整体返回值。

为什么要介绍这些transformer的实现类呢,因为ysoserial就是通过这些Transformer实现类达到反射执行任意命令的实现。

看一下源码可知,红框第一部分声明了一个Transformer数组,包含一个ConstantTransformer,3个InvokerTransformer,最后一个ConstantTransformer无执行命令的意义,暂时不关注。这里将Runtime.getRuntime().exec("calc.exe")使用反射调用和链式组装实现了出来。

那么具体什么时候会触发回调每个Transformer的transform方法呢?

5.LazyMap.decorate(innerMap, transformerChain);

被修饰过的Map在调用get方法时,会触发transform回调.
我们看一下调用流程就大概明白了
LazyMap#decorate
public static Map decorate(Map map, Transformer factory) {
        return new LazyMap(map, factory);
    }

LazyMap类不能直接通过new来获取一个LazyMap,需要通过调用一个decorate方法生产一个LazyMap,第一个参数是被修饰的map,第二个参数是个Transfomer类型的

LazyMap#get
public Object get(Object key) {
        if (!super.map.containsKey(key)) {
            Object value = this.factory.transform(key);
            super.map.put(key, value);
            return value;
        } else {
            return super.map.get(key);
        }
    }
接下来看一下get方法,我们可以发现get方法首先判断了map集合是否有这个key,如果没有则调用this.factory的transform方法自己获取一个值,也就是这个时候可以触发transform方法,造成链式操作的执行,进而执行命令。换句话说我们需要通过反序列化入口点找一个可以调用LazyMap的get方法的链,进而命令执行。

0x03 后续

大概介绍了下cc1中构造链的基础后,下一篇我们将分析cc1链具体是怎么实现和触发的。
 
posted @ 2022-02-26 22:35  rain_code  阅读(81)  评论(0)    收藏  举报