2009-02-09 7 views
11

Ich möchte einige nicht verifizierte Skripte ausführen (geschrieben in einer noch zu bestimmenden Sprache, muss aber Java-basiert sein, JRuby, Groovy, Jython, BeanShell usw. sind alle Kandidaten). Ich möchte, dass diese Skripts einige Dinge tun und von anderen Dingen abgehalten werden können.Sicherheit mit Java Scripting (JRuby, Jython, Groovy, BeanShell, usw.)

Normalerweise würde ich einfach Java SecurityManager verwenden und damit fertig sein. Das ist ziemlich einfach und lässt mich den Datei- und Netzwerkzugriff einschränken, die Möglichkeit, die JVM herunterzufahren, usw. Und das wird gut für die High-Level-Sachen funktionieren, die ich blockieren möchte.

Aber es gibt einige Sachen, die ich erlauben will, aber nur über meine benutzerdefinierte API/Bibliothek, die ich zur Verfügung stelle. Zum Beispiel möchte ich keinen direkten Netzwerkzugriff erlauben, um eine URLConnection zu yahoo.com zu öffnen, aber ich bin OK, wenn es mit MyURLConnection gemacht wird. Das ist - es gibt eine Reihe von Methoden/Klassen, die ich zulassen will und dann alles andere, was ich nicht tun will.

Ich glaube nicht, dass diese Art von Sicherheit mit dem Standard-Java-Sicherheitsmodell durchgeführt werden kann, aber vielleicht kann es. Ich habe keine spezielle Anforderung für Leistung oder Flexibilität in der Skriptsprache selbst (die Skripts sind einfache prozedurale Aufrufe an meine API mit grundlegenden Schleifen/Verzweigungen). Selbst ein "großer" Overhead, der bei jedem Reflection Call eine Sicherheitskontrolle prüft, ist für mich in Ordnung.

Vorschläge?

Antwort

4

Haftungsausschluss: Ich bin kein Experte für Java-Sicherheits-APIs, daher könnte es einen besseren Weg geben, dies zu tun.

Ich arbeite für Alfresco, Java-basierte Open Source Enterprise CMS, und wir haben etwas ähnliches wie Sie beschrieben implementiert. Wir wollten Scripting zulassen, aber nur eine Teilmenge unserer Java-APIs für die Scripting-Engine verfügbar machen.

Wir haben uns für Rhino Engine für JavaScript Scripting entschieden. Sie können steuern, welche APIs JavaScript ausgesetzt sind. Dadurch können Sie auswählen, welche Klassen verfügbar sind und welche nicht. Der Overhead liegt laut unseren Ingenieuren in der Größenordnung von 10% - nicht schlecht.

Zusätzlich dazu, und dies könnte auch für Sie relevant sein, verwenden wir auf der Java-Seite Acegi (jetzt Spring Security) und verwenden AOP, um rollenbasierte Kontrolle darüber zu geben, welche Methoden ein bestimmter Benutzer aufrufen kann . Das funktioniert ziemlich gut für die Autorisierung. Ein Benutzer, der zuerst über JavaScript auf unsere App zugreift, hat also zunächst eine eingeschränkte API zur Verfügung, die dann aufgrund der Autorisierung noch weiter eingeschränkt werden kann. Sie können also die AOP-Techniken verwenden, um die zu verwendenden Methoden weiter einzuschränken, so dass Sie diese auch in anderen Skriptsprachen wie Groovy usw. verfügbar machen können. Wir sind dabei, diese auch hinzuzufügen und vertrauen dabei auf unser zugrunde liegendes Java APIs schützen Benutzer vor unbefugtem Zugriff.

+0

Danke - das ist wirklich hilfreich. Übrigens - der Anwendungsfall für mich ist es, Leuten zu erlauben, Skripte für ihre Belastungstests hochzuladen, die auf http://browsermob.com laufen. Ich habe Rhino nicht angeschaut, aber das hört sich so an, als könnte es funktionieren, solange es keinen direkten Zugriff auf die Java-APIs wie Groovy erlaubt. –

+0

Ja - Sie haben dort mehr Kontrolle, was aus Sicherheitsgründen gut ist. Möglicherweise müssen Sie Wrapper für bestimmte APIs erstellen und dann diese Objekte verfügbar machen. Zum Beispiel haben wir eine Workflow-Engine und haben ein Workflow-Objekt erstellt, das wir dann JavaScript zur Verfügung gestellt haben, wodurch gesteuert wird, was Sie tun können. –

+0

Quick-Follow-up: Wie haben Sie sichergestellt, dass die Variable Packages nicht zugänglich war? Siehe http://codeutopia.net/blog/2009/01/02/sandboxing-rhino-in-java/ –

3

Möglicherweise können Sie einen benutzerdefinierten Klassenlader verwenden, der Tierärzte mit Klassen verbindet, bevor er an seine Eltern delegiert.

Sie können Ihre eigenen Berechtigungen erstellen, nach denen in Ihren sicherheitsrelevanten APIs suchen und dann AccessController.doPrivileged verwenden, um beim Aufruf der zugrunde liegenden API die entsprechenden Berechtigungen wiederherzustellen.

Sie müssen sicherstellen, dass die Skript-Engine selbst sicher ist. Die Version von Rhino im Sun JDK sollte in Ordnung sein, aber keine Garantien. Natürlich müssen Sie sicherstellen, dass alles, was für das Skript verfügbar ist, sicher ist.

+0

Tom - danke für die Tipps. Klingt, als müsste ich das Java-Sicherheitsmodell noch ein bisschen genauer recherchieren - ich war mir nicht bewusst, doPriveleged –

0

In Groovy können Sie genau das tun, was Sie erwähnt haben. Eigentlich sehr einfach. Sie können die Berechtigungen von nicht vertrauenswürdigen Skripten, die in einer vertrauenswürdigen Umgebung ausgeführt werden, problemlos einschränken und die Verwendung Ihrer eigenen API erlauben, was wiederum nicht vertrauenswürdige Dinge bewirken kann.

http://www.chrismoos.com/2010/03/24/groovy-scripts-and-jvm-security/