Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to block access to some classes, when executing groovy scripts from java?

I'm pretty new to groovy, and scripting in java generally, and I really hope there is a simple solution for my problem. In our application, the users can execute groovy scripts which they write themselves, and we need to control what those scripts can and can not do. I read a lot of stuff about sandboxing groovy, but either I am looking at wrong places or I am overlooking the obvious. To make it simple, I have a small example which demonstrates the problem. This is my class loader which should prevent java.lang.System from being loaded and available to scripts:

public class MyClassLoader extends ClassLoader {

    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        if (name.startsWith("java.lang.System")) {
            throw new ClassNotFoundException("Class not found: " + name);
        }
        return super.loadClass(name);
    }
}

And this is a simple program that tries to call System.currentTimeMillis():

public static void main(String[] args) {
    String code = "java.lang.System.currentTimeMillis();";
    ClassLoader classLoader = new MyClassLoader();
    Thread.currentThread().setContextClassLoader(classLoader);

    GroovyShell shell = new GroovyShell();
    Script script = shell.parse(code);
    Object result = script.run();
    log.debug(result);
}

MyClassLoader throws exceptions for java.lang.SystemBeanInfo and java.lang.SystemCustomizer, but the code executes. Same thing happens if I use javax.script classes:

ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("Groovy");
Object o = engine.eval(code);
log.debug(o);

And if I try it with JavaScript engine, it works as expected (just replace "Groovy" with "JavaScript" in the above example).

Can anyone help me with this? BTW, I'm using groovy-all-1.8.8.jar, with jdk1.7.0_55.

Thanks

like image 254
Predrag Maric Avatar asked Sep 24 '14 12:09

Predrag Maric


People also ask

Where are Groovy classes and scripts stored?

Groovy classes and scripts are usually stored in.groovy files Scripts contain Groovy statements without any class declaration. Scripts can also contain method definitions outside of class definitions. It can be compiled and fully integrated with traditional Java application.

What is the groovyscriptengine class?

The GroovyScriptEngine class is particularly for those applications which rely on the reloading of a script and its dependencies. Although we have these additional features, the implementation has only a few small differences:

What is groovy used for in Java?

Groovy source code gets compiled into Java Bytecode so it can run on any platform that has JRE is installed. Groovy also performs a lot of tasks behind the scene that makes it more agile and dynamic. Groovy language can be used as a scripting language for the Java platform.

How to install Groovy on Windows?

Note: You can also install Groovy using the Zip file or as an Eclipse IDE. In this Groovy tutorial, we will stick to Windows Installer Step 3) Launch the downloaded installer. Select language and click OK Step 4) Launch. In welcome screen, click NEXT Step 5) Agree with the license terms Step 6) Select components you want to install and click NEXT


2 Answers

I can recommend Groovy Sandbox for this purpose. In contrast to SecureASTCustomizer it will check if an execution is allowed dynamically at runtime. It intercepts every method call, object allocations, property/attribute access, array access, and so on - and you thus have a very fine grained control on what you allow (white-listing).

Naturally the configuration on what is allowed is very important. For example you may want to allow using Strings and use methods like substring, but probably not the execute method on String, which could be exploited with something like 'rm -R ~/*'.execute(). Creating a configuration that is really safe is a challenge, and it is more difficult the more you allow.

Downside of the Groovy Sandbox is that the code must run with the interceptor registered and you will have a performance penalty during execution.

This image [1] shows an example from a project where we used Groovy Sandbox for Groovy code entered by the user. The code is run to valide the script - so if the statement there would actually be executed as part of it, the application would have exited before I could do the screenshot ;)

Example from a project where we used Groovy Sandbox

like image 185
stempler Avatar answered Sep 30 '22 00:09

stempler


Perhaps you'd be interested in using a SecureASTCustomizer in conjunction with a CompilerConfiguration. If you are concerned with security, an explicit white list might be better than a black list.

def s = new SecureASTCustomizer()
s.importsWhiteList = [ 'a.legal.Klass', 'other.legal.Klass' ]

def c = new CompilerConfiguration()   
c.addCompilationCustomizers(s)

def sh = new GroovyShell(c)

Take a look at that class, it contains a lot of options that are ready to use.

like image 42
emesx Avatar answered Sep 30 '22 01:09

emesx