CommonsCollections2
环境搭建
- Commons Collections 4.0
- JDK8
- ysoserial-master
基础知识
1.Java字节码加载过程
学习一下p神的文章:
-
ClassLoader#loadClass
:从已加载的类缓存,父加载器等位置寻找类,在前面没有找到的情况下,执行findClass
-
ClassLoader#findClass
:根据基础URL指定的方式来加载类的字节码可能的来源:
- 本地文件系统
- jar包
- 远程http服务器
-
ClassLoader#defineClass
:处理字节码,转成真正的类
2.TemplatesImpl加载字节码
TemplatesImpl 是 Java 中用于处理 XSLT(Extensible Stylesheet Language Transformations)模板的类。XSLT 是一种用于将 XML 数据转换为其他格式的语言,例如 HTML 或文本。
TemplatesImpl
类通常用于将 XSLT 模板编译成可重用的Transformer
对象,以便在应用程序中进行 XML 转换操作
简单来说,TemplatesImpl中调用了defineClass,从而可以实现动态加载Java字节码
代码如下
public final class TemplatesImpl implements Templates, Serializable{
...
static final class TransletClassLoader extends ClassLoader {
TransletClassLoader(ClassLoader parent) {
super(parent);
}
/**
* Access to final protected superclass member from outer class.
*/
Class defineClass(final byte[] b) {
return defineClass(null, b, 0, b.length);
}
}
...
}
TemplatesImpl Gadget Chain
捋一下TemplatesImpl
加载字节码的Gadget Chain
/*
TemplatesImpl.newTransformer()
TemplatesImpl.getTransletInstance()
TemplatesImpl.defineTransletClasses()
ClassLoader.defineClass() => 加载字节码
*/
重点贴一下defineTransletClasses()
private void defineTransletClasses()
throws TransformerConfigurationException {
if (_bytecodes == null) {
ErrorMsg err = new ErrorMsg(ErrorMsg.NO_TRANSLET_CLASS_ERR);
throw new TransformerConfigurationException(err.toString());
}
TransletClassLoader loader = (TransletClassLoader)
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return new TransletClassLoader(ObjectFactory.findClassLoader()); // find
}
});
try {
final int classCount = _bytecodes.length;
_class = new Class[classCount];
if (classCount > 1) {
_auxClasses = new Hashtable();
}
for (int i = 0; i < classCount; i++) {
_class[i] = loader.defineClass(_bytecodes[i]); // 加载字节码
final Class superClass = _class[i].getSuperclass();
// Check if this is the main class
if (superClass.getName().equals(ABSTRACT_TRANSLET)) {
_transletIndex = i;
}
else {
_auxClasses.put(_class[i].getName(), _class[i]);
}
}
if (_transletIndex < 0) {
ErrorMsg err= new ErrorMsg(ErrorMsg.NO_MAIN_TRANSLET_ERR, _name);
throw new TransformerConfigurationException(err.toString());
}
}
catch (ClassFormatError e) {
ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_CLASS_ERR, _name);
throw new TransformerConfigurationException(err.toString());
}
catch (LinkageError e) {
ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_OBJECT_ERR, _name);
throw new TransformerConfigurationException(err.toString());
}
}
CC2 Gadget Chain
/*
Gadget chain:
ObjectInputStream.readObject()
PriorityQueue.readObject()
{
PriorityQueue.heapify()
PriorityQueue.Siftdown()
PriorityQueue.siftDownUsingComparator()
}
TransformingComparator.compare()
InvokerTransformer.transform()
Method.invoke()
// TemplatesImpl加载字节码
Runtime.exec()
*/
调试分析
- 反序列化,进入
PriorityQueue
的readObject
函数
大致流程是取ObjectInputStream
对象进行处理,跟进heapify()
heapify()
- 再进入
siftDown
- 由于
comparator
非空,进入siftDownUsingComparator()
看起来是个二分的过程,进入comparator.compare
compare
,可以发现有熟悉的transform
函数
-
典,java反射执行类方法
-
基于反射机制,使用
TemplatesImpl
动态加载恶意Java字节码