Как вы можете запустить Javascript, используя Rhino для Java в песочнице?

Часть нашего java-приложения должна запускать javascript, написанный не разработчиками. Эти не разработчики используют JavaScript для форматирования данных. (Простая логика и в основном конкатенация строк).

Мой вопрос заключается в том, как настроить выполнение этих сценариев, чтобы ошибки сценариев не оказывали серьезного негативного влияния на остальную часть приложения.

  • Нужно остерегаться бесконечных петель
  • Остерегайтесь появления новых тем.
  • Ограничить доступ к услугам и окружающей среде
    • Файловая система (пример: если недовольный сценарист решил удалить файлы)
    • База данных (то же самое, что удалить записи базы данных)

По сути, мне нужно настроить область JavaScript, чтобы включить только то, что им нужно, и не более.

6 ответов

Решение

Чтобы защититься от бесконечных циклов, вам нужно поместить его в отдельный процесс, чтобы его можно было убить.

Чтобы защититься от создания потоков, вам нужно расширить SecurityManager (реализация по умолчанию позволяет ненадежному коду получать доступ к группам потоков без полномочий root).

Безопасность Java позволяет вам запретить доступ к файловой системе.

Для ограничений базы данных вы можете использовать стандартную пользовательскую безопасность SQL, но она довольно слабая. В противном случае вам необходимо предоставить API, который обеспечивает соблюдение ваших ограничений.

Изменить: Я должен отметить, что версия Rhino, поставляемая с JDK6, была выполнена работа по безопасности, но не включает компилятор.

Чтобы защититься от бесконечных циклов, вы можете наблюдать за количеством команд во время выполнения скрипта (это работает только с интерпретированными скриптами, а не скомпилированными).

Этот пример в JavaDocs Rhino запрещает запуск сценария более десяти секунд:

 protected void observeInstructionCount(Context cx, int instructionCount)
 {
     MyContext mcx = (MyContext)cx;
     long currentTime = System.currentTimeMillis();
     if (currentTime - mcx.startTime > 10*1000) {
         // More then 10 seconds from Context creation time:
         // it is time to stop the script.
         // Throw Error instance to ensure that script will never
         // get control back through catch or finally.
         throw new Error();
     }
 }

Чтобы заблокировать доступ к классам и методам Java, взгляните на...

http://codeutopia.net/blog/2009/01/02/sandboxing-rhino-in-java/

Я только что наткнулся на это сообщение в блоге, которое, кажется, полезно для песочницы более или менее всего (не только Rhino):

http://calumleslie.blogspot.com/2008/06/simple-jvm-sandboxing.html

Если вы ищете только чистые функции JavaScript, вот решение, основанное на встроенной в JDK библиотеке Rhino без импорта сторонних библиотек:

  1. Узнайте имя класса фабрики обработчика сценариев JavaScript по ScriptEngineManager#getEngineFactories
  2. Загрузите класс фабрики обработчика сценариев в новый загрузчик классов, в котором JavaMembers или другие связанные классы будут игнорироваться.
  3. Вызовите #getScriptEngine для загруженной фабрики обработчиков сценариев и eval скриптов для возвращенной обработчика скриптов.

Если данный скрипт содержит Java-скрипт, загрузчик классов попытается загрузить JavaMembers или другие классы и вызвать исключение исключений для класса. Таким образом, вредоносные скрипты будут игнорироваться без выполнения.

Пожалуйста, прочтите файлы ConfigJSParser.java и ConfigJSClassLoader.java для более подробной информации:

https://github.com/webuzz/simpleconfig/tree/master/src/im/webuzz/config

Javascript является однопоточным и не может получить доступ к файловой системе, поэтому я не думаю, что вам нужно беспокоиться об этом. Я не уверен, есть ли способ установить тайм-аут для защиты от бесконечных циклов, но вы всегда можете создать поток (Java), который выполняет сценарий, а затем убить поток через столько времени.

Другие вопросы по тегам