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

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

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

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

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

6 ответов


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

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

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

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

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


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

вот это пример в носороге JavaDocs чтобы предотвратить запуск скрипта более десяти секунд:

 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/


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

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


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

  1. узнайте имя Заводского класса javascript script engine с помощью ScriptEngineManager#getEngineFactories
  2. Load script engine factory class в новом загрузчике классов, в котором JavaMembers или другие связанные классы будут игнорироваться.
  3. вызов #getScriptEngine на загруженной фабрике движка сценария и сценарии eval на возвращенном движке сценариев.

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

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

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


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