Security with Java Scripting (JRuby, Jython, Groovy, BeanShell, etc) - java

I'm looking to run some un-verified scripts (written in a yet-to-be-determined language, but needs to be Java-based, so JRuby, Groovy, Jython, BeanShell, etc are all candidates). I want these scripts to be able to do some things and restricted from doing other things.
Normally, I'd just go use Java's SecurityManager and be done with it. That's pretty simple and lets me restrict file and network access, the ability to shutdown the JVM, etc. And that will work well for the high level stuff I want to block off.
But there is some stuff I want to allow, but only via my custom API/library that I've providing. For example, I don't want to allow direct network access to open up a URLConnection to yahoo.com, but I am OK if it is done with MyURLConnection. That is - there is a set of methods/classes that I want to allow and then everything else I want to be off limits.
I don't believe this type of security can be done with the standard Java security model, but perhaps it can. I don't have a specific requirement for performance or flexibility in the scripting language itself (the scripts will be simple procedural calls to my API with basic looping/branching). So even a "large" overhead that checks a security check on every reflection call is fine by me.
Suggestions?

Disclaimer: I am not an expert on Java Security APIs, so there may be a better way to do this.
I work for Alfresco, Java-based Open Source Enterprise CMS, and we implemented something similar to what you describe. We wanted to allow scripting, but only to expose a subset of our Java APIs to the scripting engine.
We chose Rhino Engine for JavaScript scripting. It allows you to control which APIs are exposed to JavaScript, which allows us to choose which classes are available, and which are not. The overhead, according to our engineers, is on the order of 10%- not too bad.
In addition to this, and this may be relevant to you as well, on the Java side, we use Acegi (now Spring Security), and use AOP to give role-based control over which methods a certain user can call. That works pretty well for authorization. So in effect, a user accessing our app through JavaScript first has a restricted API available to him in the first place, and then that API can be restricted even further based on authorization. So you could use the AOP techniques to further restrict which methods can be called, thus allowing to expose this in other scripting languages, such as Groovy, etc. We are in the process of adding those as well, having the confidence that our underlying Java APIs protect users from unauthorized access.

You may be able to use a custom class loader that does vets linking to classes before delegating to its parent.
You can create your own permissions, check for those in your security sensitive APIs and then use AccessController.doPrivileged to restore appropriate privileges whilst calling the underlying API.
You need to make sure that the scripting engine itself is secure. The version of Rhino in the Sun JDK should be okay, but no guarantees. Obviously you need to make sure everything available to the script is secure.

In Groovy, you can do exactly what you mentioned. Actually very easy. You can easily limit permissions of untrusted scripts running in a trusted environment, allow usage of your own api, which in turn can do untrusted things.
http://www.chrismoos.com/2010/03/24/groovy-scripts-and-jvm-security/

Related

Can I trust Java SecurityManager sandbox?

I'm writing a JavaFX2 application that accepts arbitrary code to be loaded from remote locations. For me using a custom SecurityManager, ClassLoader and ProtectionDomain was the way to go. Unfortunately this seems to be the same setup that's used to sandbox applets, which has caused a lot of security exploits and that in turn has persuaded people to fear Java Web Plugin and removing it from their OS entirely.
Is Java sandbox a secure environment to run untrusted code onto, or is it just the Java Web Plugin as a whole to be insecure?
The security manager provides your app. with exactly as much protection as it provided the plug-in. Which was, given the security bugs, 'not much'.
It currently plugs the known security bugs (AFAIU). But as in any complex plug-in there are probably more, yet to be discovered, or possibly to be introduced in new versions or new APIs.
So basically, your code should go somewhat beyond a standard security manager, black-listing entire packages and (if need be) providing utility methods through which to perform activity normally handled by that package.
But then, that advice is the first point of a 20+ point list that I might be able to name 2 or 3 of the possible things an app. might need to guard against, in running untrusted code. Though that is not the question..
Is Java sandbox a secure environment to run untrusted code onto..
No. Java security might provide a good starting point for security against untrusted code, but it would need to be expanded specific to the app., and have other elements in order to be suited to the task required. Even then, there are the 'unknown security bugs' (in both the JRE as well as your own security efforts) to consider.

Advice for embedding a Java scripting language for debugging/remote admin

I have a fairly sophisticated server-side application which frequently requires me to see what is going on with its internals to debug and fix problems.
I've therefore embedded a Beanshell instance, which I can telnet into (normally over a ssh tunnel), but I'm wondering if there is a better way.
A few limitations:
No readline support, which I can get around by using 'rlwrap' on telnet, but its not ideal
Tab-completion of variables and methods would be really nice, but I haven't found a way to do this
Pre-defining variables (to access stuff I need to access frequently) doesn't seem to work, I have to pre-define functions instead
All-in-all its rather clunky, although Beanshell has the nice advantage that its a super-set of Java, so nobody needs to learn another programming language to use it.
I'm wondering if others have any experience with facilitating remote debugging/administration via a scripting language (Beanshell or otherwise), perhaps someone has found a better approach.
One of our application has a BeanShell interface that connects to our application over JMX with RMI+SSL.
You can indeed pre-define variables by calling Interpreter#set() before actually invoking the Interpreter.
Other than that, I agree with you on the "readline" like functionality. There is a project called java-readline (and BSH apparently ships with a plugin for it) that purports to provide functionality but I haven't investigated using it. It also requires a JNI library.
I've heard that people use Scala and Groovy to implement command line clients but as of now, I don't think the Scala API for embedding the interpreter is standardized yet. I also don't believe they support the "readline" features you're looking for.

