Groovy/Grails: есть ли способ сделать .evaluate() безопасным?

У меня возникла ситуация, когда мне нужно определить право одного объекта на «езду» на другом. Правила для транспортных средств дико запутаны, и я хотел бы иметь возможность менять их без перезапуска или перекомпиляции моего проекта.

Это работает, но в основном заставляет моих друзей по безопасности биться в конвульсиях и говорить на языках:

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

Итак, если я хочу добавить правило, согласно которому вы имеете право на определенное транспортное средство только в том случае, если ваши «вещи» — это «пегги» или «вафли», а ваш someNumber больше, чем ваш otherNumber, все, что мне нужно сделать, это следующее:

Создайте новый ConstraintByClosure с humanReadable = "peggy waffle some#>" (это удобочитаемое объяснение), а затем добавьте эту строку в качестве closureText

{
   checkRider->if(
     ["peggy","waffles"].contains(checkRider.stuff) &&
     checkRider.someNumber > checkRider.anotherNumber ) {
     return true  
   } 
   else { 
      return false
   }
}

Затем я просто создаю VehicleConstraintLinker, чтобы связать его, и вуаля.

У меня такой вопрос: есть ли способ ограничить возможности GroovyShell? Могу ли я сделать так, чтобы он не мог изменять какие-либо файлы, глобальные переменные или данные базы данных? Этого достаточно?


person Mikey    schedule 21.07.2011    source источник
comment
Возможно связанный вопрос: stackoverflow.com/q/6488368/6509   -  person tim_yates    schedule 22.07.2011


Ответы (1)


Имейте в виду, что запрета доступа к java.io и java.lang.Runtime в их различных обличьях недостаточно. Существует много основных библиотек с большими полномочиями, которые злоумышленник может попытаться использовать, поэтому вам нужно либо внести в белый список символы, к которым может получить доступ ненадежный скрипт (песочница или безопасность на основе возможностей), либо ограничить то, что может делать что угодно в JVM. сделать (через Java SecurityManager). В противном случае вы уязвимы для запутанных атак депутатов.

предоставить изолированную программную среду безопасности для выполнения сценариев пытается работать с GroovyClassLoader для обеспечения изолированной программной среды.

Изолирующая среда Java / Groovy / Freemarker Code — предотвращение выполнения определенных методы обсуждает способы песочницы groovy, но не конкретно на evaluate границах.

Сценарии Groovy и безопасность JVM рассказывает о песочнице groovy скрипты. Я не большой поклонник политики безопасности JVM, поскольку установка менеджера безопасности может повлиять на множество других вещей в JVM, но она предоставляет способ перехвата доступа к файлам и материалам во время выполнения.

Я не знаю, подвергалась ли какая-либо из первых двух схем широкомасштабным атакам, поэтому я бы с опаской относился к их развертыванию без тщательного анализа атак. Диспетчер безопасности JVM подвергся широкомасштабной атаке в браузере и потерпел множество сбоев. Это может быть хорошая эшелонированная защита, поэтому я бы не стал полагаться на нее как на единственную линию защиты для чего-то ценного.

person Mike Samuel    schedule 22.07.2011