写在前面
Java Commons Collections的利用链也被称为cc链,是在学习反序列化漏洞必不可少的一个部分。希望能由简到繁来一起了解学习下它的利用。
前置知识(序列化/反序列化)
核心也就是:
writeObject
方法,即序列化类对象。
readObject
方法,即反序列化类对象。
注意:
- 反序列化类对象是不会调用该类构造方法
- serialVersionUID(根据这个版本号来判断序列化对象的发送者和接收着是否有与该序列化/反序列化过程兼容的类)
反序列化漏洞主要原因在于readObject方法中,因为我们可以自定义该方法,在反序列化时会自动调用该方法,从而可能造成意想不到的效果。
更多基础知识:java序列化/反序列化 学习笔记
Transformer
Transformer
是一个接口类,提供了一个对象转换方法transform
:
public interface Transformer {
public Object transform(Object input);
}
该接口的重要实现类有:ConstantTransformer
、invokerTransformer
、ChainedTransformer
、TransformedMap
。
ConstantTransformer
该类的关键代码如下:
package org.apache.commons.collections.functors;
import java.io.Serializable;
import org.apache.commons.collections.Transformer;
public class ConstantTransformer implements Transformer, Serializable {
/** 省略 **/
/** The closures to call in turn **/
private final Object iConstant;
/** 省略 **/
public ConstantTransformer(Object constantToReturn) {
super();
iConstant = constantToReturn;
}
public Object transform(Object input) {
return iConstant;
}
/** 省略 **/
}
可以看出传入对象不会经过任何改变直接返回。
eg:
package cc1;
import org.apache.commons.collections.functors.ConstantTransformer;
public class ConstantTranTest {
public static void main(String[] args) {
Object obj = Runtime.class;
ConstantTransformer transformer = new ConstantTransformer(obj);
System.out.println(transformer.transform(null));
}
}
//结果为class java.lang.Runtime
InvokerTransformer
InvokerTransformer
类transform
方法实现了类方法动态调用,即采用反射机制动态调用类方法(反射方法名、参数值均可控)并返回该方法执行结果。
该类的关键代码如下:
public class InvokerTransformer implements Transformer, Serializable {
/** 要调用的方法名称 */
private final String iMethodName;
/** 反射参数类型数组 */
private final Class[] iParamTypes;
/** 反射参数值数组 */
private final Object[] iArgs;
// 省去多余的方法和变量
public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {
super();
iMethodName = methodName;
iParamTypes = paramTypes;
iArgs = args;
}
public Object transform(Object input) {
if (input == null) {
return null;
}
try {
// 获取输入类的类对象
Class cls = input.getClass();
// 通过输入的方法名和方法参数,获取指定的反射方法对象
Method method = cls.getMethod(iMethodName, iParamTypes);
// 反射调用指定的方法并返回方法调用结果
return method.invoke(input, iArgs);
} catch (Exception ex) {
// 省去异常处理部分代码
}
}
}
eg:
package cc1;
import o