Groovy-代码调用

目录

简介

基于jvm的一个语言,可被java代码调用。

漏洞原理

groovy作为一个语言,可以很轻松的进行命令执行

class test {
    static void main(args){
        def cmd = "calc";
        println "${cmd.execute()}";
    }
}

所以在代码审计过程中,存在groovy代码可控或者可以上传恶意groovy脚本的情况,就很有可能导致rce。

GroovyShell

解析groovy表达式

import groovy.lang.GroovyShell;

public class GroovyShellExample {
    public static void main( String[] args ) {
        GroovyShell groovyShell = new GroovyShell();
        groovyShell.evaluate("\"calc\".execute()");
    }
}

或者运行恶意groovy脚本

public class GroovyShellExample {
    public static void main( String[] args ) throws Exception {
        GroovyShell groovyShell = new GroovyShell();
        #test.groovy: println "whoami".execute().text
        Script script = groovyShell.parse(new File("src/test.groovy"));
        script.run();
    }
}

GroovyScriptEngine

从文件系统、URL、数据库等等加载groovy脚本。感觉和GroovyShell加载groovy脚本差不多。

import groovy.lang.Binding;
import groovy.util.GroovyScriptEngine;

public class GroovyScriptEngineExample {
    public static void main(String[] args) throws Exception {
        GroovyScriptEngine groovyScriptEngine = new GroovyScriptEngine("");
        groovyScriptEngine.run("src/test.groovy",new Binding());
    }
}

GroovyClassLoader

GroovyClassLoader是一个定制的类装载器,负责解释加载Java类中用到的Groovy类。

//从文本中获取Groovy类
GroovyClassLoader groovyClassLoader = new GroovyClassLoader();
Class aClass = groovyClassLoader.parseClass("class GroovyTest {n" +
"    static void main(args){n" +
"        println "${'whoami'.execute().text}"n" +
"n" +
"    }n" +
"}");
GroovyObject groovyObject = (GroovyObject) aClass.newInstance();
groovyObject.invokeMethod("main", "");

//从文件中获取Groovy类
GroovyClassLoader groovyClassLoader = new GroovyClassLoader();
Class aClass = groovyClassLoader.parseClass(new File("src/main/java/ysoserial/vulndemo/GroovyTest.groovy"));
GroovyObject object = (GroovyObject) aClass.newInstance();
object.invokeMethod("main", "");

ScriptEngine

ScriptEngine是一个脚本引擎管理器,它支持装载groovy引擎来执行groovy代码。

//文本
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

public class ScriptEngineExample {
    public static void main( String[] args ) throws Exception {
        ScriptEngine groovyEngine = new ScriptEngineManager().getEngineByName("groovy");
        groovyEngine.eval("\"calc\".execute()");
    }
}

//脚本
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.io.BufferedReader;
import java.io.FileReader;

public class ScriptEngineExample {
    public static void main( String[] args ) throws Exception {
        ScriptEngine groovyEngine = new ScriptEngineManager().getEngineByName("groovy");
        String code = readfile("src/test.groovy");
        groovyEngine.eval(code);
    }

    public static String readfile(String filename) throws Exception {
        BufferedReader in = new BufferedReader(new FileReader(filename));
        String string = "";
        String str;
        while ((str = in.readLine()) != null) {
            string = string + str;
        }
        return string;
    }
}

关键字

new GroovyShell()
new GroovyScriptEngine
new GroovyClassLoader
getEngineByName("groovy")