开发者

Groovy/Grails: is there a way to make .evaluate() at all safe?

I have a situation where I need to determine eligiblity for for one object to "ride" another. The rules for the vehicles are wildly confusing, and I would like to be able to change them without restarting or recompiling my project.

This works but basically makes my security friends convulse and speak in tongues:

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]
}

So if I want to add the rule that you are only eligible for a certain vehicle if your "stuff" is "peggy" or "waffles" and your someNumber is greater than your anotherNumber all I have to do is this:

Make a new ConstraintByClosure with humanReadable = "peggy waffle some#>" (thats the human readable explanation) and then add this string as the closureText

{
   checkRider-&开发者_如何学Cgt;if(
     ["peggy","waffles"].contains(checkRider.stuff) &&
     checkRider.someNumber > checkRider.anotherNumber ) {
     return true  
   } 
   else { 
      return false
   }
}

Then I just make a VehicleConstraintLinker to link it up and voila.

My question is this: Is there any way to restrict what the GroovyShell can do? Can I make it unable to change any files, globals or database data? Is this sufficient?


Be aware that denying access to java.io and java.lang.Runtime in their various guises is not sufficient. There are many core libraries with a whole lot of authority that a malicious coder could try to exploit so you need to either white-list the symbols that an untrusted script can access (sandboxing or capability based security) or limit what anything in the JVM can do (via the Java SecurityManager). Otherwise you are vulnerable to confused deputy attacks.

provide security sandbox for executing scripts attempts to works with the GroovyClassLoader to provide sandboxing.

Sandboxing Java / Groovy / Freemarker Code - Preventing execution of specific methods discusses ways of sandboxing groovy, but not specifically at evaluate boundaries.

Groovy Scripts and JVM Security talks about sandboxing groovy scripts. I'm not a huge fan of the JVM security policy stuff since installing a security manager can affect a whole lot of other things in the JVM but it does provide a way of intercepting access to files and runtime stuff.

I don't know that either of the first two schemes have been exposed to widespread attack so I would be leery of deploying them without a thorough attack review. The JVM security manager has been subjected to widespread attack in a browser, and suffered many failures. It can be a good defense-in-depth, so I would not rely on it as the sole line of defense for anything precious.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