我有一种情况需要确定一个对象“骑”另一个对象的可能性。车辆的规则非常令人困惑,我希望能够在不重新启动或重新编译项目的情况下更改它们。
这种方法很有效,但基本上让我的安全朋友感到厌烦并说方言:
class SweetRider{
String stuff
BigDecimal someNumber
BigDecimal anotherNumber
}
class SweetVehicle{
static hasMany=[constraintLinkers:VehicleConstraintLinker]
String vehicleName
Boolean canIRideIt(SweetRider checkRider){
def checkList = VehicleConstraintLinker.findAllByVehicle(this)
checkList.each{
def theClosureObject = it.closureConstraint
def iThinkINeedAShell = new GroovyShell()
def checkerThing = iThinkINeedAShell.evaluate(theClosureObject.closureText)
def result = checkerThing(checkRider)
return result
}
}
}
class VehicleConstraintLinker{
static belongsTo = [closureConstraint:ConstraintByClosure, vehicle:SweetVehicle]
}
class ConstraintByClosure{
String humanReadable
String closureText
static hasMany = [vehicleLinkers:VehicleConstraintLinker]
}
因此,如果我想添加一条规则,即如果你的“东西”是“peggy”或“华夫饼”并且你的someNumber大于你的另一个号码,那么你只能获得某辆车的资格,我所要做的就是:< / p>
使用humanReadable =“peggy waffle some#&gt;”创建一个新的ConstraintByClosure (这是人类可读的解释),然后将此字符串添加为closureText
{
checkRider->if(
["peggy","waffles"].contains(checkRider.stuff) &&
checkRider.someNumber > checkRider.anotherNumber ) {
return true
}
else {
return false
}
}
然后我只需要制作一个VehicleConstraintLinker来连接它并瞧。
我的问题是:有没有办法限制GroovyShell可以做什么?我可以让它无法更改任何文件,全局变量或数据库数据吗?这还够吗?
答案 0 :(得分:2)
请注意,拒绝以各种形式访问java.io
和java.lang.Runtime
是不够的。有许多核心库具有恶意编码器可以尝试利用的大量权限,因此您需要将不受信任的脚本可以访问的符号(沙盒或基于功能的安全性)列入白名单,或者限制JVM中的任何内容做(通过Java SecurityManager)。否则你很容易受到confused deputy attacks的攻击。</ p>
provide security sandbox for executing scripts尝试使用GroovyClassLoader
提供沙盒。
Sandboxing Java / Groovy / Freemarker Code - Preventing execution of specific methods讨论了沙箱groovy的方法,但没有具体讨论evaluate
边界。
Groovy Scripts and JVM Security讨论沙箱groovy脚本。我不是JVM安全策略的忠实粉丝,因为安装一个安全管理器会影响JVM中的许多其他东西,但它确实提供了拦截对文件和运行时内容的访问的方法。
我不知道前两个方案中的任何一个都受到了广泛的攻击,因此我会对没有彻底的攻击审查而部署它们持怀疑态度。 JVM安全管理器在浏览器中遭受了广泛的攻击,并遭遇了许多失败。它可以是一个很好的防御深度,所以我不会依赖它作为任何宝贵的防御的唯一防线。