How does Google App Engine sandbox work?

How does Google App Engine sandbox work?
What would I have to do to create my own such sandbox (to safely allow my clients to run their apps on my engine without giving them the ability to format my disk drive)? Is it just class loader magic, byte manipulation or something?
You would probably need a combination of a restrictive classloader and a thorough understanding of the Java Security Architecture. You would probably run your JVM with a very strict SecurityManager specified.
In the Java case, I think it's mostly done by restricting the available libraries. Since Java doesn't have pointer concept, and you can't upload natively compiled code (only JVM bytecode), you can't break out of the sandbox. Add some tight process scheduling, and you're done!
I guess The hardest part is to pick the libraries, to make it useful while staying safe.
In the Python case, they had to modify the VM itself, because it wasn't designed with safety in mind. Fortunately, they have Guido himself to do it.
to safely allow my clients to run their apps on my engine without giving them the ability to format my disk drive
This can be easily achieved using the Java Security Manager. Refer this answer for an example.

Limitations of Java desktop applications?

I come from a C/C++ background and now do a lot of C# stuff.
Lately I have become interested in doing some projects in Java since playing around with the Android SDK.
I know that Java apps run in a sandbox that can limit their access to the system.
In a desktop/server application environment what kind of things are restricted?
Java applications are much in a sandbox as .NET applications are in a sandbox. They both run on their respective virtual machines, and do have some limitations as to what they can do, but for the most part, they have a good deal of access to the system, including access to native code through certain calls.
You may be thinking about Java applets, which run inside a browser, and generally will be in a security sandbox that prevents access to the system resources such as local files. (This restriction can be circumvented by specifically granting access to the system to certain applets.)
Here's a section on Security Restrictions for applets from The Java Tutorials, which includes a list of restrictions placed on applets.
Typically desktop and server application run with security disabled. However, Java and the JVM still have a robust type system, so you can't for instance cast to types that an object was not created with, cannot access freed memory and can't run off the end of buffers.
For normal desktop and server apps, the limitations are not related to the sandbox concept (though you could use it to apply very fine-grained restrictions to e.g. user-submitted code) but to the platform-independant nature of Java. Basically, OS-specific stuff and hardware access usually can't be done in pure JAVA unless specifically adressed by the API library.
Examples are:
Windows registry
Windows system tray
Bluetooth
WLAN configuration
I think the main limitation you might see, is the ability to easily use the native system API's if you needed, for example if you needed to use a user32 or kernel32 API from java I think it is possible, however it is not an easy task to do, however in C# it is fairly easy thing to do.
Also if you have some legacy C/C++ dll's you can still use them in a C# application, while in java is still hard to do especially that in the worst case when your native code api has to use pointers, you can use unsafe mode in C# application to pass pointers and allocate fixed memory on stack ... etc.
but as mentioned above Java & C# in general are very much have the same limitations especially if you are targetting being platfrom independent.

Adding scripting security to an application

Let's say I have an existing application written in Java which I wish to add scripting support to. This is fairly trivial with Groovy (and just as trivial in .Net with any of the Iron range of dynamic languages).
As trivial as adding the support is, it raises a whole host of questions about script execution and security - and how to implement that security.
Has anyone come across any interesting articles/papers or have any insights into this that they'd like to share? In particular I'd be very interested in architectural things like execution contexts, script authentication, script signing and things along those lines... you know, the kind of stuff that prevents users from running arbitrary scripts they just happened to download which managed to screw up their entire application, whilst still allowing scripts to be useful and flexible.
Quick Edit
I've mentioned signing and authentication as different entities because I see them as different aspects of security.
For example, as the developer/supplier of the application I distribute a signed script. This script is legitimately "data destructive" by design. Such as it's nature, it should only be run by administrators and therefore the vast majority of users/system processes should not be able to run it. This being the case it seems to me that some sort of security/authentication context is required based on the actions the script performs and who is running that script.
script signing
Conceptually, that's just reaching into your cryptographic toolbox and using the tools that exist. Have people sign their code, validate the signatures on download, and check that the originator of the signature is trusted.
The hard(er) question is what makes people worthy of trust, and who gets to choose that. Unless your users are techies, they don't want to think about that, and so they won't set good policy. On the other hand, you'll probably have to let the users introduce trust [unless you want to go for an iPhone AppStore-style walled garden, which it doesn't sound like].
script authentication
How's this different from signing? Or, is your question just that: "what are the concepts that I should be thinking about here"?
The real question is of course: what do you want your users to be secured against? Is it only in-transit modification, or do you also want to make guarantees about the behavior of the scripts? Some examples might be: scripts can't access the file system, scripts can only access a particular subtree of the file system, scripts can't access the network, etc.
I think it might be possible [with a modest amount of work] to provide some guarantees about how scripts access the outside world if they were done in haskell and the IO monad was broken into smaller pieces. Or, possibly, if you had the scripts run in their own opaque monad with access to a limited part of IO. Be sure to remove access to unsafe functions.
You may also want to look at the considerations that went into the Java (applet) security model.
I hope this gives you something to think about.
You may have a look at the documentation on security:
http://groovy.codehaus.org/Security
Basically, you can use the usual Java Security Manager.
And beyond this, there's a sample application showing how you can introspect the code by analyzing its AST (Abstract Syntax Tree) at compile-time, so that you can allow / disallow certain code constructs, etc. Here's an example of an arithmetic shell showing this in action:
http://svn.groovy.codehaus.org/browse/groovy/trunk/groovy/groovy-core/src/examples/groovyShell

Categories